1 //===-- R600ISelDAGToDAG.cpp - A dag to dag inst selector for R600 --------===// 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 /// \file 10 /// Defines an instruction selector for the R600 subtarget. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "AMDGPU.h" 15 #include "AMDGPUISelDAGToDAG.h" 16 #include "MCTargetDesc/R600MCTargetDesc.h" 17 #include "R600.h" 18 #include "R600Subtarget.h" 19 #include "llvm/Analysis/ValueTracking.h" 20 21 class R600DAGToDAGISel : public AMDGPUDAGToDAGISel { 22 const R600Subtarget *Subtarget; 23 24 bool isConstantLoad(const MemSDNode *N, int cbID) const; 25 bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue &IntPtr); 26 bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg, 27 SDValue &Offset); 28 29 public: 30 explicit R600DAGToDAGISel(TargetMachine *TM, CodeGenOpt::Level OptLevel) 31 : AMDGPUDAGToDAGISel(TM, OptLevel) {} 32 33 void Select(SDNode *N) override; 34 35 bool SelectADDRIndirect(SDValue Addr, SDValue &Base, 36 SDValue &Offset) override; 37 bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 38 SDValue &Offset) override; 39 40 bool runOnMachineFunction(MachineFunction &MF) override; 41 42 void PreprocessISelDAG() override {} 43 44 protected: 45 // Include the pieces autogenerated from the target description. 46 #include "R600GenDAGISel.inc" 47 }; 48 49 bool R600DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { 50 Subtarget = &MF.getSubtarget<R600Subtarget>(); 51 return SelectionDAGISel::runOnMachineFunction(MF); 52 } 53 54 bool R600DAGToDAGISel::isConstantLoad(const MemSDNode *N, int CbId) const { 55 if (!N->readMem()) 56 return false; 57 if (CbId == -1) 58 return N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS || 59 N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT; 60 61 return N->getAddressSpace() == AMDGPUAS::CONSTANT_BUFFER_0 + CbId; 62 } 63 64 bool R600DAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr, 65 SDValue &IntPtr) { 66 if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) { 67 IntPtr = 68 CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr), true); 69 return true; 70 } 71 return false; 72 } 73 74 bool R600DAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr, 75 SDValue &BaseReg, 76 SDValue &Offset) { 77 if (!isa<ConstantSDNode>(Addr)) { 78 BaseReg = Addr; 79 Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true); 80 return true; 81 } 82 return false; 83 } 84 85 void R600DAGToDAGISel::Select(SDNode *N) { 86 unsigned int Opc = N->getOpcode(); 87 if (N->isMachineOpcode()) { 88 N->setNodeId(-1); 89 return; // Already selected. 90 } 91 92 switch (Opc) { 93 default: 94 break; 95 case AMDGPUISD::BUILD_VERTICAL_VECTOR: 96 case ISD::SCALAR_TO_VECTOR: 97 case ISD::BUILD_VECTOR: { 98 EVT VT = N->getValueType(0); 99 unsigned NumVectorElts = VT.getVectorNumElements(); 100 unsigned RegClassID; 101 // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG 102 // that adds a 128 bits reg copy when going through TwoAddressInstructions 103 // pass. We want to avoid 128 bits copies as much as possible because they 104 // can't be bundled by our scheduler. 105 switch (NumVectorElts) { 106 case 2: 107 RegClassID = R600::R600_Reg64RegClassID; 108 break; 109 case 4: 110 if (Opc == AMDGPUISD::BUILD_VERTICAL_VECTOR) 111 RegClassID = R600::R600_Reg128VerticalRegClassID; 112 else 113 RegClassID = R600::R600_Reg128RegClassID; 114 break; 115 default: 116 llvm_unreachable("Do not know how to lower this BUILD_VECTOR"); 117 } 118 SelectBuildVector(N, RegClassID); 119 return; 120 } 121 } 122 123 SelectCode(N); 124 } 125 126 bool R600DAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base, 127 SDValue &Offset) { 128 ConstantSDNode *C; 129 SDLoc DL(Addr); 130 131 if ((C = dyn_cast<ConstantSDNode>(Addr))) { 132 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32); 133 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 134 } else if ((Addr.getOpcode() == AMDGPUISD::DWORDADDR) && 135 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(0)))) { 136 Base = CurDAG->getRegister(R600::INDIRECT_BASE_ADDR, MVT::i32); 137 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 138 } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) && 139 (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) { 140 Base = Addr.getOperand(0); 141 Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32); 142 } else { 143 Base = Addr; 144 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); 145 } 146 147 return true; 148 } 149 150 bool R600DAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base, 151 SDValue &Offset) { 152 ConstantSDNode *IMMOffset; 153 154 if (Addr.getOpcode() == ISD::ADD && 155 (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) && 156 isInt<16>(IMMOffset->getZExtValue())) { 157 158 Base = Addr.getOperand(0); 159 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr), 160 MVT::i32); 161 return true; 162 // If the pointer address is constant, we can move it to the offset field. 163 } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr)) && 164 isInt<16>(IMMOffset->getZExtValue())) { 165 Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), 166 SDLoc(CurDAG->getEntryNode()), R600::ZERO, 167 MVT::i32); 168 Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr), 169 MVT::i32); 170 return true; 171 } 172 173 // Default case, no offset 174 Base = Addr; 175 Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32); 176 return true; 177 } 178 179 /// This pass converts a legalized DAG into a R600-specific 180 // DAG, ready for instruction scheduling. 181 FunctionPass *llvm::createR600ISelDag(TargetMachine *TM, 182 CodeGenOpt::Level OptLevel) { 183 return new R600DAGToDAGISel(TM, OptLevel); 184 } 185