1 //===- ARCISelDAGToDAG.cpp - ARC dag to dag inst selector -------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines an instruction selector for the ARC target. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "ARC.h" 15 #include "ARCTargetMachine.h" 16 #include "llvm/CodeGen/MachineFrameInfo.h" 17 #include "llvm/CodeGen/MachineFunction.h" 18 #include "llvm/CodeGen/MachineInstrBuilder.h" 19 #include "llvm/CodeGen/MachineRegisterInfo.h" 20 #include "llvm/CodeGen/SelectionDAG.h" 21 #include "llvm/CodeGen/SelectionDAGISel.h" 22 #include "llvm/CodeGen/TargetLowering.h" 23 #include "llvm/IR/CallingConv.h" 24 #include "llvm/IR/Constants.h" 25 #include "llvm/IR/DerivedTypes.h" 26 #include "llvm/IR/Function.h" 27 #include "llvm/IR/Intrinsics.h" 28 #include "llvm/IR/LLVMContext.h" 29 #include "llvm/Support/Compiler.h" 30 #include "llvm/Support/Debug.h" 31 #include "llvm/Support/ErrorHandling.h" 32 #include "llvm/Support/raw_ostream.h" 33 34 using namespace llvm; 35 36 /// ARCDAGToDAGISel - ARC specific code to select ARC machine 37 /// instructions for SelectionDAG operations. 38 namespace { 39 40 class ARCDAGToDAGISel : public SelectionDAGISel { 41 public: 42 ARCDAGToDAGISel(ARCTargetMachine &TM, CodeGenOpt::Level OptLevel) 43 : SelectionDAGISel(TM, OptLevel) {} 44 45 void Select(SDNode *N) override; 46 47 // Complex Pattern Selectors. 48 bool SelectFrameADDR_ri(SDValue Addr, SDValue &Base, SDValue &Offset); 49 bool SelectAddrModeS9(SDValue Addr, SDValue &Base, SDValue &Offset); 50 bool SelectAddrModeImm(SDValue Addr, SDValue &Base, SDValue &Offset); 51 bool SelectAddrModeFar(SDValue Addr, SDValue &Base, SDValue &Offset); 52 bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) { 53 const ConstantSDNode *CN = cast<ConstantSDNode>(N); 54 Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32); 55 Reg = CurDAG->getRegister(ARC::STATUS32, MVT::i32); 56 return true; 57 } 58 59 StringRef getPassName() const override { 60 return "ARC DAG->DAG Pattern Instruction Selection"; 61 } 62 63 // Include the pieces autogenerated from the target description. 64 #include "ARCGenDAGISel.inc" 65 }; 66 67 } // end anonymous namespace 68 69 /// This pass converts a legalized DAG into a ARC-specific DAG, ready for 70 /// instruction scheduling. 71 FunctionPass *llvm::createARCISelDag(ARCTargetMachine &TM, 72 CodeGenOpt::Level OptLevel) { 73 return new ARCDAGToDAGISel(TM, OptLevel); 74 } 75 76 bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr, SDValue &Base, 77 SDValue &Offset) { 78 if (Addr.getOpcode() == ARCISD::GAWRAPPER) { 79 Base = Addr.getOperand(0); 80 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 81 return true; 82 } 83 return false; 84 } 85 86 bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr, SDValue &Base, 87 SDValue &Offset) { 88 if (Addr.getOpcode() == ARCISD::GAWRAPPER) { 89 return false; 90 } 91 92 if (Addr.getOpcode() != ISD::ADD && Addr.getOpcode() != ISD::SUB && 93 !CurDAG->isBaseWithConstantOffset(Addr)) { 94 if (Addr.getOpcode() == ISD::FrameIndex) { 95 // Match frame index. 96 int FI = cast<FrameIndexSDNode>(Addr)->getIndex(); 97 Base = CurDAG->getTargetFrameIndex( 98 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 99 } else { 100 Base = Addr; 101 } 102 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 103 return true; 104 } 105 106 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { 107 int32_t RHSC = RHS->getSExtValue(); 108 if (Addr.getOpcode() == ISD::SUB) 109 RHSC = -RHSC; 110 111 // Do we need more than 9 bits to encode? 112 if (!isInt<9>(RHSC)) 113 return false; 114 Base = Addr.getOperand(0); 115 if (Base.getOpcode() == ISD::FrameIndex) { 116 int FI = cast<FrameIndexSDNode>(Base)->getIndex(); 117 Base = CurDAG->getTargetFrameIndex( 118 FI, TLI->getPointerTy(CurDAG->getDataLayout())); 119 } 120 Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32); 121 return true; 122 } 123 Base = Addr; 124 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 125 return true; 126 } 127 128 bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr, SDValue &Base, 129 SDValue &Offset) { 130 if (SelectAddrModeS9(Addr, Base, Offset)) 131 return false; 132 if (Addr.getOpcode() == ARCISD::GAWRAPPER) { 133 return false; 134 } 135 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) { 136 int32_t RHSC = RHS->getSExtValue(); 137 if (Addr.getOpcode() == ISD::SUB) 138 RHSC = -RHSC; 139 Base = Addr.getOperand(0); 140 Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32); 141 return true; 142 } 143 return false; 144 } 145 146 // Is this a legal frame index addressing expression. 147 bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr, SDValue &Base, 148 SDValue &Offset) { 149 FrameIndexSDNode *FIN = nullptr; 150 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) { 151 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 152 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 153 return true; 154 } 155 if (Addr.getOpcode() == ISD::ADD) { 156 ConstantSDNode *CN = nullptr; 157 if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) && 158 (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) && 159 (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) { 160 // Constant positive word offset from frame index 161 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 162 Offset = 163 CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), MVT::i32); 164 return true; 165 } 166 } 167 return false; 168 } 169 170 void ARCDAGToDAGISel::Select(SDNode *N) { 171 switch (N->getOpcode()) { 172 case ISD::Constant: { 173 uint64_t CVal = cast<ConstantSDNode>(N)->getZExtValue(); 174 ReplaceNode(N, CurDAG->getMachineNode( 175 isInt<12>(CVal) ? ARC::MOV_rs12 : ARC::MOV_rlimm, 176 SDLoc(N), MVT::i32, 177 CurDAG->getTargetConstant(CVal, SDLoc(N), MVT::i32))); 178 return; 179 } 180 } 181 SelectCode(N); 182 } 183