ARMISelDAGToDAG.cpp revision a4e64359aafaf23e440e9dc171859daef1995f1b
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> 29using namespace llvm; 30 31namespace { 32 class ARMTargetLowering : public TargetLowering { 33 public: 34 ARMTargetLowering(TargetMachine &TM); 35 virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); 36 }; 37 38} 39 40ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) 41 : TargetLowering(TM) { 42 setOperationAction(ISD::RET, MVT::Other, Custom); 43} 44 45static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { 46 assert(0 && "Not implemented"); 47 abort(); 48} 49 50static 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 77static 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 113static 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 134SDOperand 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/// 156namespace { 157class ARMDAGToDAGISel : public SelectionDAGISel { 158 ARMTargetLowering Lowering; 159 160public: 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 SelectAddrRegImm(SDOperand N, SDOperand &Offset, SDOperand &Base); 168 169 // Include the pieces autogenerated from the target description. 170#include "ARMGenDAGISel.inc" 171}; 172 173void 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//register plus/minus 12 bit offset 187bool ARMDAGToDAGISel::SelectAddrRegImm(SDOperand N, SDOperand &Offset, 188 SDOperand &Base) { 189 Offset = CurDAG->getTargetConstant(0, MVT::i32); 190 if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) { 191 Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); 192 } 193 else 194 Base = N; 195 return true; //any address fits in a register 196} 197 198void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { 199 SDNode *N = Op.Val; 200 201 switch (N->getOpcode()) { 202 default: 203 SelectCode(Result, Op); 204 break; 205 } 206} 207 208} // end anonymous namespace 209 210/// createARMISelDag - This pass converts a legalized DAG into a 211/// ARM-specific DAG, ready for instruction scheduling. 212/// 213FunctionPass *llvm::createARMISelDag(TargetMachine &TM) { 214 return new ARMDAGToDAGISel(TM); 215} 216