ARMISelDAGToDAG.cpp revision d74ea2bbd8bb630331f35ead42d385249bd42af8
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 ARMISD { 32 enum { 33 FIRST_NUMBER = ISD::BUILTIN_OP_END+ARM::INSTRUCTION_LIST_END, 34 RET_FLAG 35 }; 36} 37 38namespace { 39 class ARMTargetLowering : public TargetLowering { 40 public: 41 ARMTargetLowering(TargetMachine &TM); 42 virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); 43 44 virtual std::pair<SDOperand, SDOperand> 45 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, 46 unsigned CC, 47 bool isTailCall, SDOperand Callee, ArgListTy &Args, 48 SelectionDAG &DAG); 49 50 }; 51 52} 53 54ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) 55 : TargetLowering(TM) { 56 setOperationAction(ISD::RET, MVT::Other, Custom); 57} 58 59std::pair<SDOperand, SDOperand> 60ARMTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, 61 bool isVarArg, unsigned CC, 62 bool isTailCall, SDOperand Callee, 63 ArgListTy &Args, SelectionDAG &DAG) { 64 assert(0 && "Not implemented"); 65 abort(); 66} 67 68static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { 69 SDOperand Copy; 70 switch(Op.getNumOperands()) { 71 default: 72 assert(0 && "Do not know how to return this many arguments!"); 73 abort(); 74 case 1: 75 return SDOperand(); // ret void is legal 76 case 2: 77 Copy = DAG.getCopyToReg(Op.getOperand(0), ARM::R0, Op.getOperand(1), SDOperand()); 78 break; 79 } 80 81 return DAG.getNode(ARMISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); 82} 83 84static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG) { 85 MachineFunction &MF = DAG.getMachineFunction(); 86 SSARegMap *RegMap = MF.getSSARegMap(); 87 std::vector<SDOperand> ArgValues; 88 SDOperand Root = Op.getOperand(0); 89 90 unsigned reg_idx = 0; 91 unsigned num_regs = 4; 92 93 static const unsigned REGS[] = { 94 ARM::R0, ARM::R1, ARM::R2, ARM::R3 95 }; 96 97 for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { 98 SDOperand ArgVal; 99 100 MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); 101 assert (ObjectVT == MVT::i32); 102 103 assert(reg_idx < num_regs); 104 unsigned VReg = RegMap->createVirtualRegister(&ARM::IntRegsRegClass); 105 MF.addLiveIn(REGS[reg_idx], VReg); 106 ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32); 107 ++reg_idx; 108 109 ArgValues.push_back(ArgVal); 110 } 111 112 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; 113 assert(!isVarArg); 114 115 ArgValues.push_back(Root); 116 117 // Return the new list of results. 118 std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(), 119 Op.Val->value_end()); 120 return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues); 121} 122 123SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { 124 switch (Op.getOpcode()) { 125 default: 126 assert(0 && "Should not custom lower this!"); 127 abort(); 128 case ISD::FORMAL_ARGUMENTS: 129 return LowerFORMAL_ARGUMENTS(Op, DAG); 130 case ISD::RET: 131 return LowerRET(Op, DAG); 132 } 133} 134 135//===----------------------------------------------------------------------===// 136// Instruction Selector Implementation 137//===----------------------------------------------------------------------===// 138 139//===--------------------------------------------------------------------===// 140/// ARMDAGToDAGISel - ARM specific code to select ARM machine 141/// instructions for SelectionDAG operations. 142/// 143namespace { 144class ARMDAGToDAGISel : public SelectionDAGISel { 145 ARMTargetLowering Lowering; 146 147public: 148 ARMDAGToDAGISel(TargetMachine &TM) 149 : SelectionDAGISel(Lowering), Lowering(TM) { 150 } 151 152 void Select(SDOperand &Result, SDOperand Op); 153 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); 154 155 // Include the pieces autogenerated from the target description. 156#include "ARMGenDAGISel.inc" 157}; 158 159void ARMDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { 160 DEBUG(BB->dump()); 161 162 DAG.setRoot(SelectRoot(DAG.getRoot())); 163 CodeGenMap.clear(); 164 DAG.RemoveDeadNodes(); 165 166 ScheduleAndEmitDAG(DAG); 167} 168 169void ARMDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { 170 SelectCode(Result, Op); 171} 172 173} // end anonymous namespace 174 175/// createARMISelDag - This pass converts a legalized DAG into a 176/// ARM-specific DAG, ready for instruction scheduling. 177/// 178FunctionPass *llvm::createARMISelDag(TargetMachine &TM) { 179 return new ARMDAGToDAGISel(TM); 180} 181