ARMISelDAGToDAG.cpp revision 4b02367d542c7eaa429d1ff73119ae44ddb252a8
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_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) { 78 MachineFunction &MF = DAG.getMachineFunction(); 79 SSARegMap *RegMap = MF.getSSARegMap(); 80 std::vector<SDOperand> ArgValues; 81 SDOperand Root = Op.getOperand(0); 82 83 unsigned reg_idx = 0; 84 unsigned num_regs = 4; 85 86 static const unsigned REGS[] = { 87 ARM::R0, ARM::R1, ARM::R2, ARM::R3 88 }; 89 90 for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { 91 SDOperand ArgVal; 92 93 MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); 94 assert (ObjectVT == MVT::i32); 95 96 assert(reg_idx < num_regs); 97 unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass); 98 MF.addLiveIn(REGS[reg_idx], VReg); 99 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32); 100 ++reg_idx; 101 102 ArgValues.push_back(ArgVal); 103 } 104 105 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; 106 assert(!isVarArg); 107 108 ArgValues.push_back(Root); 109 110 // Return the new list of results. 111 std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(), 112 Op.Val->value_end()); 113 return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues); 114} 115 116SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { 117 switch (Op.getOpcode()) { 118 default: 119 assert(0 && "Should not custom lower this!"); 120 abort(); 121 case ISD::FORMAL_ARGUMENTS: 122 return LowerFORMAL_ARGUMENTS(Op, DAG); 123 case ISD::CALL: 124 return LowerCALL(Op, DAG); 125 case ISD::RET: 126 return LowerRET(Op, DAG); 127 } 128} 129 130//===----------------------------------------------------------------------===// 131// Instruction Selector Implementation 132//===----------------------------------------------------------------------===// 133 134//===--------------------------------------------------------------------===// 135/// ARMDAGToDAGISel - ARM specific code to select ARM machine 136/// instructions for SelectionDAG operations. 137/// 138namespace { 139class ARMDAGToDAGISel : public SelectionDAGISel { 140 ARMTargetLowering Lowering; 141 142public: 143 ARMDAGToDAGISel(TargetMachine &TM) 144 : SelectionDAGISel(Lowering), Lowering(TM) { 145 } 146 147 void Select(SDOperand &Result, SDOperand Op); 148 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); 149 150 // Include the pieces autogenerated from the target description. 151#include "ARMGenDAGISel.inc" 152}; 153 154void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { 155 DEBUG(BB->dump()); 156 157 DAG.setRoot(SelectRoot(DAG.getRoot())); 158 assert(InFlightSet.empty() && "ISel InFlightSet has not been emptied!"); 159 CodeGenMap.clear(); 160 HandleMap.clear(); 161 ReplaceMap.clear(); 162 DAG.RemoveDeadNodes(); 163 164 ScheduleAndEmitDAG(DAG); 165} 166 167void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { 168 SelectCode(Result, Op); 169} 170 171} // end anonymous namespace 172 173/// createARMISelDag - This pass converts a legalized DAG into a 174/// ARM-specific DAG, ready for instruction scheduling. 175/// 176FunctionPass *llvm::createARMISelDag(TargetMachine &TM) { 177 return new ARMDAGToDAGISel(TM); 178} 179