Add X86 target hook to implement load (even from GlobalAddress).
[oota-llvm.git] / lib / Target / X86 / X86FastISel.cpp
1 //===-- X86FastISel.cpp - X86 FastISel implementation ---------------------===//
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 defines the X86-specific support for the FastISel class. Much
11 // of the target-specific code is generated by tablegen in the file
12 // X86GenFastISel.inc, which is #included here.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "X86.h"
17 #include "X86InstrBuilder.h"
18 #include "X86ISelLowering.h"
19 #include "X86RegisterInfo.h"
20 #include "X86Subtarget.h"
21 #include "X86TargetMachine.h"
22 #include "llvm/CodeGen/FastISel.h"
23 #include "llvm/CodeGen/MachineRegisterInfo.h"
24
25 using namespace llvm;
26
27 class X86FastISel : public FastISel {
28   /// Subtarget - Keep a pointer to the X86Subtarget around so that we can
29   /// make the right decision when generating code for different targets.
30   const X86Subtarget *Subtarget;
31     
32 public:
33   explicit X86FastISel(MachineFunction &mf) : FastISel(mf) {
34     Subtarget = &TM.getSubtarget<X86Subtarget>();
35   }
36
37   virtual bool
38     TargetSelectInstruction(Instruction *I,
39                             DenseMap<const Value *, unsigned> &ValueMap,
40                       DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
41                             MachineBasicBlock *MBB);
42
43 #include "X86GenFastISel.inc"
44
45 private:
46   bool X86SelectConstAddr(Value *V,
47                           DenseMap<const Value *, unsigned> &ValueMap,
48                           MachineBasicBlock *MBB, unsigned &Op0);
49
50   bool X86SelectLoad(Instruction *I,
51                      DenseMap<const Value *, unsigned> &ValueMap,
52                      MachineBasicBlock *MBB);
53 };
54
55 /// X86SelectConstAddr - Select and emit code to materialize constant address.
56 /// 
57 bool X86FastISel::X86SelectConstAddr(Value *V,
58                                     DenseMap<const Value *, unsigned> &ValueMap,
59                                     MachineBasicBlock *MBB,
60                                     unsigned &Op0) {
61   // FIXME: Only GlobalAddress for now.
62   GlobalValue *GV = dyn_cast<GlobalValue>(V);
63   if (!GV)
64     return false;
65
66   if (Subtarget->GVRequiresExtraLoad(GV, TM, false)) {
67     // Issue load from stub if necessary.
68     unsigned Opc = 0;
69     const TargetRegisterClass *RC = NULL;
70     if (TLI.getPointerTy() == MVT::i32) {
71       Opc = X86::MOV32rm;
72       RC  = X86::GR32RegisterClass;
73     } else {
74       Opc = X86::MOV64rm;
75       RC  = X86::GR64RegisterClass;
76     }
77     Op0 = createResultReg(RC);
78     X86AddressMode AM;
79     AM.GV = GV;
80     addFullAddress(BuildMI(MBB, TII.get(Opc), Op0), AM);
81   }
82   return true;
83 }
84
85 /// X86SelectLoad - Select and emit code to implement load instructions.
86 ///
87 bool X86FastISel::X86SelectLoad(Instruction *I,
88                                 DenseMap<const Value *, unsigned> &ValueMap,
89                                 MachineBasicBlock *MBB)  {
90   MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
91   if (VT == MVT::Other || !VT.isSimple())
92     // Unhandled type. Halt "fast" selection and bail.
93     return false;
94   if (VT == MVT::iPTR)
95     // Use pointer type.
96     VT = TLI.getPointerTy();
97   // We only handle legal types. For example, on x86-32 the instruction
98   // selector contains all of the 64-bit instructions from x86-64,
99   // under the assumption that i64 won't be used if the target doesn't
100   // support it.
101   if (!TLI.isTypeLegal(VT))
102     return false;
103
104   Value *V = I->getOperand(0);
105   unsigned Op0 = getRegForValue(V, ValueMap);
106   if (Op0 == 0) {
107     // Handle constant load address.
108     if (!isa<Constant>(V) || !X86SelectConstAddr(V, ValueMap, MBB, Op0))
109       // Unhandled operand. Halt "fast" selection and bail.
110       return false;    
111   }
112
113   // Get opcode and regclass of the output for the given load instruction.
114   unsigned Opc = 0;
115   const TargetRegisterClass *RC = NULL;
116   switch (VT.getSimpleVT()) {
117   default: return false;
118   case MVT::i8:
119     Opc = X86::MOV8rm;
120     RC  = X86::GR8RegisterClass;
121     break;
122   case MVT::i16:
123     Opc = X86::MOV16rm;
124     RC  = X86::GR16RegisterClass;
125     break;
126   case MVT::i32:
127     Opc = X86::MOV32rm;
128     RC  = X86::GR32RegisterClass;
129     break;
130   case MVT::i64:
131     // Must be in x86-64 mode.
132     Opc = X86::MOV64rm;
133     RC  = X86::GR64RegisterClass;
134     break;
135   case MVT::f32:
136     if (Subtarget->hasSSE1()) {
137       Opc = X86::MOVSSrm;
138       RC  = X86::FR32RegisterClass;
139     } else {
140       Opc = X86::LD_Fp32m;
141       RC  = X86::RFP32RegisterClass;
142     }
143     break;
144   case MVT::f64:
145     if (Subtarget->hasSSE2()) {
146       Opc = X86::MOVSDrm;
147       RC  = X86::FR64RegisterClass;
148     } else {
149       Opc = X86::LD_Fp64m;
150       RC  = X86::RFP64RegisterClass;
151     }
152     break;
153   case MVT::f80:
154     Opc = X86::LD_Fp80m;
155     RC  = X86::RFP80RegisterClass;
156     break;
157   }
158
159   unsigned ResultReg = createResultReg(RC);
160   X86AddressMode AM;
161   if (Op0)
162     // Address is in register.
163     AM.Base.Reg = Op0;
164   else
165     AM.GV = cast<GlobalValue>(V);
166   addFullAddress(BuildMI(MBB, TII.get(Opc), ResultReg), AM);
167   UpdateValueMap(I, ResultReg, ValueMap);
168   return true;
169 }
170
171
172 bool
173 X86FastISel::TargetSelectInstruction(Instruction *I,
174                                   DenseMap<const Value *, unsigned> &ValueMap,
175                       DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap,
176                                   MachineBasicBlock *MBB)  {
177   switch (I->getOpcode()) {
178   default: break;
179   case Instruction::Load:
180     return X86SelectLoad(I, ValueMap, MBB);
181   }
182
183   return false;
184 }
185
186 namespace llvm {
187   llvm::FastISel *X86::createFastISel(MachineFunction &mf) {
188     return new X86FastISel(mf);
189   }
190 }