ARMISelDAGToDAG.cpp revision fac00a93a98d43ac0d4ca514aa5a720debbd6c8b
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/CallingConv.h" 17#include "llvm/DerivedTypes.h" 18#include "llvm/Function.h" 19#include "llvm/Intrinsics.h" 20#include "llvm/CodeGen/MachineFrameInfo.h" 21#include "llvm/CodeGen/MachineFunction.h" 22#include "llvm/CodeGen/MachineInstrBuilder.h" 23#include "llvm/CodeGen/SelectionDAG.h" 24#include "llvm/CodeGen/SelectionDAGISel.h" 25#include "llvm/CodeGen/SSARegMap.h" 26#include "llvm/Target/TargetLowering.h" 27#include "llvm/Support/Debug.h" 28#include <iostream> 29#include <set> 30using namespace llvm; 31 32namespace { 33 class ARMTargetLowering : public TargetLowering { 34 public: 35 ARMTargetLowering(TargetMachine &TM); 36 virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); 37 virtual const char *getTargetNodeName(unsigned Opcode) const; 38 }; 39 40} 41 42ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) 43 : TargetLowering(TM) { 44 setOperationAction(ISD::RET, MVT::Other, Custom); 45} 46 47namespace llvm { 48 namespace ARMISD { 49 enum NodeType { 50 // Start the numbering where the builting ops and target ops leave off. 51 FIRST_NUMBER = ISD::BUILTIN_OP_END+ARM::INSTRUCTION_LIST_END, 52 /// CALL - A direct function call. 53 CALL 54 }; 55 } 56} 57 58const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { 59 switch (Opcode) { 60 default: return 0; 61 case ARMISD::CALL: return "ARMISD::CALL"; 62 } 63} 64 65// This transforms a ISD::CALL node into a 66// callseq_star <- ARMISD:CALL <- callseq_end 67// chain 68static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { 69 SDOperand Chain = Op.getOperand(0); 70 unsigned CallConv = cast<ConstantSDNode>(Op.getOperand(1))->getValue(); 71 assert(CallConv == CallingConv::C && "unknown calling convention"); 72 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; 73 assert(isVarArg == false && "VarArg not supported"); 74 bool isTailCall = cast<ConstantSDNode>(Op.getOperand(3))->getValue() != 0; 75 assert(isTailCall == false && "tail call not supported"); 76 SDOperand Callee = Op.getOperand(4); 77 unsigned NumOps = (Op.getNumOperands() - 5) / 2; 78 79 // Count how many bytes are to be pushed on the stack. Initially 80 // only the link register. 81 unsigned NumBytes = 4; 82 83 assert(NumOps <= 4); //no args on the stack 84 85 // Adjust the stack pointer for the new arguments... 86 // These operations are automatically eliminated by the prolog/epilog pass 87 Chain = DAG.getCALLSEQ_START(Chain, 88 DAG.getConstant(NumBytes, MVT::i32)); 89 90 static const unsigned regs[] = { 91 ARM::R0, ARM::R1, ARM::R2, ARM::R3 92 }; 93 94 std::vector<std::pair<unsigned, SDOperand> > RegsToPass; 95 96 for (unsigned i = 0; i != NumOps; ++i) { 97 SDOperand Arg = Op.getOperand(5+2*i); 98 RegsToPass.push_back(std::make_pair(regs[i], Arg)); 99 } 100 101 // Build a sequence of copy-to-reg nodes chained together with token chain 102 // and flag operands which copy the outgoing args into the appropriate regs. 103 SDOperand InFlag; 104 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 105 Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second, 106 InFlag); 107 InFlag = Chain.getValue(1); 108 } 109 110 std::vector<MVT::ValueType> NodeTys; 111 NodeTys.push_back(MVT::Other); // Returns a chain 112 NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. 113 114 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every 115 // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol 116 // node so that legalize doesn't hack it. 117 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 118 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType()); 119 120 // If this is a direct call, pass the chain and the callee. 121 assert (Callee.Val); 122 std::vector<SDOperand> Ops; 123 Ops.push_back(Chain); 124 Ops.push_back(Callee); 125 126 unsigned CallOpc = ARMISD::CALL; 127 if (InFlag.Val) 128 Ops.push_back(InFlag); 129 Chain = DAG.getNode(CallOpc, NodeTys, Ops); 130 InFlag = Chain.getValue(1); 131 132 std::vector<SDOperand> ResultVals; 133 NodeTys.clear(); 134 135 // If the call has results, copy the values out of the ret val registers. 136 switch (Op.Val->getValueType(0)) { 137 default: assert(0 && "Unexpected ret value!"); 138 case MVT::Other: 139 break; 140 case MVT::i32: 141 Chain = DAG.getCopyFromReg(Chain, ARM::R0, MVT::i32, InFlag).getValue(1); 142 ResultVals.push_back(Chain.getValue(0)); 143 NodeTys.push_back(MVT::i32); 144 } 145 146 Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain, 147 DAG.getConstant(NumBytes, MVT::i32)); 148 NodeTys.push_back(MVT::Other); 149 150 if (ResultVals.empty()) 151 return Chain; 152 153 ResultVals.push_back(Chain); 154 SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys, ResultVals); 155 return Res.getValue(Op.ResNo); 156} 157 158static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { 159 SDOperand Copy; 160 SDOperand Chain = Op.getOperand(0); 161 switch(Op.getNumOperands()) { 162 default: 163 assert(0 && "Do not know how to return this many arguments!"); 164 abort(); 165 case 1: { 166 SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32); 167 return DAG.getNode(ISD::BRIND, MVT::Other, Chain, LR); 168 } 169 case 3: 170 Copy = DAG.getCopyToReg(Chain, ARM::R0, Op.getOperand(1), SDOperand()); 171 if (DAG.getMachineFunction().liveout_empty()) 172 DAG.getMachineFunction().addLiveOut(ARM::R0); 173 break; 174 } 175 176 SDOperand LR = DAG.getRegister(ARM::R14, MVT::i32); 177 178 //bug: the copy and branch should be linked with a flag so that the 179 //scheduller can't move an instruction that destroys R0 in between them 180 //return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR, Copy.getValue(1)); 181 182 return DAG.getNode(ISD::BRIND, MVT::Other, Copy, LR); 183} 184 185static SDOperand LowerFORMAL_ARGUMENT(SDOperand Op, SelectionDAG &DAG, 186 unsigned ArgNo) { 187 MachineFunction &MF = DAG.getMachineFunction(); 188 MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); 189 assert (ObjectVT == MVT::i32); 190 SDOperand Root = Op.getOperand(0); 191 SSARegMap *RegMap = MF.getSSARegMap(); 192 193 unsigned num_regs = 4; 194 static const unsigned REGS[] = { 195 ARM::R0, ARM::R1, ARM::R2, ARM::R3 196 }; 197 198 if(ArgNo < num_regs) { 199 unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass); 200 MF.addLiveIn(REGS[ArgNo], VReg); 201 return DAG.getCopyFromReg(Root, VReg, MVT::i32); 202 } else { 203 // If the argument is actually used, emit a load from the right stack 204 // slot. 205 if (!Op.Val->hasNUsesOfValue(0, ArgNo)) { 206 unsigned ArgOffset = (ArgNo - num_regs) * 4; 207 208 MachineFrameInfo *MFI = MF.getFrameInfo(); 209 unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8; 210 int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); 211 SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); 212 return DAG.getLoad(ObjectVT, Root, FIN, 213 DAG.getSrcValue(NULL)); 214 } else { 215 // Don't emit a dead load. 216 return DAG.getNode(ISD::UNDEF, ObjectVT); 217 } 218 } 219} 220 221static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) { 222 std::vector<SDOperand> ArgValues; 223 SDOperand Root = Op.getOperand(0); 224 225 for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { 226 SDOperand ArgVal = LowerFORMAL_ARGUMENT(Op, DAG, ArgNo); 227 228 ArgValues.push_back(ArgVal); 229 } 230 231 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; 232 assert(!isVarArg); 233 234 ArgValues.push_back(Root); 235 236 // Return the new list of results. 237 std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(), 238 Op.Val->value_end()); 239 return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues); 240} 241 242SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { 243 switch (Op.getOpcode()) { 244 default: 245 assert(0 && "Should not custom lower this!"); 246 abort(); 247 case ISD::FORMAL_ARGUMENTS: 248 return LowerFORMAL_ARGUMENTS(Op, DAG); 249 case ISD::CALL: 250 return LowerCALL(Op, DAG); 251 case ISD::RET: 252 return LowerRET(Op, DAG); 253 } 254} 255 256//===----------------------------------------------------------------------===// 257// Instruction Selector Implementation 258//===----------------------------------------------------------------------===// 259 260//===--------------------------------------------------------------------===// 261/// ARMDAGToDAGISel - ARM specific code to select ARM machine 262/// instructions for SelectionDAG operations. 263/// 264namespace { 265class ARMDAGToDAGISel : public SelectionDAGISel { 266 ARMTargetLowering Lowering; 267 268public: 269 ARMDAGToDAGISel(TargetMachine &TM) 270 : SelectionDAGISel(Lowering), Lowering(TM) { 271 } 272 273 void Select(SDOperand &Result, SDOperand Op); 274 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); 275 bool SelectAddrRegImm(SDOperand N, SDOperand &Offset, SDOperand &Base); 276 277 // Include the pieces autogenerated from the target description. 278#include "ARMGenDAGISel.inc" 279}; 280 281void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { 282 DEBUG(BB->dump()); 283 284 DAG.setRoot(SelectRoot(DAG.getRoot())); 285 assert(InFlightSet.empty() && "ISel InFlightSet has not been emptied!"); 286 CodeGenMap.clear(); 287 HandleMap.clear(); 288 ReplaceMap.clear(); 289 DAG.RemoveDeadNodes(); 290 291 ScheduleAndEmitDAG(DAG); 292} 293 294//register plus/minus 12 bit offset 295bool ARMDAGToDAGISel::SelectAddrRegImm(SDOperand N, SDOperand &Offset, 296 SDOperand &Base) { 297 Offset = CurDAG->getTargetConstant(0, MVT::i32); 298 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) { 299 Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); 300 } 301 else 302 Base = N; 303 return true; //any address fits in a register 304} 305 306void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { 307 SDNode *N = Op.Val; 308 309 switch (N->getOpcode()) { 310 default: 311 SelectCode(Result, Op); 312 break; 313 } 314} 315 316} // end anonymous namespace 317 318/// createARMISelDag - This pass converts a legalized DAG into a 319/// ARM-specific DAG, ready for instruction scheduling. 320/// 321FunctionPass *llvm::createARMISelDag(TargetMachine &TM) { 322 return new ARMDAGToDAGISel(TM); 323} 324