Fix FastISel to recognize that the last block in the function does
[oota-llvm.git] / lib / CodeGen / SelectionDAG / FastISel.cpp
1 ///===-- FastISel.cpp - Implementation of the FastISel class --------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains the implementation of the FastISel class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Instructions.h"
15 #include "llvm/CodeGen/FastISel.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18 #include "llvm/Target/TargetInstrInfo.h"
19 using namespace llvm;
20
21 /// SelectBinaryOp - Select and emit code for a binary operator instruction,
22 /// which has an opcode which directly corresponds to the given ISD opcode.
23 ///
24 bool FastISel::SelectBinaryOp(Instruction *I, ISD::NodeType ISDOpcode,
25                               DenseMap<const Value*, unsigned> &ValueMap) {
26   unsigned Op0 = ValueMap[I->getOperand(0)];
27   unsigned Op1 = ValueMap[I->getOperand(1)];
28   if (Op0 == 0 || Op1 == 0)
29     // Unhandled operand. Halt "fast" selection and bail.
30     return false;
31
32   MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
33   if (VT == MVT::Other || !VT.isSimple())
34     // Unhandled type. Halt "fast" selection and bail.
35     return false;
36
37   unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), ISDOpcode, Op0, Op1);
38   if (ResultReg == 0)
39     // Target-specific code wasn't able to find a machine opcode for
40     // the given ISD opcode and type. Halt "fast" selection and bail.
41     return false;
42
43   // We successfully emitted code for the given LLVM Instruction.
44   ValueMap[I] = ResultReg;
45   return true;
46 }
47
48 bool FastISel::SelectGetElementPtr(Instruction *I,
49                                    DenseMap<const Value*, unsigned> &ValueMap) {
50   // TODO: implement me
51   return false;
52 }
53
54 BasicBlock::iterator
55 FastISel::SelectInstructions(BasicBlock::iterator Begin, BasicBlock::iterator End,
56                              DenseMap<const Value*, unsigned> &ValueMap) {
57   BasicBlock::iterator I = Begin;
58
59   for (; I != End; ++I) {
60     switch (I->getOpcode()) {
61     case Instruction::Add: {
62       ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
63       if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
64     }
65     case Instruction::Sub: {
66       ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
67       if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
68     }
69     case Instruction::Mul: {
70       ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
71       if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
72     }
73     case Instruction::SDiv:
74       if (!SelectBinaryOp(I, ISD::SDIV, ValueMap)) return I; break;
75     case Instruction::UDiv:
76       if (!SelectBinaryOp(I, ISD::UDIV, ValueMap)) return I; break;
77     case Instruction::FDiv:
78       if (!SelectBinaryOp(I, ISD::FDIV, ValueMap)) return I; break;
79     case Instruction::SRem:
80       if (!SelectBinaryOp(I, ISD::SREM, ValueMap)) return I; break;
81     case Instruction::URem:
82       if (!SelectBinaryOp(I, ISD::UREM, ValueMap)) return I; break;
83     case Instruction::FRem:
84       if (!SelectBinaryOp(I, ISD::FREM, ValueMap)) return I; break;
85     case Instruction::Shl:
86       if (!SelectBinaryOp(I, ISD::SHL, ValueMap)) return I; break;
87     case Instruction::LShr:
88       if (!SelectBinaryOp(I, ISD::SRL, ValueMap)) return I; break;
89     case Instruction::AShr:
90       if (!SelectBinaryOp(I, ISD::SRA, ValueMap)) return I; break;
91     case Instruction::And:
92       if (!SelectBinaryOp(I, ISD::AND, ValueMap)) return I; break;
93     case Instruction::Or:
94       if (!SelectBinaryOp(I, ISD::OR, ValueMap)) return I; break;
95     case Instruction::Xor:
96       if (!SelectBinaryOp(I, ISD::XOR, ValueMap)) return I; break;
97
98     case Instruction::GetElementPtr:
99       if (!SelectGetElementPtr(I, ValueMap)) return I;
100       break;
101
102     case Instruction::Br: {
103       BranchInst *BI = cast<BranchInst>(I);
104
105       // For now, check for and handle just the most trivial case: an
106       // unconditional fall-through branch.
107       if (BI->isUnconditional()) {
108          MachineFunction::iterator NextMBB =
109            next(MachineFunction::iterator(MBB));
110          if (NextMBB != MF->end() &&
111              NextMBB->getBasicBlock() == BI->getSuccessor(0)) {
112           MBB->addSuccessor(NextMBB);
113           break;
114         }
115       }
116
117       // Something more complicated. Halt "fast" selection and bail.
118       return I;
119     }
120     default:
121       // Unhandled instruction. Halt "fast" selection and bail.
122       return I;
123     }
124   }
125
126   return I;
127 }
128
129 FastISel::~FastISel() {}
130
131 unsigned FastISel::FastEmit_(MVT::SimpleValueType, ISD::NodeType) {
132   return 0;
133 }
134
135 unsigned FastISel::FastEmit_r(MVT::SimpleValueType, ISD::NodeType,
136                               unsigned /*Op0*/) {
137   return 0;
138 }
139
140 unsigned FastISel::FastEmit_rr(MVT::SimpleValueType, ISD::NodeType,
141                                unsigned /*Op0*/, unsigned /*Op0*/) {
142   return 0;
143 }
144
145 unsigned FastISel::FastEmitInst_(unsigned MachineInstOpcode,
146                                     const TargetRegisterClass* RC) {
147   MachineRegisterInfo &MRI = MF->getRegInfo();
148   const TargetInstrDesc &II = TII->get(MachineInstOpcode);
149   unsigned ResultReg = MRI.createVirtualRegister(RC);
150
151   MachineInstr *MI = BuildMI(*MF, II, ResultReg);
152
153   MBB->push_back(MI);
154   return ResultReg;
155 }
156
157 unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode,
158                                   const TargetRegisterClass *RC,
159                                   unsigned Op0) {
160   MachineRegisterInfo &MRI = MF->getRegInfo();
161   const TargetInstrDesc &II = TII->get(MachineInstOpcode);
162   unsigned ResultReg = MRI.createVirtualRegister(RC);
163
164   MachineInstr *MI = BuildMI(*MF, II, ResultReg);
165   MI->addOperand(MachineOperand::CreateReg(Op0, false));
166
167   MBB->push_back(MI);
168   return ResultReg;
169 }
170
171 unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
172                                    const TargetRegisterClass *RC,
173                                    unsigned Op0, unsigned Op1) {
174   MachineRegisterInfo &MRI = MF->getRegInfo();
175   const TargetInstrDesc &II = TII->get(MachineInstOpcode);
176   unsigned ResultReg = MRI.createVirtualRegister(RC);
177
178   MachineInstr *MI = BuildMI(*MF, II, ResultReg);
179   MI->addOperand(MachineOperand::CreateReg(Op0, false));
180   MI->addOperand(MachineOperand::CreateReg(Op1, false));
181
182   MBB->push_back(MI);
183   return ResultReg;
184 }