1 //===-- AMDGPUISelDAGToDAG.h - A dag to dag inst selector for AMDGPU ----===// 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 AMDGPU target. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUISELDAGTODAG_H 15 #define LLVM_LIB_TARGET_AMDGPU_AMDGPUISELDAGTODAG_H 16 17 #include "GCNSubtarget.h" 18 #include "SIMachineFunctionInfo.h" 19 #include "SIModeRegisterDefaults.h" 20 #include "llvm/CodeGen/SelectionDAGISel.h" 21 #include "llvm/Target/TargetMachine.h" 22 23 using namespace llvm; 24 25 namespace { 26 27 static inline bool isNullConstantOrUndef(SDValue V) { 28 return V.isUndef() || isNullConstant(V); 29 } 30 31 static inline bool getConstantValue(SDValue N, uint32_t &Out) { 32 // This is only used for packed vectors, where using 0 for undef should 33 // always be good. 34 if (N.isUndef()) { 35 Out = 0; 36 return true; 37 } 38 39 if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) { 40 Out = C->getAPIntValue().getSExtValue(); 41 return true; 42 } 43 44 if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N)) { 45 Out = C->getValueAPF().bitcastToAPInt().getSExtValue(); 46 return true; 47 } 48 49 return false; 50 } 51 52 // TODO: Handle undef as zero 53 static inline SDNode *packConstantV2I16(const SDNode *N, SelectionDAG &DAG) { 54 assert(N->getOpcode() == ISD::BUILD_VECTOR && N->getNumOperands() == 2); 55 uint32_t LHSVal, RHSVal; 56 if (getConstantValue(N->getOperand(0), LHSVal) && 57 getConstantValue(N->getOperand(1), RHSVal)) { 58 SDLoc SL(N); 59 uint32_t K = (LHSVal & 0xffff) | (RHSVal << 16); 60 return DAG.getMachineNode(AMDGPU::S_MOV_B32, SL, N->getValueType(0), 61 DAG.getTargetConstant(K, SL, MVT::i32)); 62 } 63 64 return nullptr; 65 } 66 67 } // namespace 68 69 /// AMDGPU specific code to select AMDGPU machine instructions for 70 /// SelectionDAG operations. 71 class AMDGPUDAGToDAGISel : public SelectionDAGISel { 72 // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can 73 // make the right decision when generating code for different targets. 74 const GCNSubtarget *Subtarget; 75 76 // Default FP mode for the current function. 77 SIModeRegisterDefaults Mode; 78 79 bool EnableLateStructurizeCFG; 80 81 // Instructions that will be lowered with a final instruction that zeros the 82 // high result bits. 83 bool fp16SrcZerosHighBits(unsigned Opc) const; 84 85 public: 86 static char ID; 87 88 AMDGPUDAGToDAGISel() = delete; 89 90 explicit AMDGPUDAGToDAGISel(TargetMachine &TM, CodeGenOptLevel OptLevel); 91 ~AMDGPUDAGToDAGISel() override = default; 92 93 void getAnalysisUsage(AnalysisUsage &AU) const override; 94 95 bool matchLoadD16FromBuildVector(SDNode *N) const; 96 97 bool runOnMachineFunction(MachineFunction &MF) override; 98 void PreprocessISelDAG() override; 99 void Select(SDNode *N) override; 100 StringRef getPassName() const override; 101 void PostprocessISelDAG() override; 102 103 protected: 104 void SelectBuildVector(SDNode *N, unsigned RegClassID); 105 106 private: 107 std::pair<SDValue, SDValue> foldFrameIndex(SDValue N) const; 108 bool isInlineImmediate(const SDNode *N) const; 109 110 bool isInlineImmediate16(int64_t Imm) const { 111 return AMDGPU::isInlinableLiteral16(Imm, Subtarget->hasInv2PiInlineImm()); 112 } 113 114 bool isInlineImmediate32(int64_t Imm) const { 115 return AMDGPU::isInlinableLiteral32(Imm, Subtarget->hasInv2PiInlineImm()); 116 } 117 118 bool isInlineImmediate64(int64_t Imm) const { 119 return AMDGPU::isInlinableLiteral64(Imm, Subtarget->hasInv2PiInlineImm()); 120 } 121 122 bool isInlineImmediate(const APFloat &Imm) const { 123 return Subtarget->getInstrInfo()->isInlineConstant(Imm); 124 } 125 126 bool isVGPRImm(const SDNode *N) const; 127 bool isUniformLoad(const SDNode *N) const; 128 bool isUniformBr(const SDNode *N) const; 129 130 // Returns true if ISD::AND SDNode `N`'s masking of the shift amount operand's 131 // `ShAmtBits` bits is unneeded. 132 bool isUnneededShiftMask(const SDNode *N, unsigned ShAmtBits) const; 133 134 bool isBaseWithConstantOffset64(SDValue Addr, SDValue &LHS, 135 SDValue &RHS) const; 136 137 MachineSDNode *buildSMovImm64(SDLoc &DL, uint64_t Val, EVT VT) const; 138 139 SDNode *glueCopyToOp(SDNode *N, SDValue NewChain, SDValue Glue) const; 140 SDNode *glueCopyToM0(SDNode *N, SDValue Val) const; 141 SDNode *glueCopyToM0LDSInit(SDNode *N) const; 142 143 const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const; 144 virtual bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset); 145 virtual bool SelectADDRIndirect(SDValue Addr, SDValue &Base, SDValue &Offset); 146 bool isDSOffsetLegal(SDValue Base, unsigned Offset) const; 147 bool isDSOffset2Legal(SDValue Base, unsigned Offset0, unsigned Offset1, 148 unsigned Size) const; 149 150 bool isFlatScratchBaseLegal(SDValue Addr) const; 151 bool isFlatScratchBaseLegalSV(SDValue Addr) const; 152 bool isFlatScratchBaseLegalSVImm(SDValue Addr) const; 153 154 bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const; 155 bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0, 156 SDValue &Offset1) const; 157 bool SelectDS128Bit8ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0, 158 SDValue &Offset1) const; 159 bool SelectDSReadWrite2(SDValue Ptr, SDValue &Base, SDValue &Offset0, 160 SDValue &Offset1, unsigned Size) const; 161 bool SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr, 162 SDValue &SOffset, SDValue &Offset, SDValue &Offen, 163 SDValue &Idxen, SDValue &Addr64) const; 164 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr, 165 SDValue &SOffset, SDValue &Offset) const; 166 bool SelectMUBUFScratchOffen(SDNode *Parent, SDValue Addr, SDValue &RSrc, 167 SDValue &VAddr, SDValue &SOffset, 168 SDValue &ImmOffset) const; 169 bool SelectMUBUFScratchOffset(SDNode *Parent, SDValue Addr, SDValue &SRsrc, 170 SDValue &Soffset, SDValue &Offset) const; 171 172 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset, 173 SDValue &Offset) const; 174 bool SelectBUFSOffset(SDValue Addr, SDValue &SOffset) const; 175 176 bool SelectFlatOffsetImpl(SDNode *N, SDValue Addr, SDValue &VAddr, 177 SDValue &Offset, uint64_t FlatVariant) const; 178 bool SelectFlatOffset(SDNode *N, SDValue Addr, SDValue &VAddr, 179 SDValue &Offset) const; 180 bool SelectGlobalOffset(SDNode *N, SDValue Addr, SDValue &VAddr, 181 SDValue &Offset) const; 182 bool SelectScratchOffset(SDNode *N, SDValue Addr, SDValue &VAddr, 183 SDValue &Offset) const; 184 bool SelectGlobalSAddr(SDNode *N, SDValue Addr, SDValue &SAddr, 185 SDValue &VOffset, SDValue &Offset) const; 186 bool SelectScratchSAddr(SDNode *N, SDValue Addr, SDValue &SAddr, 187 SDValue &Offset) const; 188 bool checkFlatScratchSVSSwizzleBug(SDValue VAddr, SDValue SAddr, 189 uint64_t ImmOffset) const; 190 bool SelectScratchSVAddr(SDNode *N, SDValue Addr, SDValue &VAddr, 191 SDValue &SAddr, SDValue &Offset) const; 192 193 bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue *SOffset, 194 SDValue *Offset, bool Imm32Only = false, 195 bool IsBuffer = false) const; 196 SDValue Expand32BitAddress(SDValue Addr) const; 197 bool SelectSMRDBaseOffset(SDValue Addr, SDValue &SBase, SDValue *SOffset, 198 SDValue *Offset, bool Imm32Only = false, 199 bool IsBuffer = false) const; 200 bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue *SOffset, 201 SDValue *Offset, bool Imm32Only = false) const; 202 bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 203 bool SelectSMRDImm32(SDValue Addr, SDValue &SBase, SDValue &Offset) const; 204 bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &SOffset) const; 205 bool SelectSMRDSgprImm(SDValue Addr, SDValue &SBase, SDValue &SOffset, 206 SDValue &Offset) const; 207 bool SelectSMRDBufferImm(SDValue N, SDValue &Offset) const; 208 bool SelectSMRDBufferImm32(SDValue N, SDValue &Offset) const; 209 bool SelectSMRDBufferSgprImm(SDValue N, SDValue &SOffset, 210 SDValue &Offset) const; 211 bool SelectMOVRELOffset(SDValue Index, SDValue &Base, SDValue &Offset) const; 212 213 bool SelectVOP3ModsImpl(SDValue In, SDValue &Src, unsigned &SrcMods, 214 bool IsCanonicalizing = true, 215 bool AllowAbs = true) const; 216 bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 217 bool SelectVOP3ModsNonCanonicalizing(SDValue In, SDValue &Src, 218 SDValue &SrcMods) const; 219 bool SelectVOP3BMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 220 bool SelectVOP3NoMods(SDValue In, SDValue &Src) const; 221 bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods, 222 SDValue &Clamp, SDValue &Omod) const; 223 bool SelectVOP3BMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 224 SDValue &Clamp, SDValue &Omod) const; 225 bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods, 226 SDValue &Clamp, SDValue &Omod) const; 227 228 bool SelectVINTERPModsImpl(SDValue In, SDValue &Src, SDValue &SrcMods, 229 bool OpSel) const; 230 bool SelectVINTERPMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 231 bool SelectVINTERPModsHi(SDValue In, SDValue &Src, SDValue &SrcMods) const; 232 233 bool SelectVOP3OMods(SDValue In, SDValue &Src, SDValue &Clamp, 234 SDValue &Omod) const; 235 236 bool SelectVOP3PMods(SDValue In, SDValue &Src, SDValue &SrcMods, 237 bool IsDOT = false) const; 238 bool SelectVOP3PModsDOT(SDValue In, SDValue &Src, SDValue &SrcMods) const; 239 240 bool SelectDotIUVOP3PMods(SDValue In, SDValue &Src) const; 241 bool SelectWMMAOpSelVOP3PMods(SDValue In, SDValue &Src) const; 242 243 bool SelectVOP3OpSel(SDValue In, SDValue &Src, SDValue &SrcMods) const; 244 245 bool SelectVOP3OpSelMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 246 bool SelectVOP3PMadMixModsImpl(SDValue In, SDValue &Src, 247 unsigned &Mods) const; 248 bool SelectVOP3PMadMixModsExt(SDValue In, SDValue &Src, 249 SDValue &SrcMods) const; 250 bool SelectVOP3PMadMixMods(SDValue In, SDValue &Src, SDValue &SrcMods) const; 251 252 SDValue getHi16Elt(SDValue In) const; 253 254 SDValue getMaterializedScalarImm32(int64_t Val, const SDLoc &DL) const; 255 256 void SelectADD_SUB_I64(SDNode *N); 257 void SelectAddcSubb(SDNode *N); 258 void SelectUADDO_USUBO(SDNode *N); 259 void SelectDIV_SCALE(SDNode *N); 260 void SelectMAD_64_32(SDNode *N); 261 void SelectMUL_LOHI(SDNode *N); 262 void SelectFMA_W_CHAIN(SDNode *N); 263 void SelectFMUL_W_CHAIN(SDNode *N); 264 SDNode *getBFE32(bool IsSigned, const SDLoc &DL, SDValue Val, uint32_t Offset, 265 uint32_t Width); 266 void SelectS_BFEFromShifts(SDNode *N); 267 void SelectS_BFE(SDNode *N); 268 bool isCBranchSCC(const SDNode *N) const; 269 void SelectBRCOND(SDNode *N); 270 void SelectFMAD_FMA(SDNode *N); 271 void SelectFP_EXTEND(SDNode *N); 272 void SelectDSAppendConsume(SDNode *N, unsigned IntrID); 273 void SelectDSBvhStackIntrinsic(SDNode *N); 274 void SelectDS_GWS(SDNode *N, unsigned IntrID); 275 void SelectInterpP1F16(SDNode *N); 276 void SelectINTRINSIC_W_CHAIN(SDNode *N); 277 void SelectINTRINSIC_WO_CHAIN(SDNode *N); 278 void SelectINTRINSIC_VOID(SDNode *N); 279 void SelectWAVE_ADDRESS(SDNode *N); 280 void SelectSTACKRESTORE(SDNode *N); 281 282 protected: 283 // Include the pieces autogenerated from the target description. 284 #include "AMDGPUGenDAGISel.inc" 285 }; 286 287 #endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUISELDAGTODAG_H 288