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