FastISel.cpp revision 4cbe0662abb2cd6025eff51e19574a48f1a83b97
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"
19using 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///
24bool 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
48bool FastISel::SelectGetElementPtr(Instruction *I,
49                                   DenseMap<const Value*, unsigned> &ValueMap) {
50  // TODO: implement me
51  return false;
52}
53
54BasicBlock::iterator
55FastISel::SelectInstructions(BasicBlock::iterator Begin,
56                             BasicBlock::iterator End,
57                             DenseMap<const Value*, unsigned> &ValueMap) {
58  BasicBlock::iterator I = Begin;
59
60  for (; I != End; ++I) {
61    switch (I->getOpcode()) {
62    case Instruction::Add: {
63      ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
64      if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
65    }
66    case Instruction::Sub: {
67      ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
68      if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
69    }
70    case Instruction::Mul: {
71      ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
72      if (!SelectBinaryOp(I, Opc, ValueMap))  return I; break;
73    }
74    case Instruction::SDiv:
75      if (!SelectBinaryOp(I, ISD::SDIV, ValueMap)) return I; break;
76    case Instruction::UDiv:
77      if (!SelectBinaryOp(I, ISD::UDIV, ValueMap)) return I; break;
78    case Instruction::FDiv:
79      if (!SelectBinaryOp(I, ISD::FDIV, ValueMap)) return I; break;
80    case Instruction::SRem:
81      if (!SelectBinaryOp(I, ISD::SREM, ValueMap)) return I; break;
82    case Instruction::URem:
83      if (!SelectBinaryOp(I, ISD::UREM, ValueMap)) return I; break;
84    case Instruction::FRem:
85      if (!SelectBinaryOp(I, ISD::FREM, ValueMap)) return I; break;
86    case Instruction::Shl:
87      if (!SelectBinaryOp(I, ISD::SHL, ValueMap)) return I; break;
88    case Instruction::LShr:
89      if (!SelectBinaryOp(I, ISD::SRL, ValueMap)) return I; break;
90    case Instruction::AShr:
91      if (!SelectBinaryOp(I, ISD::SRA, ValueMap)) return I; break;
92    case Instruction::And:
93      if (!SelectBinaryOp(I, ISD::AND, ValueMap)) return I; break;
94    case Instruction::Or:
95      if (!SelectBinaryOp(I, ISD::OR, ValueMap)) return I; break;
96    case Instruction::Xor:
97      if (!SelectBinaryOp(I, ISD::XOR, ValueMap)) return I; break;
98
99    case Instruction::GetElementPtr:
100      if (!SelectGetElementPtr(I, ValueMap)) return I;
101      break;
102
103    case Instruction::Br: {
104      BranchInst *BI = cast<BranchInst>(I);
105
106      // For now, check for and handle just the most trivial case: an
107      // unconditional fall-through branch.
108      if (BI->isUnconditional()) {
109         MachineFunction::iterator NextMBB =
110           next(MachineFunction::iterator(MBB));
111         if (NextMBB != MF->end() &&
112             NextMBB->getBasicBlock() == BI->getSuccessor(0)) {
113          MBB->addSuccessor(NextMBB);
114          break;
115        }
116      }
117
118      // Something more complicated. Halt "fast" selection and bail.
119      return I;
120    }
121    default:
122      // Unhandled instruction. Halt "fast" selection and bail.
123      return I;
124    }
125  }
126
127  return I;
128}
129
130FastISel::~FastISel() {}
131
132unsigned FastISel::FastEmit_(MVT::SimpleValueType, ISD::NodeType) {
133  return 0;
134}
135
136unsigned FastISel::FastEmit_r(MVT::SimpleValueType, ISD::NodeType,
137                              unsigned /*Op0*/) {
138  return 0;
139}
140
141unsigned FastISel::FastEmit_rr(MVT::SimpleValueType, ISD::NodeType,
142                               unsigned /*Op0*/, unsigned /*Op0*/) {
143  return 0;
144}
145
146unsigned FastISel::FastEmitInst_(unsigned MachineInstOpcode,
147                                 const TargetRegisterClass* RC) {
148  MachineRegisterInfo &MRI = MF->getRegInfo();
149  unsigned ResultReg = MRI.createVirtualRegister(RC);
150  const TargetInstrDesc &II = TII->get(MachineInstOpcode);
151
152  MachineInstr *MI = BuildMI(*MF, II, ResultReg);
153
154  MBB->push_back(MI);
155  return ResultReg;
156}
157
158unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode,
159                                  const TargetRegisterClass *RC,
160                                  unsigned Op0) {
161  MachineRegisterInfo &MRI = MF->getRegInfo();
162  unsigned ResultReg = MRI.createVirtualRegister(RC);
163  const TargetInstrDesc &II = TII->get(MachineInstOpcode);
164
165  MachineInstr *MI = BuildMI(*MF, II, ResultReg);
166  MI->addOperand(MachineOperand::CreateReg(Op0, false));
167
168  MBB->push_back(MI);
169  return ResultReg;
170}
171
172unsigned FastISel::FastEmitInst_rr(unsigned MachineInstOpcode,
173                                   const TargetRegisterClass *RC,
174                                   unsigned Op0, unsigned Op1) {
175  MachineRegisterInfo &MRI = MF->getRegInfo();
176  unsigned ResultReg = MRI.createVirtualRegister(RC);
177  const TargetInstrDesc &II = TII->get(MachineInstOpcode);
178
179  MachineInstr *MI = BuildMI(*MF, II, ResultReg);
180  MI->addOperand(MachineOperand::CreateReg(Op0, false));
181  MI->addOperand(MachineOperand::CreateReg(Op1, false));
182
183  MBB->push_back(MI);
184  return ResultReg;
185}
186