1 //===-- ARMISelDAGToDAG.cpp - A dag to dag inst selector for ARM ----------===//
3 // The LLVM Compiler Infrastructure
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.
8 //===----------------------------------------------------------------------===//
10 // This file defines an instruction selector for the ARM target.
12 //===----------------------------------------------------------------------===//
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"
32 class ARMTargetLowering : public TargetLowering {
34 ARMTargetLowering(TargetMachine &TM);
35 virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG);
40 ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
41 : TargetLowering(TM) {
42 setOperationAction(ISD::RET, MVT::Other, Custom);
45 static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) {
46 assert(0 && "Not implemented");
50 static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) {
52 SDOperand Chain = Op.getOperand(0);
53 switch(Op.getNumOperands()) {
55 assert(0 && "Do not know how to return this many arguments!");
58 SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
59 return DAG.getNode(ISD::BRIND, MVT::Other, Chain, LR);
62 Copy = DAG.getCopyToReg(Chain, ARM::R0, Op.getOperand(1), SDOperand());
63 if (DAG.getMachineFunction().liveout_empty())
64 DAG.getMachineFunction().addLiveOut(ARM::R0);
68 SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32);
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));
74 return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR);
77 static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG,
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();
85 unsigned num_regs = 4;
86 static const unsigned REGS[] = {
87 ARM::R0, ARM::R1, ARM::R2, ARM::R3
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);
95 // If the argument is actually used, emit a load from the right stack
97 if (!Op.Val->hasNUsesOfValue(0, ArgNo)) {
98 unsigned ArgOffset = (ArgNo - num_regs) * 4;
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));
107 // Don't emit a dead load.
108 return DAG.getNode(ISD::UNDEF, ObjectVT);
113 static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) {
114 std::vector<SDOperand> ArgValues;
115 SDOperand Root = Op.getOperand(0);
117 for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
118 SDOperand ArgVal = LowerFORMAL_ARGUMENT(Op, DAG, ArgNo);
120 ArgValues.push_back(ArgVal);
123 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
126 ArgValues.push_back(Root);
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);
134 SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
135 switch (Op.getOpcode()) {
137 assert(0 && "Should not custom lower this!");
139 case ISD::FORMAL_ARGUMENTS:
140 return LowerFORMAL_ARGUMENTS(Op, DAG);
142 return LowerCALL(Op, DAG);
144 return LowerRET(Op, DAG);
148 //===----------------------------------------------------------------------===//
149 // Instruction Selector Implementation
150 //===----------------------------------------------------------------------===//
152 //===--------------------------------------------------------------------===//
153 /// ARMDAGToDAGISel - ARM specific code to select ARM machine
154 /// instructions for SelectionDAG operations.
157 class ARMDAGToDAGISel : public SelectionDAGISel {
158 ARMTargetLowering Lowering;
161 ARMDAGToDAGISel(TargetMachine &TM)
162 : SelectionDAGISel(Lowering), Lowering(TM) {
165 void Select(SDOperand &Result, SDOperand Op);
166 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
167 bool SelectAddrReg(SDOperand N, SDOperand &Base);
169 // Include the pieces autogenerated from the target description.
170 #include "ARMGenDAGISel.inc"
173 void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
176 DAG.setRoot(SelectRoot(DAG.getRoot()));
177 assert(InFlightSet.empty() && "ISel InFlightSet has not been emptied!");
181 DAG.RemoveDeadNodes();
183 ScheduleAndEmitDAG(DAG);
186 bool ARMDAGToDAGISel::SelectAddrReg(SDOperand N, SDOperand &Base) {
187 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) {
188 Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
192 return true; //any address fits in a register
195 void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) {
198 switch (N->getOpcode()) {
200 SelectCode(Result, Op);
205 } // end anonymous namespace
207 /// createARMISelDag - This pass converts a legalized DAG into a
208 /// ARM-specific DAG, ready for instruction scheduling.
210 FunctionPass *llvm::createARMISelDag(TargetMachine &TM) {
211 return new ARMDAGToDAGISel(TM);