33413d6c5b507aa2a31cb1c88d4a5c8a4f055e45
[oota-llvm.git] / lib / Target / ARM / ARMISelDAGToDAG.cpp
1 //===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Chris Lattner and is distributed under
6 // the University of Illinois Open Source License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines an instruction selector for the ARM target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ARM.h"
15 #include "ARMTargetMachine.h"
16 #include "llvm/DerivedTypes.h"
17 #include "llvm/Function.h"
18 #include "llvm/Intrinsics.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/SelectionDAG.h"
23 #include "llvm/CodeGen/SelectionDAGISel.h"
24 #include "llvm/CodeGen/SSARegMap.h"
25 #include "llvm/Target/TargetLowering.h"
26 #include "llvm/Support/Debug.h"
27 #include <iostream>
28 #include <set>
29 using namespace llvm;
30
31 namespace {
32   class ARMTargetLowering : public TargetLowering {
33   public:
34     ARMTargetLowering(TargetMachine &TM);
35     virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
36   };
37
38 }
39
40 ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
41   : TargetLowering(TM) {
42   setOperationAction(ISD::RET, MVT::Other, Custom);
43 }
44
45 static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
46   assert(0 && "Not implemented");
47   abort();
48 }
49
50 static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
51   SDOperand Copy;
52   SDOperand Chain = Op.getOperand(0);
53   switch(Op.getNumOperands()) {
54   default:
55     assert(0 && "Do not know how to return this many arguments!");
56     abort();
57   case 1: {
58     SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
59     return DAG.getNode(ISD::BRIND, MVT::Other, Chain, LR);
60   }
61   case 3:
62     Copy = DAG.getCopyToReg(Chain, ARM::R0, Op.getOperand(1), SDOperand());
63     if (DAG.getMachineFunction().liveout_empty())
64       DAG.getMachineFunction().addLiveOut(ARM::R0);
65     break;
66   }
67
68   SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
69
70   //bug: the copy and branch should be linked with a flag so that the
71   //scheduller can't move an instruction that destroys R0 in between them
72   //return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR, Copy.getValue(1));
73
74   return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR);
75 }
76
77 static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG,
78                                       unsigned ArgNo) {
79   MachineFunction &MF = DAG.getMachineFunction();
80   MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType();
81   assert (ObjectVT == MVT::i32);
82   SDOperand Root = Op.getOperand(0);
83   SSARegMap *RegMap = MF.getSSARegMap();
84
85   unsigned num_regs = 4;
86   static const unsigned REGS[] = {
87     ARM::R0, ARM::R1, ARM::R2, ARM::R3
88   };
89
90   if(ArgNo < num_regs) {
91     unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass);
92     MF.addLiveIn(REGS[ArgNo], VReg);
93     return DAG.getCopyFromReg(Root, VReg, MVT::i32);
94   } else {
95     // If the argument is actually used, emit a load from the right stack
96       // slot.
97     if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
98       unsigned ArgOffset = (ArgNo - num_regs) * 4;
99
100       MachineFrameInfo *MFI = MF.getFrameInfo();
101       unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8;
102       int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
103       SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32);
104       return DAG.getLoad(ObjectVT, Root, FIN,
105                          DAG.getSrcValue(NULL));
106     } else {
107       // Don't emit a dead load.
108       return DAG.getNode(ISD::UNDEF, ObjectVT);
109     }
110   }
111 }
112
113 static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
114   std::vector<SDOperand> ArgValues;
115   SDOperand Root = Op.getOperand(0);
116
117   for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
118     SDOperand ArgVal = LowerFORMAL_ARGUMENT(Op, DAG, ArgNo);
119
120     ArgValues.push_back(ArgVal);
121   }
122
123   bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
124   assert(!isVarArg);
125
126   ArgValues.push_back(Root);
127
128   // Return the new list of results.
129   std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(),
130                                     Op.Val->value_end());
131   return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues);
132 }
133
134 SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
135   switch (Op.getOpcode()) {
136   default:
137     assert(0 && "Should not custom lower this!");
138     abort();
139   case ISD::FORMAL_ARGUMENTS:
140     return LowerFORMAL_ARGUMENTS(Op, DAG);
141   case ISD::CALL:
142     return LowerCALL(Op, DAG);
143   case ISD::RET:
144     return LowerRET(Op, DAG);
145   }
146 }
147
148 //===----------------------------------------------------------------------===//
149 // Instruction Selector Implementation
150 //===----------------------------------------------------------------------===//
151
152 //===--------------------------------------------------------------------===//
153 /// ARMDAGToDAGISel - ARM specific code to select ARM machine
154 /// instructions for SelectionDAG operations.
155 ///
156 namespace {
157 class ARMDAGToDAGISel : public SelectionDAGISel {
158   ARMTargetLowering Lowering;
159
160 public:
161   ARMDAGToDAGISel(TargetMachine &TM)
162     : SelectionDAGISel(Lowering), Lowering(TM) {
163   }
164
165   void Select(SDOperand &Result, SDOperand Op);
166   virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
167   bool SelectAddrReg(SDOperand N, SDOperand &Base);
168
169   // Include the pieces autogenerated from the target description.
170 #include "ARMGenDAGISel.inc"
171 };
172
173 void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
174   DEBUG(BB->dump());
175
176   DAG.setRoot(SelectRoot(DAG.getRoot()));
177   assert(InFlightSet.empty() && "ISel InFlightSet has not been emptied!");
178   CodeGenMap.clear();
179   HandleMap.clear();
180   ReplaceMap.clear();
181   DAG.RemoveDeadNodes();
182
183   ScheduleAndEmitDAG(DAG);
184 }
185
186 bool ARMDAGToDAGISel::SelectAddrReg(SDOperand N, SDOperand &Base) {
187   if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) {
188     Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
189   }
190   else
191     Base = N;
192   return true;      //any address fits in a register
193 }
194
195 void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
196   SDNode *N = Op.Val;
197
198   switch (N->getOpcode()) {
199   default:
200     SelectCode(Result, Op);
201     break;
202   }
203 }
204
205 }  // end anonymous namespace
206
207 /// createARMISelDag - This pass converts a legalized DAG into a
208 /// ARM-specific DAG, ready for instruction scheduling.
209 ///
210 FunctionPass *llvm::createARMISelDag(TargetMachine &TM) {
211   return new ARMDAGToDAGISel(TM);
212 }