Path: blob/main/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.h
35269 views
//===-- AMDGPUISelDAGToDAG.h - A dag to dag inst selector for AMDGPU ----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//==-----------------------------------------------------------------------===//7//8/// \file9/// Defines an instruction selector for the AMDGPU target.10//11//===----------------------------------------------------------------------===//1213#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUISELDAGTODAG_H14#define LLVM_LIB_TARGET_AMDGPU_AMDGPUISELDAGTODAG_H1516#include "GCNSubtarget.h"17#include "SIMachineFunctionInfo.h"18#include "SIModeRegisterDefaults.h"19#include "llvm/CodeGen/SelectionDAGISel.h"20#include "llvm/Target/TargetMachine.h"2122using namespace llvm;2324namespace {2526static inline bool getConstantValue(SDValue N, uint32_t &Out) {27// This is only used for packed vectors, where using 0 for undef should28// always be good.29if (N.isUndef()) {30Out = 0;31return true;32}3334if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N)) {35Out = C->getAPIntValue().getSExtValue();36return true;37}3839if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(N)) {40Out = C->getValueAPF().bitcastToAPInt().getSExtValue();41return true;42}4344return false;45}4647// TODO: Handle undef as zero48static inline SDNode *packConstantV2I16(const SDNode *N, SelectionDAG &DAG) {49assert(N->getOpcode() == ISD::BUILD_VECTOR && N->getNumOperands() == 2);50uint32_t LHSVal, RHSVal;51if (getConstantValue(N->getOperand(0), LHSVal) &&52getConstantValue(N->getOperand(1), RHSVal)) {53SDLoc SL(N);54uint32_t K = (LHSVal & 0xffff) | (RHSVal << 16);55return DAG.getMachineNode(AMDGPU::S_MOV_B32, SL, N->getValueType(0),56DAG.getTargetConstant(K, SL, MVT::i32));57}5859return nullptr;60}6162} // namespace6364/// AMDGPU specific code to select AMDGPU machine instructions for65/// SelectionDAG operations.66class AMDGPUDAGToDAGISel : public SelectionDAGISel {67// Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can68// make the right decision when generating code for different targets.69const GCNSubtarget *Subtarget;7071// Default FP mode for the current function.72SIModeRegisterDefaults Mode;7374bool EnableLateStructurizeCFG;7576// Instructions that will be lowered with a final instruction that zeros the77// high result bits.78bool fp16SrcZerosHighBits(unsigned Opc) const;7980public:81AMDGPUDAGToDAGISel() = delete;8283explicit AMDGPUDAGToDAGISel(TargetMachine &TM, CodeGenOptLevel OptLevel);8485bool runOnMachineFunction(MachineFunction &MF) override;86bool matchLoadD16FromBuildVector(SDNode *N) const;87void PreprocessISelDAG() override;88void Select(SDNode *N) override;89void PostprocessISelDAG() override;9091protected:92void SelectBuildVector(SDNode *N, unsigned RegClassID);9394private:95std::pair<SDValue, SDValue> foldFrameIndex(SDValue N) const;9697bool isInlineImmediate(const SDNode *N) const;9899bool isInlineImmediate(const APInt &Imm) const {100return Subtarget->getInstrInfo()->isInlineConstant(Imm);101}102103bool isInlineImmediate(const APFloat &Imm) const {104return Subtarget->getInstrInfo()->isInlineConstant(Imm);105}106107bool isVGPRImm(const SDNode *N) const;108bool isUniformLoad(const SDNode *N) const;109bool isUniformBr(const SDNode *N) const;110111// Returns true if ISD::AND SDNode `N`'s masking of the shift amount operand's112// `ShAmtBits` bits is unneeded.113bool isUnneededShiftMask(const SDNode *N, unsigned ShAmtBits) const;114115bool isBaseWithConstantOffset64(SDValue Addr, SDValue &LHS,116SDValue &RHS) const;117118MachineSDNode *buildSMovImm64(SDLoc &DL, uint64_t Val, EVT VT) const;119120SDNode *glueCopyToOp(SDNode *N, SDValue NewChain, SDValue Glue) const;121SDNode *glueCopyToM0(SDNode *N, SDValue Val) const;122SDNode *glueCopyToM0LDSInit(SDNode *N) const;123124const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const;125virtual bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset);126virtual bool SelectADDRIndirect(SDValue Addr, SDValue &Base, SDValue &Offset);127bool isDSOffsetLegal(SDValue Base, unsigned Offset) const;128bool isDSOffset2Legal(SDValue Base, unsigned Offset0, unsigned Offset1,129unsigned Size) const;130131bool isFlatScratchBaseLegal(SDValue Addr) const;132bool isFlatScratchBaseLegalSV(SDValue Addr) const;133bool isFlatScratchBaseLegalSVImm(SDValue Addr) const;134bool isSOffsetLegalWithImmOffset(SDValue *SOffset, bool Imm32Only,135bool IsBuffer, int64_t ImmOffset = 0) const;136137bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const;138bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0,139SDValue &Offset1) const;140bool SelectDS128Bit8ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0,141SDValue &Offset1) const;142bool SelectDSReadWrite2(SDValue Ptr, SDValue &Base, SDValue &Offset0,143SDValue &Offset1, unsigned Size) const;144bool SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,145SDValue &SOffset, SDValue &Offset, SDValue &Offen,146SDValue &Idxen, SDValue &Addr64) const;147bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,148SDValue &SOffset, SDValue &Offset) const;149bool SelectMUBUFScratchOffen(SDNode *Parent, SDValue Addr, SDValue &RSrc,150SDValue &VAddr, SDValue &SOffset,151SDValue &ImmOffset) const;152bool SelectMUBUFScratchOffset(SDNode *Parent, SDValue Addr, SDValue &SRsrc,153SDValue &Soffset, SDValue &Offset) const;154155bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset,156SDValue &Offset) const;157bool SelectBUFSOffset(SDValue Addr, SDValue &SOffset) const;158159bool SelectFlatOffsetImpl(SDNode *N, SDValue Addr, SDValue &VAddr,160SDValue &Offset, uint64_t FlatVariant) const;161bool SelectFlatOffset(SDNode *N, SDValue Addr, SDValue &VAddr,162SDValue &Offset) const;163bool SelectGlobalOffset(SDNode *N, SDValue Addr, SDValue &VAddr,164SDValue &Offset) const;165bool SelectScratchOffset(SDNode *N, SDValue Addr, SDValue &VAddr,166SDValue &Offset) const;167bool SelectGlobalSAddr(SDNode *N, SDValue Addr, SDValue &SAddr,168SDValue &VOffset, SDValue &Offset) const;169bool SelectScratchSAddr(SDNode *N, SDValue Addr, SDValue &SAddr,170SDValue &Offset) const;171bool checkFlatScratchSVSSwizzleBug(SDValue VAddr, SDValue SAddr,172uint64_t ImmOffset) const;173bool SelectScratchSVAddr(SDNode *N, SDValue Addr, SDValue &VAddr,174SDValue &SAddr, SDValue &Offset) const;175176bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue *SOffset,177SDValue *Offset, bool Imm32Only = false,178bool IsBuffer = false, bool HasSOffset = false,179int64_t ImmOffset = 0) const;180SDValue Expand32BitAddress(SDValue Addr) const;181bool SelectSMRDBaseOffset(SDValue Addr, SDValue &SBase, SDValue *SOffset,182SDValue *Offset, bool Imm32Only = false,183bool IsBuffer = false, bool HasSOffset = false,184int64_t ImmOffset = 0) const;185bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue *SOffset,186SDValue *Offset, bool Imm32Only = false) const;187bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const;188bool SelectSMRDImm32(SDValue Addr, SDValue &SBase, SDValue &Offset) const;189bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &SOffset) const;190bool SelectSMRDSgprImm(SDValue Addr, SDValue &SBase, SDValue &SOffset,191SDValue &Offset) const;192bool SelectSMRDBufferImm(SDValue N, SDValue &Offset) const;193bool SelectSMRDBufferImm32(SDValue N, SDValue &Offset) const;194bool SelectSMRDBufferSgprImm(SDValue N, SDValue &SOffset,195SDValue &Offset) const;196bool SelectSMRDPrefetchImm(SDValue Addr, SDValue &SBase,197SDValue &Offset) const;198bool SelectMOVRELOffset(SDValue Index, SDValue &Base, SDValue &Offset) const;199200bool SelectVOP3ModsImpl(SDValue In, SDValue &Src, unsigned &SrcMods,201bool IsCanonicalizing = true,202bool AllowAbs = true) const;203bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const;204bool SelectVOP3ModsNonCanonicalizing(SDValue In, SDValue &Src,205SDValue &SrcMods) const;206bool SelectVOP3BMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;207bool SelectVOP3NoMods(SDValue In, SDValue &Src) const;208bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods,209SDValue &Clamp, SDValue &Omod) const;210bool SelectVOP3BMods0(SDValue In, SDValue &Src, SDValue &SrcMods,211SDValue &Clamp, SDValue &Omod) const;212bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods,213SDValue &Clamp, SDValue &Omod) const;214215bool SelectVINTERPModsImpl(SDValue In, SDValue &Src, SDValue &SrcMods,216bool OpSel) const;217bool SelectVINTERPMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;218bool SelectVINTERPModsHi(SDValue In, SDValue &Src, SDValue &SrcMods) const;219220bool SelectVOP3OMods(SDValue In, SDValue &Src, SDValue &Clamp,221SDValue &Omod) const;222223bool SelectVOP3PMods(SDValue In, SDValue &Src, SDValue &SrcMods,224bool IsDOT = false) const;225bool SelectVOP3PModsDOT(SDValue In, SDValue &Src, SDValue &SrcMods) const;226227bool SelectVOP3PModsNeg(SDValue In, SDValue &Src) const;228bool SelectWMMAOpSelVOP3PMods(SDValue In, SDValue &Src) const;229230bool SelectWMMAModsF32NegAbs(SDValue In, SDValue &Src,231SDValue &SrcMods) const;232bool SelectWMMAModsF16Neg(SDValue In, SDValue &Src, SDValue &SrcMods) const;233bool SelectWMMAModsF16NegAbs(SDValue In, SDValue &Src,234SDValue &SrcMods) const;235bool SelectWMMAVISrc(SDValue In, SDValue &Src) const;236237bool SelectSWMMACIndex8(SDValue In, SDValue &Src, SDValue &IndexKey) const;238bool SelectSWMMACIndex16(SDValue In, SDValue &Src, SDValue &IndexKey) const;239240bool SelectVOP3OpSel(SDValue In, SDValue &Src, SDValue &SrcMods) const;241242bool SelectVOP3OpSelMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;243bool SelectVOP3PMadMixModsImpl(SDValue In, SDValue &Src,244unsigned &Mods) const;245bool SelectVOP3PMadMixModsExt(SDValue In, SDValue &Src,246SDValue &SrcMods) const;247bool SelectVOP3PMadMixMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;248249SDValue getHi16Elt(SDValue In) const;250251SDValue getMaterializedScalarImm32(int64_t Val, const SDLoc &DL) const;252253void SelectADD_SUB_I64(SDNode *N);254void SelectAddcSubb(SDNode *N);255void SelectUADDO_USUBO(SDNode *N);256void SelectDIV_SCALE(SDNode *N);257void SelectMAD_64_32(SDNode *N);258void SelectMUL_LOHI(SDNode *N);259void SelectFMA_W_CHAIN(SDNode *N);260void SelectFMUL_W_CHAIN(SDNode *N);261SDNode *getBFE32(bool IsSigned, const SDLoc &DL, SDValue Val, uint32_t Offset,262uint32_t Width);263void SelectS_BFEFromShifts(SDNode *N);264void SelectS_BFE(SDNode *N);265bool isCBranchSCC(const SDNode *N) const;266void SelectBRCOND(SDNode *N);267void SelectFMAD_FMA(SDNode *N);268void SelectFP_EXTEND(SDNode *N);269void SelectDSAppendConsume(SDNode *N, unsigned IntrID);270void SelectDSBvhStackIntrinsic(SDNode *N);271void SelectDS_GWS(SDNode *N, unsigned IntrID);272void SelectInterpP1F16(SDNode *N);273void SelectINTRINSIC_W_CHAIN(SDNode *N);274void SelectINTRINSIC_WO_CHAIN(SDNode *N);275void SelectINTRINSIC_VOID(SDNode *N);276void SelectWAVE_ADDRESS(SDNode *N);277void SelectSTACKRESTORE(SDNode *N);278279protected:280// Include the pieces autogenerated from the target description.281#include "AMDGPUGenDAGISel.inc"282};283284class AMDGPUISelDAGToDAGPass : public SelectionDAGISelPass {285public:286AMDGPUISelDAGToDAGPass(TargetMachine &TM);287288PreservedAnalyses run(MachineFunction &MF,289MachineFunctionAnalysisManager &MFAM);290};291292class AMDGPUDAGToDAGISelLegacy : public SelectionDAGISelLegacy {293public:294static char ID;295296AMDGPUDAGToDAGISelLegacy(TargetMachine &TM, CodeGenOptLevel OptLevel);297298bool runOnMachineFunction(MachineFunction &MF) override;299void getAnalysisUsage(AnalysisUsage &AU) const override;300StringRef getPassName() const override;301};302303#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUISELDAGTODAG_H304305306