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