LLVM 18.0.0git
AMDGPUISelDAGToDAG.h
Go to the documentation of this file.
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"
22
23using namespace llvm;
24
25namespace {
26
27static inline bool isNullConstantOrUndef(SDValue V) {
28 return V.isUndef() || isNullConstant(V);
29}
30
31static 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
53static inline SDNode *packConstantV2I16(const SDNode *N, SelectionDAG &DAG,
54 bool Negate = false) {
55 assert(N->getOpcode() == ISD::BUILD_VECTOR && N->getNumOperands() == 2);
56 uint32_t LHSVal, RHSVal;
57 if (getConstantValue(N->getOperand(0), LHSVal) &&
58 getConstantValue(N->getOperand(1), RHSVal)) {
59 SDLoc SL(N);
60 uint32_t K = Negate ? (-LHSVal & 0xffff) | (-RHSVal << 16)
61 : (LHSVal & 0xffff) | (RHSVal << 16);
62 return DAG.getMachineNode(AMDGPU::S_MOV_B32, SL, N->getValueType(0),
63 DAG.getTargetConstant(K, SL, MVT::i32));
64 }
65
66 return nullptr;
67}
68
69static inline SDNode *packNegConstantV2I16(const SDNode *N, SelectionDAG &DAG) {
70 return packConstantV2I16(N, DAG, true);
71}
72} // namespace
73
74/// AMDGPU specific code to select AMDGPU machine instructions for
75/// SelectionDAG operations.
77 // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can
78 // make the right decision when generating code for different targets.
79 const GCNSubtarget *Subtarget;
80
81 // Default FP mode for the current function.
83
84 bool EnableLateStructurizeCFG;
85
86 // Instructions that will be lowered with a final instruction that zeros the
87 // high result bits.
88 bool fp16SrcZerosHighBits(unsigned Opc) const;
89
90public:
91 static char ID;
92
94
96 ~AMDGPUDAGToDAGISel() override = default;
97
98 void getAnalysisUsage(AnalysisUsage &AU) const override;
99
101
103 void PreprocessISelDAG() override;
104 void Select(SDNode *N) override;
105 StringRef getPassName() const override;
106 void PostprocessISelDAG() override;
107
108protected:
109 void SelectBuildVector(SDNode *N, unsigned RegClassID);
110
111private:
112 std::pair<SDValue, SDValue> foldFrameIndex(SDValue N) const;
113 bool isInlineImmediate(const SDNode *N, bool Negated = false) const;
114 bool isNegInlineImmediate(const SDNode *N) const {
115 return isInlineImmediate(N, true);
116 }
117
118 bool isInlineImmediate16(int64_t Imm) const {
119 return AMDGPU::isInlinableLiteral16(Imm, Subtarget->hasInv2PiInlineImm());
120 }
121
122 bool isInlineImmediate32(int64_t Imm) const {
123 return AMDGPU::isInlinableLiteral32(Imm, Subtarget->hasInv2PiInlineImm());
124 }
125
126 bool isInlineImmediate64(int64_t Imm) const {
127 return AMDGPU::isInlinableLiteral64(Imm, Subtarget->hasInv2PiInlineImm());
128 }
129
130 bool isInlineImmediate(const APFloat &Imm) const {
131 return Subtarget->getInstrInfo()->isInlineConstant(Imm);
132 }
133
134 bool isVGPRImm(const SDNode *N) const;
135 bool isUniformLoad(const SDNode *N) const;
136 bool isUniformBr(const SDNode *N) const;
137
138 // Returns true if ISD::AND SDNode `N`'s masking of the shift amount operand's
139 // `ShAmtBits` bits is unneeded.
140 bool isUnneededShiftMask(const SDNode *N, unsigned ShAmtBits) const;
141
142 bool isBaseWithConstantOffset64(SDValue Addr, SDValue &LHS,
143 SDValue &RHS) const;
144
145 MachineSDNode *buildSMovImm64(SDLoc &DL, uint64_t Val, EVT VT) const;
146
147 SDNode *glueCopyToOp(SDNode *N, SDValue NewChain, SDValue Glue) const;
148 SDNode *glueCopyToM0(SDNode *N, SDValue Val) const;
149 SDNode *glueCopyToM0LDSInit(SDNode *N) const;
150
151 const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const;
152 virtual bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset);
153 virtual bool SelectADDRIndirect(SDValue Addr, SDValue &Base, SDValue &Offset);
154 bool isDSOffsetLegal(SDValue Base, unsigned Offset) const;
155 bool isDSOffset2Legal(SDValue Base, unsigned Offset0, unsigned Offset1,
156 unsigned Size) const;
157 bool isFlatScratchBaseLegal(
158 SDValue Base, uint64_t FlatVariant = SIInstrFlags::FlatScratch) const;
159
160 bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const;
161 bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0,
162 SDValue &Offset1) const;
163 bool SelectDS128Bit8ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0,
164 SDValue &Offset1) const;
165 bool SelectDSReadWrite2(SDValue Ptr, SDValue &Base, SDValue &Offset0,
166 SDValue &Offset1, unsigned Size) const;
167 bool SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,
168 SDValue &SOffset, SDValue &Offset, SDValue &Offen,
169 SDValue &Idxen, SDValue &Addr64) const;
170 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,
171 SDValue &SOffset, SDValue &Offset) const;
172 bool SelectMUBUFScratchOffen(SDNode *Parent, SDValue Addr, SDValue &RSrc,
173 SDValue &VAddr, SDValue &SOffset,
174 SDValue &ImmOffset) const;
175 bool SelectMUBUFScratchOffset(SDNode *Parent, SDValue Addr, SDValue &SRsrc,
176 SDValue &Soffset, SDValue &Offset) const;
177
178 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset,
179 SDValue &Offset) const;
180
181 bool SelectFlatOffsetImpl(SDNode *N, SDValue Addr, SDValue &VAddr,
182 SDValue &Offset, uint64_t FlatVariant) const;
183 bool SelectFlatOffset(SDNode *N, SDValue Addr, SDValue &VAddr,
184 SDValue &Offset) const;
185 bool SelectGlobalOffset(SDNode *N, SDValue Addr, SDValue &VAddr,
186 SDValue &Offset) const;
187 bool SelectScratchOffset(SDNode *N, SDValue Addr, SDValue &VAddr,
188 SDValue &Offset) const;
189 bool SelectGlobalSAddr(SDNode *N, SDValue Addr, SDValue &SAddr,
190 SDValue &VOffset, SDValue &Offset) const;
191 bool SelectScratchSAddr(SDNode *N, SDValue Addr, SDValue &SAddr,
192 SDValue &Offset) const;
193 bool checkFlatScratchSVSSwizzleBug(SDValue VAddr, SDValue SAddr,
194 uint64_t ImmOffset) const;
195 bool SelectScratchSVAddr(SDNode *N, SDValue Addr, SDValue &VAddr,
196 SDValue &SAddr, SDValue &Offset) const;
197
198 bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue *SOffset,
199 SDValue *Offset, bool Imm32Only = false,
200 bool IsBuffer = false) const;
201 SDValue Expand32BitAddress(SDValue Addr) const;
202 bool SelectSMRDBaseOffset(SDValue Addr, SDValue &SBase, SDValue *SOffset,
203 SDValue *Offset, bool Imm32Only = false,
204 bool IsBuffer = false) const;
205 bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue *SOffset,
206 SDValue *Offset, bool Imm32Only = false) const;
207 bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
208 bool SelectSMRDImm32(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
209 bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &SOffset) const;
210 bool SelectSMRDSgprImm(SDValue Addr, SDValue &SBase, SDValue &SOffset,
211 SDValue &Offset) const;
212 bool SelectSMRDBufferImm(SDValue N, SDValue &Offset) const;
213 bool SelectSMRDBufferImm32(SDValue N, SDValue &Offset) const;
214 bool SelectSMRDBufferSgprImm(SDValue N, SDValue &SOffset,
215 SDValue &Offset) const;
216 bool SelectMOVRELOffset(SDValue Index, SDValue &Base, SDValue &Offset) const;
217
218 bool SelectVOP3ModsImpl(SDValue In, SDValue &Src, unsigned &SrcMods,
219 bool IsCanonicalizing = true,
220 bool AllowAbs = true) const;
221 bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
222 bool SelectVOP3ModsNonCanonicalizing(SDValue In, SDValue &Src,
223 SDValue &SrcMods) const;
224 bool SelectVOP3BMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
225 bool SelectVOP3NoMods(SDValue In, SDValue &Src) const;
226 bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods,
227 SDValue &Clamp, SDValue &Omod) const;
228 bool SelectVOP3BMods0(SDValue In, SDValue &Src, SDValue &SrcMods,
229 SDValue &Clamp, SDValue &Omod) const;
230 bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods,
231 SDValue &Clamp, SDValue &Omod) const;
232
233 bool SelectVINTERPModsImpl(SDValue In, SDValue &Src, SDValue &SrcMods,
234 bool OpSel) const;
235 bool SelectVINTERPMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
236 bool SelectVINTERPModsHi(SDValue In, SDValue &Src, SDValue &SrcMods) const;
237
238 bool SelectVOP3OMods(SDValue In, SDValue &Src, SDValue &Clamp,
239 SDValue &Omod) const;
240
241 bool SelectVOP3PMods(SDValue In, SDValue &Src, SDValue &SrcMods,
242 bool IsDOT = false) const;
243 bool SelectVOP3PModsDOT(SDValue In, SDValue &Src, SDValue &SrcMods) const;
244
245 bool SelectDotIUVOP3PMods(SDValue In, SDValue &Src) const;
246 bool SelectWMMAOpSelVOP3PMods(SDValue In, SDValue &Src) const;
247
248 bool SelectVOP3OpSel(SDValue In, SDValue &Src, SDValue &SrcMods) const;
249
250 bool SelectVOP3OpSelMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
251 bool SelectVOP3PMadMixModsImpl(SDValue In, SDValue &Src,
252 unsigned &Mods) const;
253 bool SelectVOP3PMadMixModsExt(SDValue In, SDValue &Src,
254 SDValue &SrcMods) const;
255 bool SelectVOP3PMadMixMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
256
257 SDValue getHi16Elt(SDValue In) const;
258
259 SDValue getMaterializedScalarImm32(int64_t Val, const SDLoc &DL) const;
260
261 void SelectADD_SUB_I64(SDNode *N);
262 void SelectAddcSubb(SDNode *N);
263 void SelectUADDO_USUBO(SDNode *N);
264 void SelectDIV_SCALE(SDNode *N);
265 void SelectMAD_64_32(SDNode *N);
266 void SelectMUL_LOHI(SDNode *N);
267 void SelectFMA_W_CHAIN(SDNode *N);
268 void SelectFMUL_W_CHAIN(SDNode *N);
269 SDNode *getBFE32(bool IsSigned, const SDLoc &DL, SDValue Val, uint32_t Offset,
270 uint32_t Width);
271 void SelectS_BFEFromShifts(SDNode *N);
272 void SelectS_BFE(SDNode *N);
273 bool isCBranchSCC(const SDNode *N) const;
274 void SelectBRCOND(SDNode *N);
275 void SelectFMAD_FMA(SDNode *N);
276 void SelectFP_EXTEND(SDNode *N);
277 void SelectDSAppendConsume(SDNode *N, unsigned IntrID);
278 void SelectDSBvhStackIntrinsic(SDNode *N);
279 void SelectDS_GWS(SDNode *N, unsigned IntrID);
280 void SelectInterpP1F16(SDNode *N);
281 void SelectINTRINSIC_W_CHAIN(SDNode *N);
282 void SelectINTRINSIC_WO_CHAIN(SDNode *N);
283 void SelectINTRINSIC_VOID(SDNode *N);
284 void SelectWAVE_ADDRESS(SDNode *N);
285 void SelectSTACKRESTORE(SDNode *N);
286
287protected:
288 // Include the pieces autogenerated from the target description.
289#include "AMDGPUGenDAGISel.inc"
290};
291
292#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUISELDAGTODAG_H
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu AMDGPU Register Bank Select
uint64_t Addr
uint64_t Size
AMD GCN specific subclass of TargetSubtarget.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
AMDGPU specific code to select AMDGPU machine instructions for SelectionDAG operations.
void SelectBuildVector(SDNode *N, unsigned RegClassID)
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
~AMDGPUDAGToDAGISel() override=default
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
void PostprocessISelDAG() override
PostprocessISelDAG() - This hook allows the target to hack on the graph right after selection.
StringRef getPassName() const override
getPassName - Return a nice clean name for a pass.
AMDGPUDAGToDAGISel()=delete
bool matchLoadD16FromBuildVector(SDNode *N) const
bool hasInv2PiInlineImm() const
Represent the analysis usage information of a pass.
const SIInstrInfo * getInstrInfo() const override
Definition: GCNSubtarget.h:237
An SDNode that represents everything that will be needed to construct a MachineInstr.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
bool isInlineConstant(const APInt &Imm) const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
MachineFunction * MF
CodeGenOptLevel OptLevel
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
Definition: SelectionDAG.h:225
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
Definition: SelectionDAG.h:674
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:78
bool isInlinableLiteral16(int16_t Literal, bool HasInv2Pi)
bool isInlinableLiteral32(int32_t Literal, bool HasInv2Pi)
bool isInlinableLiteral64(int64_t Literal, bool HasInv2Pi)
Is this literal inlinable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
Definition: ISDOpcodes.h:515
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
CodeGenOptLevel
Code generation optimization level.
Definition: CodeGen.h:54
#define N
Extended Value Type.
Definition: ValueTypes.h:34