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
158 bool isFlatScratchBaseLegal(SDValue Addr) const;
159 bool isFlatScratchBaseLegalSV(SDValue Addr) const;
160 bool isFlatScratchBaseLegalSVImm(SDValue Addr) const;
161
162 bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const;
163 bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0,
164 SDValue &Offset1) const;
165 bool SelectDS128Bit8ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0,
166 SDValue &Offset1) const;
167 bool SelectDSReadWrite2(SDValue Ptr, SDValue &Base, SDValue &Offset0,
168 SDValue &Offset1, unsigned Size) const;
169 bool SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,
170 SDValue &SOffset, SDValue &Offset, SDValue &Offen,
171 SDValue &Idxen, SDValue &Addr64) const;
172 bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,
173 SDValue &SOffset, SDValue &Offset) const;
174 bool SelectMUBUFScratchOffen(SDNode *Parent, SDValue Addr, SDValue &RSrc,
175 SDValue &VAddr, SDValue &SOffset,
176 SDValue &ImmOffset) const;
177 bool SelectMUBUFScratchOffset(SDNode *Parent, SDValue Addr, SDValue &SRsrc,
178 SDValue &Soffset, SDValue &Offset) const;
179
180 bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset,
181 SDValue &Offset) const;
182
183 bool SelectFlatOffsetImpl(SDNode *N, SDValue Addr, SDValue &VAddr,
184 SDValue &Offset, uint64_t FlatVariant) const;
185 bool SelectFlatOffset(SDNode *N, SDValue Addr, SDValue &VAddr,
186 SDValue &Offset) const;
187 bool SelectGlobalOffset(SDNode *N, SDValue Addr, SDValue &VAddr,
188 SDValue &Offset) const;
189 bool SelectScratchOffset(SDNode *N, SDValue Addr, SDValue &VAddr,
190 SDValue &Offset) const;
191 bool SelectGlobalSAddr(SDNode *N, SDValue Addr, SDValue &SAddr,
192 SDValue &VOffset, SDValue &Offset) const;
193 bool SelectScratchSAddr(SDNode *N, SDValue Addr, SDValue &SAddr,
194 SDValue &Offset) const;
195 bool checkFlatScratchSVSSwizzleBug(SDValue VAddr, SDValue SAddr,
196 uint64_t ImmOffset) const;
197 bool SelectScratchSVAddr(SDNode *N, SDValue Addr, SDValue &VAddr,
198 SDValue &SAddr, SDValue &Offset) const;
199
200 bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue *SOffset,
201 SDValue *Offset, bool Imm32Only = false,
202 bool IsBuffer = false) const;
203 SDValue Expand32BitAddress(SDValue Addr) const;
204 bool SelectSMRDBaseOffset(SDValue Addr, SDValue &SBase, SDValue *SOffset,
205 SDValue *Offset, bool Imm32Only = false,
206 bool IsBuffer = false) const;
207 bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue *SOffset,
208 SDValue *Offset, bool Imm32Only = false) const;
209 bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
210 bool SelectSMRDImm32(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
211 bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &SOffset) const;
212 bool SelectSMRDSgprImm(SDValue Addr, SDValue &SBase, SDValue &SOffset,
213 SDValue &Offset) const;
214 bool SelectSMRDBufferImm(SDValue N, SDValue &Offset) const;
215 bool SelectSMRDBufferImm32(SDValue N, SDValue &Offset) const;
216 bool SelectSMRDBufferSgprImm(SDValue N, SDValue &SOffset,
217 SDValue &Offset) const;
218 bool SelectMOVRELOffset(SDValue Index, SDValue &Base, SDValue &Offset) const;
219
220 bool SelectVOP3ModsImpl(SDValue In, SDValue &Src, unsigned &SrcMods,
221 bool IsCanonicalizing = true,
222 bool AllowAbs = true) const;
223 bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
224 bool SelectVOP3ModsNonCanonicalizing(SDValue In, SDValue &Src,
225 SDValue &SrcMods) const;
226 bool SelectVOP3BMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
227 bool SelectVOP3NoMods(SDValue In, SDValue &Src) const;
228 bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods,
229 SDValue &Clamp, SDValue &Omod) const;
230 bool SelectVOP3BMods0(SDValue In, SDValue &Src, SDValue &SrcMods,
231 SDValue &Clamp, SDValue &Omod) const;
232 bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods,
233 SDValue &Clamp, SDValue &Omod) const;
234
235 bool SelectVINTERPModsImpl(SDValue In, SDValue &Src, SDValue &SrcMods,
236 bool OpSel) const;
237 bool SelectVINTERPMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
238 bool SelectVINTERPModsHi(SDValue In, SDValue &Src, SDValue &SrcMods) const;
239
240 bool SelectVOP3OMods(SDValue In, SDValue &Src, SDValue &Clamp,
241 SDValue &Omod) const;
242
243 bool SelectVOP3PMods(SDValue In, SDValue &Src, SDValue &SrcMods,
244 bool IsDOT = false) const;
245 bool SelectVOP3PModsDOT(SDValue In, SDValue &Src, SDValue &SrcMods) const;
246
247 bool SelectDotIUVOP3PMods(SDValue In, SDValue &Src) const;
248 bool SelectWMMAOpSelVOP3PMods(SDValue In, SDValue &Src) const;
249
250 bool SelectVOP3OpSel(SDValue In, SDValue &Src, SDValue &SrcMods) const;
251
252 bool SelectVOP3OpSelMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
253 bool SelectVOP3PMadMixModsImpl(SDValue In, SDValue &Src,
254 unsigned &Mods) const;
255 bool SelectVOP3PMadMixModsExt(SDValue In, SDValue &Src,
256 SDValue &SrcMods) const;
257 bool SelectVOP3PMadMixMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
258
259 SDValue getHi16Elt(SDValue In) const;
260
261 SDValue getMaterializedScalarImm32(int64_t Val, const SDLoc &DL) const;
262
263 void SelectADD_SUB_I64(SDNode *N);
264 void SelectAddcSubb(SDNode *N);
265 void SelectUADDO_USUBO(SDNode *N);
266 void SelectDIV_SCALE(SDNode *N);
267 void SelectMAD_64_32(SDNode *N);
268 void SelectMUL_LOHI(SDNode *N);
269 void SelectFMA_W_CHAIN(SDNode *N);
270 void SelectFMUL_W_CHAIN(SDNode *N);
271 SDNode *getBFE32(bool IsSigned, const SDLoc &DL, SDValue Val, uint32_t Offset,
272 uint32_t Width);
273 void SelectS_BFEFromShifts(SDNode *N);
274 void SelectS_BFE(SDNode *N);
275 bool isCBranchSCC(const SDNode *N) const;
276 void SelectBRCOND(SDNode *N);
277 void SelectFMAD_FMA(SDNode *N);
278 void SelectFP_EXTEND(SDNode *N);
279 void SelectDSAppendConsume(SDNode *N, unsigned IntrID);
280 void SelectDSBvhStackIntrinsic(SDNode *N);
281 void SelectDS_GWS(SDNode *N, unsigned IntrID);
282 void SelectInterpP1F16(SDNode *N);
283 void SelectINTRINSIC_W_CHAIN(SDNode *N);
284 void SelectINTRINSIC_WO_CHAIN(SDNode *N);
285 void SelectINTRINSIC_VOID(SDNode *N);
286 void SelectWAVE_ADDRESS(SDNode *N);
287 void SelectSTACKRESTORE(SDNode *N);
288
289protected:
290 // Include the pieces autogenerated from the target description.
291#include "AMDGPUGenDAGISel.inc"
292};
293
294#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:456
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