1*9880d681SAndroid Build Coastguard Worker //===-- AMDGPUISelDAGToDAG.cpp - A dag to dag inst selector for AMDGPU ----===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //==-----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// \brief Defines an instruction selector for the AMDGPU target.
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "AMDGPUInstrInfo.h"
16*9880d681SAndroid Build Coastguard Worker #include "AMDGPUIntrinsicInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "AMDGPUISelLowering.h" // For AMDGPUISD
18*9880d681SAndroid Build Coastguard Worker #include "AMDGPUSubtarget.h"
19*9880d681SAndroid Build Coastguard Worker #include "SIISelLowering.h"
20*9880d681SAndroid Build Coastguard Worker #include "SIMachineFunctionInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/FunctionLoweringInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/PseudoSourceValue.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAG.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAGISel.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DiagnosticInfo.h"
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker using namespace llvm;
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker namespace llvm {
32*9880d681SAndroid Build Coastguard Worker class R600InstrInfo;
33*9880d681SAndroid Build Coastguard Worker }
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
36*9880d681SAndroid Build Coastguard Worker // Instruction Selector Implementation
37*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker namespace {
40*9880d681SAndroid Build Coastguard Worker
isCBranchSCC(const SDNode * N)41*9880d681SAndroid Build Coastguard Worker static bool isCBranchSCC(const SDNode *N) {
42*9880d681SAndroid Build Coastguard Worker assert(N->getOpcode() == ISD::BRCOND);
43*9880d681SAndroid Build Coastguard Worker if (!N->hasOneUse())
44*9880d681SAndroid Build Coastguard Worker return false;
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker SDValue Cond = N->getOperand(1);
47*9880d681SAndroid Build Coastguard Worker if (Cond.getOpcode() == ISD::CopyToReg)
48*9880d681SAndroid Build Coastguard Worker Cond = Cond.getOperand(2);
49*9880d681SAndroid Build Coastguard Worker return Cond.getOpcode() == ISD::SETCC &&
50*9880d681SAndroid Build Coastguard Worker Cond.getOperand(0).getValueType() == MVT::i32 && Cond.hasOneUse();
51*9880d681SAndroid Build Coastguard Worker }
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker /// AMDGPU specific code to select AMDGPU machine instructions for
54*9880d681SAndroid Build Coastguard Worker /// SelectionDAG operations.
55*9880d681SAndroid Build Coastguard Worker class AMDGPUDAGToDAGISel : public SelectionDAGISel {
56*9880d681SAndroid Build Coastguard Worker // Subtarget - Keep a pointer to the AMDGPU Subtarget around so that we can
57*9880d681SAndroid Build Coastguard Worker // make the right decision when generating code for different targets.
58*9880d681SAndroid Build Coastguard Worker const AMDGPUSubtarget *Subtarget;
59*9880d681SAndroid Build Coastguard Worker
60*9880d681SAndroid Build Coastguard Worker public:
61*9880d681SAndroid Build Coastguard Worker AMDGPUDAGToDAGISel(TargetMachine &TM);
62*9880d681SAndroid Build Coastguard Worker virtual ~AMDGPUDAGToDAGISel();
63*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &MF) override;
64*9880d681SAndroid Build Coastguard Worker void Select(SDNode *N) override;
65*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override;
66*9880d681SAndroid Build Coastguard Worker void PreprocessISelDAG() override;
67*9880d681SAndroid Build Coastguard Worker void PostprocessISelDAG() override;
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker private:
70*9880d681SAndroid Build Coastguard Worker bool isInlineImmediate(SDNode *N) const;
71*9880d681SAndroid Build Coastguard Worker bool FoldOperand(SDValue &Src, SDValue &Sel, SDValue &Neg, SDValue &Abs,
72*9880d681SAndroid Build Coastguard Worker const R600InstrInfo *TII);
73*9880d681SAndroid Build Coastguard Worker bool FoldOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &);
74*9880d681SAndroid Build Coastguard Worker bool FoldDotOperands(unsigned, const R600InstrInfo *, std::vector<SDValue> &);
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker bool isConstantLoad(const MemSDNode *N, int cbID) const;
77*9880d681SAndroid Build Coastguard Worker bool isUniformBr(const SDNode *N) const;
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Worker SDNode *glueCopyToM0(SDNode *N) const;
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *getOperandRegClass(SDNode *N, unsigned OpNo) const;
82*9880d681SAndroid Build Coastguard Worker bool SelectGlobalValueConstantOffset(SDValue Addr, SDValue& IntPtr);
83*9880d681SAndroid Build Coastguard Worker bool SelectGlobalValueVariableOffset(SDValue Addr, SDValue &BaseReg,
84*9880d681SAndroid Build Coastguard Worker SDValue& Offset);
85*9880d681SAndroid Build Coastguard Worker bool SelectADDRVTX_READ(SDValue Addr, SDValue &Base, SDValue &Offset);
86*9880d681SAndroid Build Coastguard Worker bool SelectADDRIndirect(SDValue Addr, SDValue &Base, SDValue &Offset);
87*9880d681SAndroid Build Coastguard Worker bool isDSOffsetLegal(const SDValue &Base, unsigned Offset,
88*9880d681SAndroid Build Coastguard Worker unsigned OffsetBits) const;
89*9880d681SAndroid Build Coastguard Worker bool SelectDS1Addr1Offset(SDValue Ptr, SDValue &Base, SDValue &Offset) const;
90*9880d681SAndroid Build Coastguard Worker bool SelectDS64Bit4ByteAligned(SDValue Ptr, SDValue &Base, SDValue &Offset0,
91*9880d681SAndroid Build Coastguard Worker SDValue &Offset1) const;
92*9880d681SAndroid Build Coastguard Worker bool SelectMUBUF(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,
93*9880d681SAndroid Build Coastguard Worker SDValue &SOffset, SDValue &Offset, SDValue &Offen,
94*9880d681SAndroid Build Coastguard Worker SDValue &Idxen, SDValue &Addr64, SDValue &GLC, SDValue &SLC,
95*9880d681SAndroid Build Coastguard Worker SDValue &TFE) const;
96*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc, SDValue &VAddr,
97*9880d681SAndroid Build Coastguard Worker SDValue &SOffset, SDValue &Offset, SDValue &GLC,
98*9880d681SAndroid Build Coastguard Worker SDValue &SLC, SDValue &TFE) const;
99*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
100*9880d681SAndroid Build Coastguard Worker SDValue &VAddr, SDValue &SOffset, SDValue &Offset,
101*9880d681SAndroid Build Coastguard Worker SDValue &SLC) const;
102*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFScratch(SDValue Addr, SDValue &RSrc, SDValue &VAddr,
103*9880d681SAndroid Build Coastguard Worker SDValue &SOffset, SDValue &ImmOffset) const;
104*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &SOffset,
105*9880d681SAndroid Build Coastguard Worker SDValue &Offset, SDValue &GLC, SDValue &SLC,
106*9880d681SAndroid Build Coastguard Worker SDValue &TFE) const;
107*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset,
108*9880d681SAndroid Build Coastguard Worker SDValue &Offset, SDValue &SLC) const;
109*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc, SDValue &Soffset,
110*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const;
111*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFConstant(SDValue Constant,
112*9880d681SAndroid Build Coastguard Worker SDValue &SOffset,
113*9880d681SAndroid Build Coastguard Worker SDValue &ImmOffset) const;
114*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFIntrinsicOffset(SDValue Offset, SDValue &SOffset,
115*9880d681SAndroid Build Coastguard Worker SDValue &ImmOffset) const;
116*9880d681SAndroid Build Coastguard Worker bool SelectMUBUFIntrinsicVOffset(SDValue Offset, SDValue &SOffset,
117*9880d681SAndroid Build Coastguard Worker SDValue &ImmOffset, SDValue &VOffset) const;
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker bool SelectFlat(SDValue Addr, SDValue &VAddr,
120*9880d681SAndroid Build Coastguard Worker SDValue &SLC, SDValue &TFE) const;
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker bool SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset,
123*9880d681SAndroid Build Coastguard Worker bool &Imm) const;
124*9880d681SAndroid Build Coastguard Worker bool SelectSMRD(SDValue Addr, SDValue &SBase, SDValue &Offset,
125*9880d681SAndroid Build Coastguard Worker bool &Imm) const;
126*9880d681SAndroid Build Coastguard Worker bool SelectSMRDImm(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
127*9880d681SAndroid Build Coastguard Worker bool SelectSMRDImm32(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
128*9880d681SAndroid Build Coastguard Worker bool SelectSMRDSgpr(SDValue Addr, SDValue &SBase, SDValue &Offset) const;
129*9880d681SAndroid Build Coastguard Worker bool SelectSMRDBufferImm(SDValue Addr, SDValue &Offset) const;
130*9880d681SAndroid Build Coastguard Worker bool SelectSMRDBufferImm32(SDValue Addr, SDValue &Offset) const;
131*9880d681SAndroid Build Coastguard Worker bool SelectSMRDBufferSgpr(SDValue Addr, SDValue &Offset) const;
132*9880d681SAndroid Build Coastguard Worker bool SelectMOVRELOffset(SDValue Index, SDValue &Base, SDValue &Offset) const;
133*9880d681SAndroid Build Coastguard Worker bool SelectVOP3Mods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
134*9880d681SAndroid Build Coastguard Worker bool SelectVOP3NoMods(SDValue In, SDValue &Src, SDValue &SrcMods) const;
135*9880d681SAndroid Build Coastguard Worker bool SelectVOP3Mods0(SDValue In, SDValue &Src, SDValue &SrcMods,
136*9880d681SAndroid Build Coastguard Worker SDValue &Clamp, SDValue &Omod) const;
137*9880d681SAndroid Build Coastguard Worker bool SelectVOP3NoMods0(SDValue In, SDValue &Src, SDValue &SrcMods,
138*9880d681SAndroid Build Coastguard Worker SDValue &Clamp, SDValue &Omod) const;
139*9880d681SAndroid Build Coastguard Worker
140*9880d681SAndroid Build Coastguard Worker bool SelectVOP3Mods0Clamp(SDValue In, SDValue &Src, SDValue &SrcMods,
141*9880d681SAndroid Build Coastguard Worker SDValue &Omod) const;
142*9880d681SAndroid Build Coastguard Worker bool SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src, SDValue &SrcMods,
143*9880d681SAndroid Build Coastguard Worker SDValue &Clamp,
144*9880d681SAndroid Build Coastguard Worker SDValue &Omod) const;
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker void SelectADD_SUB_I64(SDNode *N);
147*9880d681SAndroid Build Coastguard Worker void SelectDIV_SCALE(SDNode *N);
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker SDNode *getS_BFE(unsigned Opcode, const SDLoc &DL, SDValue Val,
150*9880d681SAndroid Build Coastguard Worker uint32_t Offset, uint32_t Width);
151*9880d681SAndroid Build Coastguard Worker void SelectS_BFEFromShifts(SDNode *N);
152*9880d681SAndroid Build Coastguard Worker void SelectS_BFE(SDNode *N);
153*9880d681SAndroid Build Coastguard Worker void SelectBRCOND(SDNode *N);
154*9880d681SAndroid Build Coastguard Worker void SelectATOMIC_CMP_SWAP(SDNode *N);
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker // Include the pieces autogenerated from the target description.
157*9880d681SAndroid Build Coastguard Worker #include "AMDGPUGenDAGISel.inc"
158*9880d681SAndroid Build Coastguard Worker };
159*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
160*9880d681SAndroid Build Coastguard Worker
161*9880d681SAndroid Build Coastguard Worker /// \brief This pass converts a legalized DAG into a AMDGPU-specific
162*9880d681SAndroid Build Coastguard Worker // DAG, ready for instruction scheduling.
createAMDGPUISelDag(TargetMachine & TM)163*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createAMDGPUISelDag(TargetMachine &TM) {
164*9880d681SAndroid Build Coastguard Worker return new AMDGPUDAGToDAGISel(TM);
165*9880d681SAndroid Build Coastguard Worker }
166*9880d681SAndroid Build Coastguard Worker
AMDGPUDAGToDAGISel(TargetMachine & TM)167*9880d681SAndroid Build Coastguard Worker AMDGPUDAGToDAGISel::AMDGPUDAGToDAGISel(TargetMachine &TM)
168*9880d681SAndroid Build Coastguard Worker : SelectionDAGISel(TM) {}
169*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)170*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
171*9880d681SAndroid Build Coastguard Worker Subtarget = &MF.getSubtarget<AMDGPUSubtarget>();
172*9880d681SAndroid Build Coastguard Worker return SelectionDAGISel::runOnMachineFunction(MF);
173*9880d681SAndroid Build Coastguard Worker }
174*9880d681SAndroid Build Coastguard Worker
~AMDGPUDAGToDAGISel()175*9880d681SAndroid Build Coastguard Worker AMDGPUDAGToDAGISel::~AMDGPUDAGToDAGISel() {
176*9880d681SAndroid Build Coastguard Worker }
177*9880d681SAndroid Build Coastguard Worker
isInlineImmediate(SDNode * N) const178*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::isInlineImmediate(SDNode *N) const {
179*9880d681SAndroid Build Coastguard Worker const SITargetLowering *TL
180*9880d681SAndroid Build Coastguard Worker = static_cast<const SITargetLowering *>(getTargetLowering());
181*9880d681SAndroid Build Coastguard Worker return TL->analyzeImmediate(N) == 0;
182*9880d681SAndroid Build Coastguard Worker }
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker /// \brief Determine the register class for \p OpNo
185*9880d681SAndroid Build Coastguard Worker /// \returns The register class of the virtual register that will be used for
186*9880d681SAndroid Build Coastguard Worker /// the given operand number \OpNo or NULL if the register class cannot be
187*9880d681SAndroid Build Coastguard Worker /// determined.
getOperandRegClass(SDNode * N,unsigned OpNo) const188*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *AMDGPUDAGToDAGISel::getOperandRegClass(SDNode *N,
189*9880d681SAndroid Build Coastguard Worker unsigned OpNo) const {
190*9880d681SAndroid Build Coastguard Worker if (!N->isMachineOpcode())
191*9880d681SAndroid Build Coastguard Worker return nullptr;
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker switch (N->getMachineOpcode()) {
194*9880d681SAndroid Build Coastguard Worker default: {
195*9880d681SAndroid Build Coastguard Worker const MCInstrDesc &Desc =
196*9880d681SAndroid Build Coastguard Worker Subtarget->getInstrInfo()->get(N->getMachineOpcode());
197*9880d681SAndroid Build Coastguard Worker unsigned OpIdx = Desc.getNumDefs() + OpNo;
198*9880d681SAndroid Build Coastguard Worker if (OpIdx >= Desc.getNumOperands())
199*9880d681SAndroid Build Coastguard Worker return nullptr;
200*9880d681SAndroid Build Coastguard Worker int RegClass = Desc.OpInfo[OpIdx].RegClass;
201*9880d681SAndroid Build Coastguard Worker if (RegClass == -1)
202*9880d681SAndroid Build Coastguard Worker return nullptr;
203*9880d681SAndroid Build Coastguard Worker
204*9880d681SAndroid Build Coastguard Worker return Subtarget->getRegisterInfo()->getRegClass(RegClass);
205*9880d681SAndroid Build Coastguard Worker }
206*9880d681SAndroid Build Coastguard Worker case AMDGPU::REG_SEQUENCE: {
207*9880d681SAndroid Build Coastguard Worker unsigned RCID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue();
208*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *SuperRC =
209*9880d681SAndroid Build Coastguard Worker Subtarget->getRegisterInfo()->getRegClass(RCID);
210*9880d681SAndroid Build Coastguard Worker
211*9880d681SAndroid Build Coastguard Worker SDValue SubRegOp = N->getOperand(OpNo + 1);
212*9880d681SAndroid Build Coastguard Worker unsigned SubRegIdx = cast<ConstantSDNode>(SubRegOp)->getZExtValue();
213*9880d681SAndroid Build Coastguard Worker return Subtarget->getRegisterInfo()->getSubClassWithSubReg(SuperRC,
214*9880d681SAndroid Build Coastguard Worker SubRegIdx);
215*9880d681SAndroid Build Coastguard Worker }
216*9880d681SAndroid Build Coastguard Worker }
217*9880d681SAndroid Build Coastguard Worker }
218*9880d681SAndroid Build Coastguard Worker
glueCopyToM0(SDNode * N) const219*9880d681SAndroid Build Coastguard Worker SDNode *AMDGPUDAGToDAGISel::glueCopyToM0(SDNode *N) const {
220*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS ||
221*9880d681SAndroid Build Coastguard Worker cast<MemSDNode>(N)->getAddressSpace() != AMDGPUAS::LOCAL_ADDRESS)
222*9880d681SAndroid Build Coastguard Worker return N;
223*9880d681SAndroid Build Coastguard Worker
224*9880d681SAndroid Build Coastguard Worker const SITargetLowering& Lowering =
225*9880d681SAndroid Build Coastguard Worker *static_cast<const SITargetLowering*>(getTargetLowering());
226*9880d681SAndroid Build Coastguard Worker
227*9880d681SAndroid Build Coastguard Worker // Write max value to m0 before each load operation
228*9880d681SAndroid Build Coastguard Worker
229*9880d681SAndroid Build Coastguard Worker SDValue M0 = Lowering.copyToM0(*CurDAG, CurDAG->getEntryNode(), SDLoc(N),
230*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(-1, SDLoc(N), MVT::i32));
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker SDValue Glue = M0.getValue(1);
233*9880d681SAndroid Build Coastguard Worker
234*9880d681SAndroid Build Coastguard Worker SmallVector <SDValue, 8> Ops;
235*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
236*9880d681SAndroid Build Coastguard Worker Ops.push_back(N->getOperand(i));
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker Ops.push_back(Glue);
239*9880d681SAndroid Build Coastguard Worker CurDAG->MorphNodeTo(N, N->getOpcode(), N->getVTList(), Ops);
240*9880d681SAndroid Build Coastguard Worker
241*9880d681SAndroid Build Coastguard Worker return N;
242*9880d681SAndroid Build Coastguard Worker }
243*9880d681SAndroid Build Coastguard Worker
selectSGPRVectorRegClassID(unsigned NumVectorElts)244*9880d681SAndroid Build Coastguard Worker static unsigned selectSGPRVectorRegClassID(unsigned NumVectorElts) {
245*9880d681SAndroid Build Coastguard Worker switch (NumVectorElts) {
246*9880d681SAndroid Build Coastguard Worker case 1:
247*9880d681SAndroid Build Coastguard Worker return AMDGPU::SReg_32RegClassID;
248*9880d681SAndroid Build Coastguard Worker case 2:
249*9880d681SAndroid Build Coastguard Worker return AMDGPU::SReg_64RegClassID;
250*9880d681SAndroid Build Coastguard Worker case 4:
251*9880d681SAndroid Build Coastguard Worker return AMDGPU::SReg_128RegClassID;
252*9880d681SAndroid Build Coastguard Worker case 8:
253*9880d681SAndroid Build Coastguard Worker return AMDGPU::SReg_256RegClassID;
254*9880d681SAndroid Build Coastguard Worker case 16:
255*9880d681SAndroid Build Coastguard Worker return AMDGPU::SReg_512RegClassID;
256*9880d681SAndroid Build Coastguard Worker }
257*9880d681SAndroid Build Coastguard Worker
258*9880d681SAndroid Build Coastguard Worker llvm_unreachable("invalid vector size");
259*9880d681SAndroid Build Coastguard Worker }
260*9880d681SAndroid Build Coastguard Worker
Select(SDNode * N)261*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::Select(SDNode *N) {
262*9880d681SAndroid Build Coastguard Worker unsigned int Opc = N->getOpcode();
263*9880d681SAndroid Build Coastguard Worker if (N->isMachineOpcode()) {
264*9880d681SAndroid Build Coastguard Worker N->setNodeId(-1);
265*9880d681SAndroid Build Coastguard Worker return; // Already selected.
266*9880d681SAndroid Build Coastguard Worker }
267*9880d681SAndroid Build Coastguard Worker
268*9880d681SAndroid Build Coastguard Worker if (isa<AtomicSDNode>(N) ||
269*9880d681SAndroid Build Coastguard Worker (Opc == AMDGPUISD::ATOMIC_INC || Opc == AMDGPUISD::ATOMIC_DEC))
270*9880d681SAndroid Build Coastguard Worker N = glueCopyToM0(N);
271*9880d681SAndroid Build Coastguard Worker
272*9880d681SAndroid Build Coastguard Worker switch (Opc) {
273*9880d681SAndroid Build Coastguard Worker default: break;
274*9880d681SAndroid Build Coastguard Worker // We are selecting i64 ADD here instead of custom lower it during
275*9880d681SAndroid Build Coastguard Worker // DAG legalization, so we can fold some i64 ADDs used for address
276*9880d681SAndroid Build Coastguard Worker // calculation into the LOAD and STORE instructions.
277*9880d681SAndroid Build Coastguard Worker case ISD::ADD:
278*9880d681SAndroid Build Coastguard Worker case ISD::SUB: {
279*9880d681SAndroid Build Coastguard Worker if (N->getValueType(0) != MVT::i64 ||
280*9880d681SAndroid Build Coastguard Worker Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
281*9880d681SAndroid Build Coastguard Worker break;
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker SelectADD_SUB_I64(N);
284*9880d681SAndroid Build Coastguard Worker return;
285*9880d681SAndroid Build Coastguard Worker }
286*9880d681SAndroid Build Coastguard Worker case ISD::SCALAR_TO_VECTOR:
287*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BUILD_VERTICAL_VECTOR:
288*9880d681SAndroid Build Coastguard Worker case ISD::BUILD_VECTOR: {
289*9880d681SAndroid Build Coastguard Worker unsigned RegClassID;
290*9880d681SAndroid Build Coastguard Worker const AMDGPURegisterInfo *TRI = Subtarget->getRegisterInfo();
291*9880d681SAndroid Build Coastguard Worker EVT VT = N->getValueType(0);
292*9880d681SAndroid Build Coastguard Worker unsigned NumVectorElts = VT.getVectorNumElements();
293*9880d681SAndroid Build Coastguard Worker EVT EltVT = VT.getVectorElementType();
294*9880d681SAndroid Build Coastguard Worker assert(EltVT.bitsEq(MVT::i32));
295*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) {
296*9880d681SAndroid Build Coastguard Worker RegClassID = selectSGPRVectorRegClassID(NumVectorElts);
297*9880d681SAndroid Build Coastguard Worker } else {
298*9880d681SAndroid Build Coastguard Worker // BUILD_VECTOR was lowered into an IMPLICIT_DEF + 4 INSERT_SUBREG
299*9880d681SAndroid Build Coastguard Worker // that adds a 128 bits reg copy when going through TwoAddressInstructions
300*9880d681SAndroid Build Coastguard Worker // pass. We want to avoid 128 bits copies as much as possible because they
301*9880d681SAndroid Build Coastguard Worker // can't be bundled by our scheduler.
302*9880d681SAndroid Build Coastguard Worker switch(NumVectorElts) {
303*9880d681SAndroid Build Coastguard Worker case 2: RegClassID = AMDGPU::R600_Reg64RegClassID; break;
304*9880d681SAndroid Build Coastguard Worker case 4:
305*9880d681SAndroid Build Coastguard Worker if (Opc == AMDGPUISD::BUILD_VERTICAL_VECTOR)
306*9880d681SAndroid Build Coastguard Worker RegClassID = AMDGPU::R600_Reg128VerticalRegClassID;
307*9880d681SAndroid Build Coastguard Worker else
308*9880d681SAndroid Build Coastguard Worker RegClassID = AMDGPU::R600_Reg128RegClassID;
309*9880d681SAndroid Build Coastguard Worker break;
310*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Do not know how to lower this BUILD_VECTOR");
311*9880d681SAndroid Build Coastguard Worker }
312*9880d681SAndroid Build Coastguard Worker }
313*9880d681SAndroid Build Coastguard Worker
314*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
315*9880d681SAndroid Build Coastguard Worker SDValue RegClass = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32);
316*9880d681SAndroid Build Coastguard Worker
317*9880d681SAndroid Build Coastguard Worker if (NumVectorElts == 1) {
318*9880d681SAndroid Build Coastguard Worker CurDAG->SelectNodeTo(N, AMDGPU::COPY_TO_REGCLASS, EltVT, N->getOperand(0),
319*9880d681SAndroid Build Coastguard Worker RegClass);
320*9880d681SAndroid Build Coastguard Worker return;
321*9880d681SAndroid Build Coastguard Worker }
322*9880d681SAndroid Build Coastguard Worker
323*9880d681SAndroid Build Coastguard Worker assert(NumVectorElts <= 16 && "Vectors with more than 16 elements not "
324*9880d681SAndroid Build Coastguard Worker "supported yet");
325*9880d681SAndroid Build Coastguard Worker // 16 = Max Num Vector Elements
326*9880d681SAndroid Build Coastguard Worker // 2 = 2 REG_SEQUENCE operands per element (value, subreg index)
327*9880d681SAndroid Build Coastguard Worker // 1 = Vector Register Class
328*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 16 * 2 + 1> RegSeqArgs(NumVectorElts * 2 + 1);
329*9880d681SAndroid Build Coastguard Worker
330*9880d681SAndroid Build Coastguard Worker RegSeqArgs[0] = CurDAG->getTargetConstant(RegClassID, DL, MVT::i32);
331*9880d681SAndroid Build Coastguard Worker bool IsRegSeq = true;
332*9880d681SAndroid Build Coastguard Worker unsigned NOps = N->getNumOperands();
333*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NOps; i++) {
334*9880d681SAndroid Build Coastguard Worker // XXX: Why is this here?
335*9880d681SAndroid Build Coastguard Worker if (isa<RegisterSDNode>(N->getOperand(i))) {
336*9880d681SAndroid Build Coastguard Worker IsRegSeq = false;
337*9880d681SAndroid Build Coastguard Worker break;
338*9880d681SAndroid Build Coastguard Worker }
339*9880d681SAndroid Build Coastguard Worker RegSeqArgs[1 + (2 * i)] = N->getOperand(i);
340*9880d681SAndroid Build Coastguard Worker RegSeqArgs[1 + (2 * i) + 1] =
341*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL,
342*9880d681SAndroid Build Coastguard Worker MVT::i32);
343*9880d681SAndroid Build Coastguard Worker }
344*9880d681SAndroid Build Coastguard Worker
345*9880d681SAndroid Build Coastguard Worker if (NOps != NumVectorElts) {
346*9880d681SAndroid Build Coastguard Worker // Fill in the missing undef elements if this was a scalar_to_vector.
347*9880d681SAndroid Build Coastguard Worker assert(Opc == ISD::SCALAR_TO_VECTOR && NOps < NumVectorElts);
348*9880d681SAndroid Build Coastguard Worker
349*9880d681SAndroid Build Coastguard Worker MachineSDNode *ImpDef = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
350*9880d681SAndroid Build Coastguard Worker DL, EltVT);
351*9880d681SAndroid Build Coastguard Worker for (unsigned i = NOps; i < NumVectorElts; ++i) {
352*9880d681SAndroid Build Coastguard Worker RegSeqArgs[1 + (2 * i)] = SDValue(ImpDef, 0);
353*9880d681SAndroid Build Coastguard Worker RegSeqArgs[1 + (2 * i) + 1] =
354*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(TRI->getSubRegFromChannel(i), DL, MVT::i32);
355*9880d681SAndroid Build Coastguard Worker }
356*9880d681SAndroid Build Coastguard Worker }
357*9880d681SAndroid Build Coastguard Worker
358*9880d681SAndroid Build Coastguard Worker if (!IsRegSeq)
359*9880d681SAndroid Build Coastguard Worker break;
360*9880d681SAndroid Build Coastguard Worker CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, N->getVTList(), RegSeqArgs);
361*9880d681SAndroid Build Coastguard Worker return;
362*9880d681SAndroid Build Coastguard Worker }
363*9880d681SAndroid Build Coastguard Worker case ISD::BUILD_PAIR: {
364*9880d681SAndroid Build Coastguard Worker SDValue RC, SubReg0, SubReg1;
365*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
366*9880d681SAndroid Build Coastguard Worker break;
367*9880d681SAndroid Build Coastguard Worker }
368*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
369*9880d681SAndroid Build Coastguard Worker if (N->getValueType(0) == MVT::i128) {
370*9880d681SAndroid Build Coastguard Worker RC = CurDAG->getTargetConstant(AMDGPU::SReg_128RegClassID, DL, MVT::i32);
371*9880d681SAndroid Build Coastguard Worker SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0_sub1, DL, MVT::i32);
372*9880d681SAndroid Build Coastguard Worker SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub2_sub3, DL, MVT::i32);
373*9880d681SAndroid Build Coastguard Worker } else if (N->getValueType(0) == MVT::i64) {
374*9880d681SAndroid Build Coastguard Worker RC = CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32);
375*9880d681SAndroid Build Coastguard Worker SubReg0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
376*9880d681SAndroid Build Coastguard Worker SubReg1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
377*9880d681SAndroid Build Coastguard Worker } else {
378*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unhandled value type for BUILD_PAIR");
379*9880d681SAndroid Build Coastguard Worker }
380*9880d681SAndroid Build Coastguard Worker const SDValue Ops[] = { RC, N->getOperand(0), SubReg0,
381*9880d681SAndroid Build Coastguard Worker N->getOperand(1), SubReg1 };
382*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
383*9880d681SAndroid Build Coastguard Worker N->getValueType(0), Ops));
384*9880d681SAndroid Build Coastguard Worker return;
385*9880d681SAndroid Build Coastguard Worker }
386*9880d681SAndroid Build Coastguard Worker
387*9880d681SAndroid Build Coastguard Worker case ISD::Constant:
388*9880d681SAndroid Build Coastguard Worker case ISD::ConstantFP: {
389*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS ||
390*9880d681SAndroid Build Coastguard Worker N->getValueType(0).getSizeInBits() != 64 || isInlineImmediate(N))
391*9880d681SAndroid Build Coastguard Worker break;
392*9880d681SAndroid Build Coastguard Worker
393*9880d681SAndroid Build Coastguard Worker uint64_t Imm;
394*9880d681SAndroid Build Coastguard Worker if (ConstantFPSDNode *FP = dyn_cast<ConstantFPSDNode>(N))
395*9880d681SAndroid Build Coastguard Worker Imm = FP->getValueAPF().bitcastToAPInt().getZExtValue();
396*9880d681SAndroid Build Coastguard Worker else {
397*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C = cast<ConstantSDNode>(N);
398*9880d681SAndroid Build Coastguard Worker Imm = C->getZExtValue();
399*9880d681SAndroid Build Coastguard Worker }
400*9880d681SAndroid Build Coastguard Worker
401*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
402*9880d681SAndroid Build Coastguard Worker SDNode *Lo = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
403*9880d681SAndroid Build Coastguard Worker CurDAG->getConstant(Imm & 0xFFFFFFFF, DL,
404*9880d681SAndroid Build Coastguard Worker MVT::i32));
405*9880d681SAndroid Build Coastguard Worker SDNode *Hi = CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
406*9880d681SAndroid Build Coastguard Worker CurDAG->getConstant(Imm >> 32, DL, MVT::i32));
407*9880d681SAndroid Build Coastguard Worker const SDValue Ops[] = {
408*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
409*9880d681SAndroid Build Coastguard Worker SDValue(Lo, 0), CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32),
410*9880d681SAndroid Build Coastguard Worker SDValue(Hi, 0), CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32)
411*9880d681SAndroid Build Coastguard Worker };
412*9880d681SAndroid Build Coastguard Worker
413*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
414*9880d681SAndroid Build Coastguard Worker N->getValueType(0), Ops));
415*9880d681SAndroid Build Coastguard Worker return;
416*9880d681SAndroid Build Coastguard Worker }
417*9880d681SAndroid Build Coastguard Worker case ISD::LOAD:
418*9880d681SAndroid Build Coastguard Worker case ISD::STORE: {
419*9880d681SAndroid Build Coastguard Worker N = glueCopyToM0(N);
420*9880d681SAndroid Build Coastguard Worker break;
421*9880d681SAndroid Build Coastguard Worker }
422*9880d681SAndroid Build Coastguard Worker
423*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BFE_I32:
424*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BFE_U32: {
425*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
426*9880d681SAndroid Build Coastguard Worker break;
427*9880d681SAndroid Build Coastguard Worker
428*9880d681SAndroid Build Coastguard Worker // There is a scalar version available, but unlike the vector version which
429*9880d681SAndroid Build Coastguard Worker // has a separate operand for the offset and width, the scalar version packs
430*9880d681SAndroid Build Coastguard Worker // the width and offset into a single operand. Try to move to the scalar
431*9880d681SAndroid Build Coastguard Worker // version if the offsets are constant, so that we can try to keep extended
432*9880d681SAndroid Build Coastguard Worker // loads of kernel arguments in SGPRs.
433*9880d681SAndroid Build Coastguard Worker
434*9880d681SAndroid Build Coastguard Worker // TODO: Technically we could try to pattern match scalar bitshifts of
435*9880d681SAndroid Build Coastguard Worker // dynamic values, but it's probably not useful.
436*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1));
437*9880d681SAndroid Build Coastguard Worker if (!Offset)
438*9880d681SAndroid Build Coastguard Worker break;
439*9880d681SAndroid Build Coastguard Worker
440*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));
441*9880d681SAndroid Build Coastguard Worker if (!Width)
442*9880d681SAndroid Build Coastguard Worker break;
443*9880d681SAndroid Build Coastguard Worker
444*9880d681SAndroid Build Coastguard Worker bool Signed = Opc == AMDGPUISD::BFE_I32;
445*9880d681SAndroid Build Coastguard Worker
446*9880d681SAndroid Build Coastguard Worker uint32_t OffsetVal = Offset->getZExtValue();
447*9880d681SAndroid Build Coastguard Worker uint32_t WidthVal = Width->getZExtValue();
448*9880d681SAndroid Build Coastguard Worker
449*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, getS_BFE(Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32,
450*9880d681SAndroid Build Coastguard Worker SDLoc(N), N->getOperand(0), OffsetVal, WidthVal));
451*9880d681SAndroid Build Coastguard Worker return;
452*9880d681SAndroid Build Coastguard Worker }
453*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::DIV_SCALE: {
454*9880d681SAndroid Build Coastguard Worker SelectDIV_SCALE(N);
455*9880d681SAndroid Build Coastguard Worker return;
456*9880d681SAndroid Build Coastguard Worker }
457*9880d681SAndroid Build Coastguard Worker case ISD::CopyToReg: {
458*9880d681SAndroid Build Coastguard Worker const SITargetLowering& Lowering =
459*9880d681SAndroid Build Coastguard Worker *static_cast<const SITargetLowering*>(getTargetLowering());
460*9880d681SAndroid Build Coastguard Worker Lowering.legalizeTargetIndependentNode(N, *CurDAG);
461*9880d681SAndroid Build Coastguard Worker break;
462*9880d681SAndroid Build Coastguard Worker }
463*9880d681SAndroid Build Coastguard Worker case ISD::AND:
464*9880d681SAndroid Build Coastguard Worker case ISD::SRL:
465*9880d681SAndroid Build Coastguard Worker case ISD::SRA:
466*9880d681SAndroid Build Coastguard Worker case ISD::SIGN_EXTEND_INREG:
467*9880d681SAndroid Build Coastguard Worker if (N->getValueType(0) != MVT::i32 ||
468*9880d681SAndroid Build Coastguard Worker Subtarget->getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS)
469*9880d681SAndroid Build Coastguard Worker break;
470*9880d681SAndroid Build Coastguard Worker
471*9880d681SAndroid Build Coastguard Worker SelectS_BFE(N);
472*9880d681SAndroid Build Coastguard Worker return;
473*9880d681SAndroid Build Coastguard Worker case ISD::BRCOND:
474*9880d681SAndroid Build Coastguard Worker SelectBRCOND(N);
475*9880d681SAndroid Build Coastguard Worker return;
476*9880d681SAndroid Build Coastguard Worker
477*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::ATOMIC_CMP_SWAP:
478*9880d681SAndroid Build Coastguard Worker SelectATOMIC_CMP_SWAP(N);
479*9880d681SAndroid Build Coastguard Worker return;
480*9880d681SAndroid Build Coastguard Worker }
481*9880d681SAndroid Build Coastguard Worker
482*9880d681SAndroid Build Coastguard Worker SelectCode(N);
483*9880d681SAndroid Build Coastguard Worker }
484*9880d681SAndroid Build Coastguard Worker
isConstantLoad(const MemSDNode * N,int CbId) const485*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::isConstantLoad(const MemSDNode *N, int CbId) const {
486*9880d681SAndroid Build Coastguard Worker if (!N->readMem())
487*9880d681SAndroid Build Coastguard Worker return false;
488*9880d681SAndroid Build Coastguard Worker if (CbId == -1)
489*9880d681SAndroid Build Coastguard Worker return N->getAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS;
490*9880d681SAndroid Build Coastguard Worker
491*9880d681SAndroid Build Coastguard Worker return N->getAddressSpace() == AMDGPUAS::CONSTANT_BUFFER_0 + CbId;
492*9880d681SAndroid Build Coastguard Worker }
493*9880d681SAndroid Build Coastguard Worker
isUniformBr(const SDNode * N) const494*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::isUniformBr(const SDNode *N) const {
495*9880d681SAndroid Build Coastguard Worker const BasicBlock *BB = FuncInfo->MBB->getBasicBlock();
496*9880d681SAndroid Build Coastguard Worker const Instruction *Term = BB->getTerminator();
497*9880d681SAndroid Build Coastguard Worker return Term->getMetadata("amdgpu.uniform") ||
498*9880d681SAndroid Build Coastguard Worker Term->getMetadata("structurizecfg.uniform");
499*9880d681SAndroid Build Coastguard Worker }
500*9880d681SAndroid Build Coastguard Worker
getPassName() const501*9880d681SAndroid Build Coastguard Worker const char *AMDGPUDAGToDAGISel::getPassName() const {
502*9880d681SAndroid Build Coastguard Worker return "AMDGPU DAG->DAG Pattern Instruction Selection";
503*9880d681SAndroid Build Coastguard Worker }
504*9880d681SAndroid Build Coastguard Worker
505*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
506*9880d681SAndroid Build Coastguard Worker // Complex Patterns
507*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
508*9880d681SAndroid Build Coastguard Worker
SelectGlobalValueConstantOffset(SDValue Addr,SDValue & IntPtr)509*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectGlobalValueConstantOffset(SDValue Addr,
510*9880d681SAndroid Build Coastguard Worker SDValue& IntPtr) {
511*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Addr)) {
512*9880d681SAndroid Build Coastguard Worker IntPtr = CurDAG->getIntPtrConstant(Cst->getZExtValue() / 4, SDLoc(Addr),
513*9880d681SAndroid Build Coastguard Worker true);
514*9880d681SAndroid Build Coastguard Worker return true;
515*9880d681SAndroid Build Coastguard Worker }
516*9880d681SAndroid Build Coastguard Worker return false;
517*9880d681SAndroid Build Coastguard Worker }
518*9880d681SAndroid Build Coastguard Worker
SelectGlobalValueVariableOffset(SDValue Addr,SDValue & BaseReg,SDValue & Offset)519*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectGlobalValueVariableOffset(SDValue Addr,
520*9880d681SAndroid Build Coastguard Worker SDValue& BaseReg, SDValue &Offset) {
521*9880d681SAndroid Build Coastguard Worker if (!isa<ConstantSDNode>(Addr)) {
522*9880d681SAndroid Build Coastguard Worker BaseReg = Addr;
523*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getIntPtrConstant(0, SDLoc(Addr), true);
524*9880d681SAndroid Build Coastguard Worker return true;
525*9880d681SAndroid Build Coastguard Worker }
526*9880d681SAndroid Build Coastguard Worker return false;
527*9880d681SAndroid Build Coastguard Worker }
528*9880d681SAndroid Build Coastguard Worker
SelectADDRVTX_READ(SDValue Addr,SDValue & Base,SDValue & Offset)529*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectADDRVTX_READ(SDValue Addr, SDValue &Base,
530*9880d681SAndroid Build Coastguard Worker SDValue &Offset) {
531*9880d681SAndroid Build Coastguard Worker ConstantSDNode *IMMOffset;
532*9880d681SAndroid Build Coastguard Worker
533*9880d681SAndroid Build Coastguard Worker if (Addr.getOpcode() == ISD::ADD
534*9880d681SAndroid Build Coastguard Worker && (IMMOffset = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
535*9880d681SAndroid Build Coastguard Worker && isInt<16>(IMMOffset->getZExtValue())) {
536*9880d681SAndroid Build Coastguard Worker
537*9880d681SAndroid Build Coastguard Worker Base = Addr.getOperand(0);
538*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),
539*9880d681SAndroid Build Coastguard Worker MVT::i32);
540*9880d681SAndroid Build Coastguard Worker return true;
541*9880d681SAndroid Build Coastguard Worker // If the pointer address is constant, we can move it to the offset field.
542*9880d681SAndroid Build Coastguard Worker } else if ((IMMOffset = dyn_cast<ConstantSDNode>(Addr))
543*9880d681SAndroid Build Coastguard Worker && isInt<16>(IMMOffset->getZExtValue())) {
544*9880d681SAndroid Build Coastguard Worker Base = CurDAG->getCopyFromReg(CurDAG->getEntryNode(),
545*9880d681SAndroid Build Coastguard Worker SDLoc(CurDAG->getEntryNode()),
546*9880d681SAndroid Build Coastguard Worker AMDGPU::ZERO, MVT::i32);
547*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(IMMOffset->getZExtValue(), SDLoc(Addr),
548*9880d681SAndroid Build Coastguard Worker MVT::i32);
549*9880d681SAndroid Build Coastguard Worker return true;
550*9880d681SAndroid Build Coastguard Worker }
551*9880d681SAndroid Build Coastguard Worker
552*9880d681SAndroid Build Coastguard Worker // Default case, no offset
553*9880d681SAndroid Build Coastguard Worker Base = Addr;
554*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
555*9880d681SAndroid Build Coastguard Worker return true;
556*9880d681SAndroid Build Coastguard Worker }
557*9880d681SAndroid Build Coastguard Worker
SelectADDRIndirect(SDValue Addr,SDValue & Base,SDValue & Offset)558*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectADDRIndirect(SDValue Addr, SDValue &Base,
559*9880d681SAndroid Build Coastguard Worker SDValue &Offset) {
560*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C;
561*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
562*9880d681SAndroid Build Coastguard Worker
563*9880d681SAndroid Build Coastguard Worker if ((C = dyn_cast<ConstantSDNode>(Addr))) {
564*9880d681SAndroid Build Coastguard Worker Base = CurDAG->getRegister(AMDGPU::INDIRECT_BASE_ADDR, MVT::i32);
565*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
566*9880d681SAndroid Build Coastguard Worker } else if ((Addr.getOpcode() == ISD::ADD || Addr.getOpcode() == ISD::OR) &&
567*9880d681SAndroid Build Coastguard Worker (C = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) {
568*9880d681SAndroid Build Coastguard Worker Base = Addr.getOperand(0);
569*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(C->getZExtValue(), DL, MVT::i32);
570*9880d681SAndroid Build Coastguard Worker } else {
571*9880d681SAndroid Build Coastguard Worker Base = Addr;
572*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
573*9880d681SAndroid Build Coastguard Worker }
574*9880d681SAndroid Build Coastguard Worker
575*9880d681SAndroid Build Coastguard Worker return true;
576*9880d681SAndroid Build Coastguard Worker }
577*9880d681SAndroid Build Coastguard Worker
SelectADD_SUB_I64(SDNode * N)578*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::SelectADD_SUB_I64(SDNode *N) {
579*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
580*9880d681SAndroid Build Coastguard Worker SDValue LHS = N->getOperand(0);
581*9880d681SAndroid Build Coastguard Worker SDValue RHS = N->getOperand(1);
582*9880d681SAndroid Build Coastguard Worker
583*9880d681SAndroid Build Coastguard Worker bool IsAdd = (N->getOpcode() == ISD::ADD);
584*9880d681SAndroid Build Coastguard Worker
585*9880d681SAndroid Build Coastguard Worker SDValue Sub0 = CurDAG->getTargetConstant(AMDGPU::sub0, DL, MVT::i32);
586*9880d681SAndroid Build Coastguard Worker SDValue Sub1 = CurDAG->getTargetConstant(AMDGPU::sub1, DL, MVT::i32);
587*9880d681SAndroid Build Coastguard Worker
588*9880d681SAndroid Build Coastguard Worker SDNode *Lo0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
589*9880d681SAndroid Build Coastguard Worker DL, MVT::i32, LHS, Sub0);
590*9880d681SAndroid Build Coastguard Worker SDNode *Hi0 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
591*9880d681SAndroid Build Coastguard Worker DL, MVT::i32, LHS, Sub1);
592*9880d681SAndroid Build Coastguard Worker
593*9880d681SAndroid Build Coastguard Worker SDNode *Lo1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
594*9880d681SAndroid Build Coastguard Worker DL, MVT::i32, RHS, Sub0);
595*9880d681SAndroid Build Coastguard Worker SDNode *Hi1 = CurDAG->getMachineNode(TargetOpcode::EXTRACT_SUBREG,
596*9880d681SAndroid Build Coastguard Worker DL, MVT::i32, RHS, Sub1);
597*9880d681SAndroid Build Coastguard Worker
598*9880d681SAndroid Build Coastguard Worker SDVTList VTList = CurDAG->getVTList(MVT::i32, MVT::Glue);
599*9880d681SAndroid Build Coastguard Worker SDValue AddLoArgs[] = { SDValue(Lo0, 0), SDValue(Lo1, 0) };
600*9880d681SAndroid Build Coastguard Worker
601*9880d681SAndroid Build Coastguard Worker unsigned Opc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
602*9880d681SAndroid Build Coastguard Worker unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;
603*9880d681SAndroid Build Coastguard Worker
604*9880d681SAndroid Build Coastguard Worker SDNode *AddLo = CurDAG->getMachineNode( Opc, DL, VTList, AddLoArgs);
605*9880d681SAndroid Build Coastguard Worker SDValue Carry(AddLo, 1);
606*9880d681SAndroid Build Coastguard Worker SDNode *AddHi
607*9880d681SAndroid Build Coastguard Worker = CurDAG->getMachineNode(CarryOpc, DL, MVT::i32,
608*9880d681SAndroid Build Coastguard Worker SDValue(Hi0, 0), SDValue(Hi1, 0), Carry);
609*9880d681SAndroid Build Coastguard Worker
610*9880d681SAndroid Build Coastguard Worker SDValue Args[5] = {
611*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(AMDGPU::SReg_64RegClassID, DL, MVT::i32),
612*9880d681SAndroid Build Coastguard Worker SDValue(AddLo,0),
613*9880d681SAndroid Build Coastguard Worker Sub0,
614*9880d681SAndroid Build Coastguard Worker SDValue(AddHi,0),
615*9880d681SAndroid Build Coastguard Worker Sub1,
616*9880d681SAndroid Build Coastguard Worker };
617*9880d681SAndroid Build Coastguard Worker CurDAG->SelectNodeTo(N, AMDGPU::REG_SEQUENCE, MVT::i64, Args);
618*9880d681SAndroid Build Coastguard Worker }
619*9880d681SAndroid Build Coastguard Worker
620*9880d681SAndroid Build Coastguard Worker // We need to handle this here because tablegen doesn't support matching
621*9880d681SAndroid Build Coastguard Worker // instructions with multiple outputs.
SelectDIV_SCALE(SDNode * N)622*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::SelectDIV_SCALE(SDNode *N) {
623*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
624*9880d681SAndroid Build Coastguard Worker EVT VT = N->getValueType(0);
625*9880d681SAndroid Build Coastguard Worker
626*9880d681SAndroid Build Coastguard Worker assert(VT == MVT::f32 || VT == MVT::f64);
627*9880d681SAndroid Build Coastguard Worker
628*9880d681SAndroid Build Coastguard Worker unsigned Opc
629*9880d681SAndroid Build Coastguard Worker = (VT == MVT::f64) ? AMDGPU::V_DIV_SCALE_F64 : AMDGPU::V_DIV_SCALE_F32;
630*9880d681SAndroid Build Coastguard Worker
631*9880d681SAndroid Build Coastguard Worker // src0_modifiers, src0, src1_modifiers, src1, src2_modifiers, src2, clamp,
632*9880d681SAndroid Build Coastguard Worker // omod
633*9880d681SAndroid Build Coastguard Worker SDValue Ops[8];
634*9880d681SAndroid Build Coastguard Worker
635*9880d681SAndroid Build Coastguard Worker SelectVOP3Mods0(N->getOperand(0), Ops[1], Ops[0], Ops[6], Ops[7]);
636*9880d681SAndroid Build Coastguard Worker SelectVOP3Mods(N->getOperand(1), Ops[3], Ops[2]);
637*9880d681SAndroid Build Coastguard Worker SelectVOP3Mods(N->getOperand(2), Ops[5], Ops[4]);
638*9880d681SAndroid Build Coastguard Worker CurDAG->SelectNodeTo(N, Opc, VT, MVT::i1, Ops);
639*9880d681SAndroid Build Coastguard Worker }
640*9880d681SAndroid Build Coastguard Worker
isDSOffsetLegal(const SDValue & Base,unsigned Offset,unsigned OffsetBits) const641*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::isDSOffsetLegal(const SDValue &Base, unsigned Offset,
642*9880d681SAndroid Build Coastguard Worker unsigned OffsetBits) const {
643*9880d681SAndroid Build Coastguard Worker if ((OffsetBits == 16 && !isUInt<16>(Offset)) ||
644*9880d681SAndroid Build Coastguard Worker (OffsetBits == 8 && !isUInt<8>(Offset)))
645*9880d681SAndroid Build Coastguard Worker return false;
646*9880d681SAndroid Build Coastguard Worker
647*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() >= AMDGPUSubtarget::SEA_ISLANDS ||
648*9880d681SAndroid Build Coastguard Worker Subtarget->unsafeDSOffsetFoldingEnabled())
649*9880d681SAndroid Build Coastguard Worker return true;
650*9880d681SAndroid Build Coastguard Worker
651*9880d681SAndroid Build Coastguard Worker // On Southern Islands instruction with a negative base value and an offset
652*9880d681SAndroid Build Coastguard Worker // don't seem to work.
653*9880d681SAndroid Build Coastguard Worker return CurDAG->SignBitIsZero(Base);
654*9880d681SAndroid Build Coastguard Worker }
655*9880d681SAndroid Build Coastguard Worker
SelectDS1Addr1Offset(SDValue Addr,SDValue & Base,SDValue & Offset) const656*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectDS1Addr1Offset(SDValue Addr, SDValue &Base,
657*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const {
658*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
659*9880d681SAndroid Build Coastguard Worker if (CurDAG->isBaseWithConstantOffset(Addr)) {
660*9880d681SAndroid Build Coastguard Worker SDValue N0 = Addr.getOperand(0);
661*9880d681SAndroid Build Coastguard Worker SDValue N1 = Addr.getOperand(1);
662*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
663*9880d681SAndroid Build Coastguard Worker if (isDSOffsetLegal(N0, C1->getSExtValue(), 16)) {
664*9880d681SAndroid Build Coastguard Worker // (add n0, c0)
665*9880d681SAndroid Build Coastguard Worker Base = N0;
666*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
667*9880d681SAndroid Build Coastguard Worker return true;
668*9880d681SAndroid Build Coastguard Worker }
669*9880d681SAndroid Build Coastguard Worker } else if (Addr.getOpcode() == ISD::SUB) {
670*9880d681SAndroid Build Coastguard Worker // sub C, x -> add (sub 0, x), C
671*9880d681SAndroid Build Coastguard Worker if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) {
672*9880d681SAndroid Build Coastguard Worker int64_t ByteOffset = C->getSExtValue();
673*9880d681SAndroid Build Coastguard Worker if (isUInt<16>(ByteOffset)) {
674*9880d681SAndroid Build Coastguard Worker SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
675*9880d681SAndroid Build Coastguard Worker
676*9880d681SAndroid Build Coastguard Worker // XXX - This is kind of hacky. Create a dummy sub node so we can check
677*9880d681SAndroid Build Coastguard Worker // the known bits in isDSOffsetLegal. We need to emit the selected node
678*9880d681SAndroid Build Coastguard Worker // here, so this is thrown away.
679*9880d681SAndroid Build Coastguard Worker SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32,
680*9880d681SAndroid Build Coastguard Worker Zero, Addr.getOperand(1));
681*9880d681SAndroid Build Coastguard Worker
682*9880d681SAndroid Build Coastguard Worker if (isDSOffsetLegal(Sub, ByteOffset, 16)) {
683*9880d681SAndroid Build Coastguard Worker MachineSDNode *MachineSub
684*9880d681SAndroid Build Coastguard Worker = CurDAG->getMachineNode(AMDGPU::V_SUB_I32_e32, DL, MVT::i32,
685*9880d681SAndroid Build Coastguard Worker Zero, Addr.getOperand(1));
686*9880d681SAndroid Build Coastguard Worker
687*9880d681SAndroid Build Coastguard Worker Base = SDValue(MachineSub, 0);
688*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(ByteOffset, DL, MVT::i16);
689*9880d681SAndroid Build Coastguard Worker return true;
690*9880d681SAndroid Build Coastguard Worker }
691*9880d681SAndroid Build Coastguard Worker }
692*9880d681SAndroid Build Coastguard Worker }
693*9880d681SAndroid Build Coastguard Worker } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
694*9880d681SAndroid Build Coastguard Worker // If we have a constant address, prefer to put the constant into the
695*9880d681SAndroid Build Coastguard Worker // offset. This can save moves to load the constant address since multiple
696*9880d681SAndroid Build Coastguard Worker // operations can share the zero base address register, and enables merging
697*9880d681SAndroid Build Coastguard Worker // into read2 / write2 instructions.
698*9880d681SAndroid Build Coastguard Worker
699*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
700*9880d681SAndroid Build Coastguard Worker
701*9880d681SAndroid Build Coastguard Worker if (isUInt<16>(CAddr->getZExtValue())) {
702*9880d681SAndroid Build Coastguard Worker SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
703*9880d681SAndroid Build Coastguard Worker MachineSDNode *MovZero = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
704*9880d681SAndroid Build Coastguard Worker DL, MVT::i32, Zero);
705*9880d681SAndroid Build Coastguard Worker Base = SDValue(MovZero, 0);
706*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(CAddr->getZExtValue(), DL, MVT::i16);
707*9880d681SAndroid Build Coastguard Worker return true;
708*9880d681SAndroid Build Coastguard Worker }
709*9880d681SAndroid Build Coastguard Worker }
710*9880d681SAndroid Build Coastguard Worker
711*9880d681SAndroid Build Coastguard Worker // default case
712*9880d681SAndroid Build Coastguard Worker Base = Addr;
713*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i16);
714*9880d681SAndroid Build Coastguard Worker return true;
715*9880d681SAndroid Build Coastguard Worker }
716*9880d681SAndroid Build Coastguard Worker
717*9880d681SAndroid Build Coastguard Worker // TODO: If offset is too big, put low 16-bit into offset.
SelectDS64Bit4ByteAligned(SDValue Addr,SDValue & Base,SDValue & Offset0,SDValue & Offset1) const718*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectDS64Bit4ByteAligned(SDValue Addr, SDValue &Base,
719*9880d681SAndroid Build Coastguard Worker SDValue &Offset0,
720*9880d681SAndroid Build Coastguard Worker SDValue &Offset1) const {
721*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
722*9880d681SAndroid Build Coastguard Worker
723*9880d681SAndroid Build Coastguard Worker if (CurDAG->isBaseWithConstantOffset(Addr)) {
724*9880d681SAndroid Build Coastguard Worker SDValue N0 = Addr.getOperand(0);
725*9880d681SAndroid Build Coastguard Worker SDValue N1 = Addr.getOperand(1);
726*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
727*9880d681SAndroid Build Coastguard Worker unsigned DWordOffset0 = C1->getZExtValue() / 4;
728*9880d681SAndroid Build Coastguard Worker unsigned DWordOffset1 = DWordOffset0 + 1;
729*9880d681SAndroid Build Coastguard Worker // (add n0, c0)
730*9880d681SAndroid Build Coastguard Worker if (isDSOffsetLegal(N0, DWordOffset1, 8)) {
731*9880d681SAndroid Build Coastguard Worker Base = N0;
732*9880d681SAndroid Build Coastguard Worker Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8);
733*9880d681SAndroid Build Coastguard Worker Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8);
734*9880d681SAndroid Build Coastguard Worker return true;
735*9880d681SAndroid Build Coastguard Worker }
736*9880d681SAndroid Build Coastguard Worker } else if (Addr.getOpcode() == ISD::SUB) {
737*9880d681SAndroid Build Coastguard Worker // sub C, x -> add (sub 0, x), C
738*9880d681SAndroid Build Coastguard Worker if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Addr.getOperand(0))) {
739*9880d681SAndroid Build Coastguard Worker unsigned DWordOffset0 = C->getZExtValue() / 4;
740*9880d681SAndroid Build Coastguard Worker unsigned DWordOffset1 = DWordOffset0 + 1;
741*9880d681SAndroid Build Coastguard Worker
742*9880d681SAndroid Build Coastguard Worker if (isUInt<8>(DWordOffset0)) {
743*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
744*9880d681SAndroid Build Coastguard Worker SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
745*9880d681SAndroid Build Coastguard Worker
746*9880d681SAndroid Build Coastguard Worker // XXX - This is kind of hacky. Create a dummy sub node so we can check
747*9880d681SAndroid Build Coastguard Worker // the known bits in isDSOffsetLegal. We need to emit the selected node
748*9880d681SAndroid Build Coastguard Worker // here, so this is thrown away.
749*9880d681SAndroid Build Coastguard Worker SDValue Sub = CurDAG->getNode(ISD::SUB, DL, MVT::i32,
750*9880d681SAndroid Build Coastguard Worker Zero, Addr.getOperand(1));
751*9880d681SAndroid Build Coastguard Worker
752*9880d681SAndroid Build Coastguard Worker if (isDSOffsetLegal(Sub, DWordOffset1, 8)) {
753*9880d681SAndroid Build Coastguard Worker MachineSDNode *MachineSub
754*9880d681SAndroid Build Coastguard Worker = CurDAG->getMachineNode(AMDGPU::V_SUB_I32_e32, DL, MVT::i32,
755*9880d681SAndroid Build Coastguard Worker Zero, Addr.getOperand(1));
756*9880d681SAndroid Build Coastguard Worker
757*9880d681SAndroid Build Coastguard Worker Base = SDValue(MachineSub, 0);
758*9880d681SAndroid Build Coastguard Worker Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8);
759*9880d681SAndroid Build Coastguard Worker Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8);
760*9880d681SAndroid Build Coastguard Worker return true;
761*9880d681SAndroid Build Coastguard Worker }
762*9880d681SAndroid Build Coastguard Worker }
763*9880d681SAndroid Build Coastguard Worker }
764*9880d681SAndroid Build Coastguard Worker } else if (const ConstantSDNode *CAddr = dyn_cast<ConstantSDNode>(Addr)) {
765*9880d681SAndroid Build Coastguard Worker unsigned DWordOffset0 = CAddr->getZExtValue() / 4;
766*9880d681SAndroid Build Coastguard Worker unsigned DWordOffset1 = DWordOffset0 + 1;
767*9880d681SAndroid Build Coastguard Worker assert(4 * DWordOffset0 == CAddr->getZExtValue());
768*9880d681SAndroid Build Coastguard Worker
769*9880d681SAndroid Build Coastguard Worker if (isUInt<8>(DWordOffset0) && isUInt<8>(DWordOffset1)) {
770*9880d681SAndroid Build Coastguard Worker SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
771*9880d681SAndroid Build Coastguard Worker MachineSDNode *MovZero
772*9880d681SAndroid Build Coastguard Worker = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
773*9880d681SAndroid Build Coastguard Worker DL, MVT::i32, Zero);
774*9880d681SAndroid Build Coastguard Worker Base = SDValue(MovZero, 0);
775*9880d681SAndroid Build Coastguard Worker Offset0 = CurDAG->getTargetConstant(DWordOffset0, DL, MVT::i8);
776*9880d681SAndroid Build Coastguard Worker Offset1 = CurDAG->getTargetConstant(DWordOffset1, DL, MVT::i8);
777*9880d681SAndroid Build Coastguard Worker return true;
778*9880d681SAndroid Build Coastguard Worker }
779*9880d681SAndroid Build Coastguard Worker }
780*9880d681SAndroid Build Coastguard Worker
781*9880d681SAndroid Build Coastguard Worker // default case
782*9880d681SAndroid Build Coastguard Worker Base = Addr;
783*9880d681SAndroid Build Coastguard Worker Offset0 = CurDAG->getTargetConstant(0, DL, MVT::i8);
784*9880d681SAndroid Build Coastguard Worker Offset1 = CurDAG->getTargetConstant(1, DL, MVT::i8);
785*9880d681SAndroid Build Coastguard Worker return true;
786*9880d681SAndroid Build Coastguard Worker }
787*9880d681SAndroid Build Coastguard Worker
isLegalMUBUFImmOffset(const ConstantSDNode * Imm)788*9880d681SAndroid Build Coastguard Worker static bool isLegalMUBUFImmOffset(const ConstantSDNode *Imm) {
789*9880d681SAndroid Build Coastguard Worker return isUInt<12>(Imm->getZExtValue());
790*9880d681SAndroid Build Coastguard Worker }
791*9880d681SAndroid Build Coastguard Worker
SelectMUBUF(SDValue Addr,SDValue & Ptr,SDValue & VAddr,SDValue & SOffset,SDValue & Offset,SDValue & Offen,SDValue & Idxen,SDValue & Addr64,SDValue & GLC,SDValue & SLC,SDValue & TFE) const792*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUF(SDValue Addr, SDValue &Ptr,
793*9880d681SAndroid Build Coastguard Worker SDValue &VAddr, SDValue &SOffset,
794*9880d681SAndroid Build Coastguard Worker SDValue &Offset, SDValue &Offen,
795*9880d681SAndroid Build Coastguard Worker SDValue &Idxen, SDValue &Addr64,
796*9880d681SAndroid Build Coastguard Worker SDValue &GLC, SDValue &SLC,
797*9880d681SAndroid Build Coastguard Worker SDValue &TFE) const {
798*9880d681SAndroid Build Coastguard Worker // Subtarget prefers to use flat instruction
799*9880d681SAndroid Build Coastguard Worker if (Subtarget->useFlatForGlobal())
800*9880d681SAndroid Build Coastguard Worker return false;
801*9880d681SAndroid Build Coastguard Worker
802*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
803*9880d681SAndroid Build Coastguard Worker
804*9880d681SAndroid Build Coastguard Worker if (!GLC.getNode())
805*9880d681SAndroid Build Coastguard Worker GLC = CurDAG->getTargetConstant(0, DL, MVT::i1);
806*9880d681SAndroid Build Coastguard Worker if (!SLC.getNode())
807*9880d681SAndroid Build Coastguard Worker SLC = CurDAG->getTargetConstant(0, DL, MVT::i1);
808*9880d681SAndroid Build Coastguard Worker TFE = CurDAG->getTargetConstant(0, DL, MVT::i1);
809*9880d681SAndroid Build Coastguard Worker
810*9880d681SAndroid Build Coastguard Worker Idxen = CurDAG->getTargetConstant(0, DL, MVT::i1);
811*9880d681SAndroid Build Coastguard Worker Offen = CurDAG->getTargetConstant(0, DL, MVT::i1);
812*9880d681SAndroid Build Coastguard Worker Addr64 = CurDAG->getTargetConstant(0, DL, MVT::i1);
813*9880d681SAndroid Build Coastguard Worker SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32);
814*9880d681SAndroid Build Coastguard Worker
815*9880d681SAndroid Build Coastguard Worker if (CurDAG->isBaseWithConstantOffset(Addr)) {
816*9880d681SAndroid Build Coastguard Worker SDValue N0 = Addr.getOperand(0);
817*9880d681SAndroid Build Coastguard Worker SDValue N1 = Addr.getOperand(1);
818*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
819*9880d681SAndroid Build Coastguard Worker
820*9880d681SAndroid Build Coastguard Worker if (N0.getOpcode() == ISD::ADD) {
821*9880d681SAndroid Build Coastguard Worker // (add (add N2, N3), C1) -> addr64
822*9880d681SAndroid Build Coastguard Worker SDValue N2 = N0.getOperand(0);
823*9880d681SAndroid Build Coastguard Worker SDValue N3 = N0.getOperand(1);
824*9880d681SAndroid Build Coastguard Worker Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1);
825*9880d681SAndroid Build Coastguard Worker Ptr = N2;
826*9880d681SAndroid Build Coastguard Worker VAddr = N3;
827*9880d681SAndroid Build Coastguard Worker } else {
828*9880d681SAndroid Build Coastguard Worker
829*9880d681SAndroid Build Coastguard Worker // (add N0, C1) -> offset
830*9880d681SAndroid Build Coastguard Worker VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32);
831*9880d681SAndroid Build Coastguard Worker Ptr = N0;
832*9880d681SAndroid Build Coastguard Worker }
833*9880d681SAndroid Build Coastguard Worker
834*9880d681SAndroid Build Coastguard Worker if (isLegalMUBUFImmOffset(C1)) {
835*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
836*9880d681SAndroid Build Coastguard Worker return true;
837*9880d681SAndroid Build Coastguard Worker }
838*9880d681SAndroid Build Coastguard Worker
839*9880d681SAndroid Build Coastguard Worker if (isUInt<32>(C1->getZExtValue())) {
840*9880d681SAndroid Build Coastguard Worker // Illegal offset, store it in soffset.
841*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
842*9880d681SAndroid Build Coastguard Worker SOffset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
843*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32)),
844*9880d681SAndroid Build Coastguard Worker 0);
845*9880d681SAndroid Build Coastguard Worker return true;
846*9880d681SAndroid Build Coastguard Worker }
847*9880d681SAndroid Build Coastguard Worker }
848*9880d681SAndroid Build Coastguard Worker
849*9880d681SAndroid Build Coastguard Worker if (Addr.getOpcode() == ISD::ADD) {
850*9880d681SAndroid Build Coastguard Worker // (add N0, N1) -> addr64
851*9880d681SAndroid Build Coastguard Worker SDValue N0 = Addr.getOperand(0);
852*9880d681SAndroid Build Coastguard Worker SDValue N1 = Addr.getOperand(1);
853*9880d681SAndroid Build Coastguard Worker Addr64 = CurDAG->getTargetConstant(1, DL, MVT::i1);
854*9880d681SAndroid Build Coastguard Worker Ptr = N0;
855*9880d681SAndroid Build Coastguard Worker VAddr = N1;
856*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
857*9880d681SAndroid Build Coastguard Worker return true;
858*9880d681SAndroid Build Coastguard Worker }
859*9880d681SAndroid Build Coastguard Worker
860*9880d681SAndroid Build Coastguard Worker // default case -> offset
861*9880d681SAndroid Build Coastguard Worker VAddr = CurDAG->getTargetConstant(0, DL, MVT::i32);
862*9880d681SAndroid Build Coastguard Worker Ptr = Addr;
863*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, DL, MVT::i16);
864*9880d681SAndroid Build Coastguard Worker
865*9880d681SAndroid Build Coastguard Worker return true;
866*9880d681SAndroid Build Coastguard Worker }
867*9880d681SAndroid Build Coastguard Worker
SelectMUBUFAddr64(SDValue Addr,SDValue & SRsrc,SDValue & VAddr,SDValue & SOffset,SDValue & Offset,SDValue & GLC,SDValue & SLC,SDValue & TFE) const868*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
869*9880d681SAndroid Build Coastguard Worker SDValue &VAddr, SDValue &SOffset,
870*9880d681SAndroid Build Coastguard Worker SDValue &Offset, SDValue &GLC,
871*9880d681SAndroid Build Coastguard Worker SDValue &SLC, SDValue &TFE) const {
872*9880d681SAndroid Build Coastguard Worker SDValue Ptr, Offen, Idxen, Addr64;
873*9880d681SAndroid Build Coastguard Worker
874*9880d681SAndroid Build Coastguard Worker // addr64 bit was removed for volcanic islands.
875*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
876*9880d681SAndroid Build Coastguard Worker return false;
877*9880d681SAndroid Build Coastguard Worker
878*9880d681SAndroid Build Coastguard Worker if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64,
879*9880d681SAndroid Build Coastguard Worker GLC, SLC, TFE))
880*9880d681SAndroid Build Coastguard Worker return false;
881*9880d681SAndroid Build Coastguard Worker
882*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C = cast<ConstantSDNode>(Addr64);
883*9880d681SAndroid Build Coastguard Worker if (C->getSExtValue()) {
884*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
885*9880d681SAndroid Build Coastguard Worker
886*9880d681SAndroid Build Coastguard Worker const SITargetLowering& Lowering =
887*9880d681SAndroid Build Coastguard Worker *static_cast<const SITargetLowering*>(getTargetLowering());
888*9880d681SAndroid Build Coastguard Worker
889*9880d681SAndroid Build Coastguard Worker SRsrc = SDValue(Lowering.wrapAddr64Rsrc(*CurDAG, DL, Ptr), 0);
890*9880d681SAndroid Build Coastguard Worker return true;
891*9880d681SAndroid Build Coastguard Worker }
892*9880d681SAndroid Build Coastguard Worker
893*9880d681SAndroid Build Coastguard Worker return false;
894*9880d681SAndroid Build Coastguard Worker }
895*9880d681SAndroid Build Coastguard Worker
SelectMUBUFAddr64(SDValue Addr,SDValue & SRsrc,SDValue & VAddr,SDValue & SOffset,SDValue & Offset,SDValue & SLC) const896*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFAddr64(SDValue Addr, SDValue &SRsrc,
897*9880d681SAndroid Build Coastguard Worker SDValue &VAddr, SDValue &SOffset,
898*9880d681SAndroid Build Coastguard Worker SDValue &Offset,
899*9880d681SAndroid Build Coastguard Worker SDValue &SLC) const {
900*9880d681SAndroid Build Coastguard Worker SLC = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i1);
901*9880d681SAndroid Build Coastguard Worker SDValue GLC, TFE;
902*9880d681SAndroid Build Coastguard Worker
903*9880d681SAndroid Build Coastguard Worker return SelectMUBUFAddr64(Addr, SRsrc, VAddr, SOffset, Offset, GLC, SLC, TFE);
904*9880d681SAndroid Build Coastguard Worker }
905*9880d681SAndroid Build Coastguard Worker
SelectMUBUFScratch(SDValue Addr,SDValue & Rsrc,SDValue & VAddr,SDValue & SOffset,SDValue & ImmOffset) const906*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFScratch(SDValue Addr, SDValue &Rsrc,
907*9880d681SAndroid Build Coastguard Worker SDValue &VAddr, SDValue &SOffset,
908*9880d681SAndroid Build Coastguard Worker SDValue &ImmOffset) const {
909*9880d681SAndroid Build Coastguard Worker
910*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
911*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = CurDAG->getMachineFunction();
912*9880d681SAndroid Build Coastguard Worker const SIMachineFunctionInfo *Info = MF.getInfo<SIMachineFunctionInfo>();
913*9880d681SAndroid Build Coastguard Worker
914*9880d681SAndroid Build Coastguard Worker Rsrc = CurDAG->getRegister(Info->getScratchRSrcReg(), MVT::v4i32);
915*9880d681SAndroid Build Coastguard Worker SOffset = CurDAG->getRegister(Info->getScratchWaveOffsetReg(), MVT::i32);
916*9880d681SAndroid Build Coastguard Worker
917*9880d681SAndroid Build Coastguard Worker // (add n0, c1)
918*9880d681SAndroid Build Coastguard Worker if (CurDAG->isBaseWithConstantOffset(Addr)) {
919*9880d681SAndroid Build Coastguard Worker SDValue N0 = Addr.getOperand(0);
920*9880d681SAndroid Build Coastguard Worker SDValue N1 = Addr.getOperand(1);
921*9880d681SAndroid Build Coastguard Worker
922*9880d681SAndroid Build Coastguard Worker // Offsets in vaddr must be positive.
923*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
924*9880d681SAndroid Build Coastguard Worker if (isLegalMUBUFImmOffset(C1)) {
925*9880d681SAndroid Build Coastguard Worker VAddr = N0;
926*9880d681SAndroid Build Coastguard Worker ImmOffset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i16);
927*9880d681SAndroid Build Coastguard Worker return true;
928*9880d681SAndroid Build Coastguard Worker }
929*9880d681SAndroid Build Coastguard Worker }
930*9880d681SAndroid Build Coastguard Worker
931*9880d681SAndroid Build Coastguard Worker // (node)
932*9880d681SAndroid Build Coastguard Worker VAddr = Addr;
933*9880d681SAndroid Build Coastguard Worker ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16);
934*9880d681SAndroid Build Coastguard Worker return true;
935*9880d681SAndroid Build Coastguard Worker }
936*9880d681SAndroid Build Coastguard Worker
SelectMUBUFOffset(SDValue Addr,SDValue & SRsrc,SDValue & SOffset,SDValue & Offset,SDValue & GLC,SDValue & SLC,SDValue & TFE) const937*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc,
938*9880d681SAndroid Build Coastguard Worker SDValue &SOffset, SDValue &Offset,
939*9880d681SAndroid Build Coastguard Worker SDValue &GLC, SDValue &SLC,
940*9880d681SAndroid Build Coastguard Worker SDValue &TFE) const {
941*9880d681SAndroid Build Coastguard Worker SDValue Ptr, VAddr, Offen, Idxen, Addr64;
942*9880d681SAndroid Build Coastguard Worker const SIInstrInfo *TII =
943*9880d681SAndroid Build Coastguard Worker static_cast<const SIInstrInfo *>(Subtarget->getInstrInfo());
944*9880d681SAndroid Build Coastguard Worker
945*9880d681SAndroid Build Coastguard Worker if (!SelectMUBUF(Addr, Ptr, VAddr, SOffset, Offset, Offen, Idxen, Addr64,
946*9880d681SAndroid Build Coastguard Worker GLC, SLC, TFE))
947*9880d681SAndroid Build Coastguard Worker return false;
948*9880d681SAndroid Build Coastguard Worker
949*9880d681SAndroid Build Coastguard Worker if (!cast<ConstantSDNode>(Offen)->getSExtValue() &&
950*9880d681SAndroid Build Coastguard Worker !cast<ConstantSDNode>(Idxen)->getSExtValue() &&
951*9880d681SAndroid Build Coastguard Worker !cast<ConstantSDNode>(Addr64)->getSExtValue()) {
952*9880d681SAndroid Build Coastguard Worker uint64_t Rsrc = TII->getDefaultRsrcDataFormat() |
953*9880d681SAndroid Build Coastguard Worker APInt::getAllOnesValue(32).getZExtValue(); // Size
954*9880d681SAndroid Build Coastguard Worker SDLoc DL(Addr);
955*9880d681SAndroid Build Coastguard Worker
956*9880d681SAndroid Build Coastguard Worker const SITargetLowering& Lowering =
957*9880d681SAndroid Build Coastguard Worker *static_cast<const SITargetLowering*>(getTargetLowering());
958*9880d681SAndroid Build Coastguard Worker
959*9880d681SAndroid Build Coastguard Worker SRsrc = SDValue(Lowering.buildRSRC(*CurDAG, DL, Ptr, 0, Rsrc), 0);
960*9880d681SAndroid Build Coastguard Worker return true;
961*9880d681SAndroid Build Coastguard Worker }
962*9880d681SAndroid Build Coastguard Worker return false;
963*9880d681SAndroid Build Coastguard Worker }
964*9880d681SAndroid Build Coastguard Worker
SelectMUBUFOffset(SDValue Addr,SDValue & SRsrc,SDValue & Soffset,SDValue & Offset) const965*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc,
966*9880d681SAndroid Build Coastguard Worker SDValue &Soffset, SDValue &Offset
967*9880d681SAndroid Build Coastguard Worker ) const {
968*9880d681SAndroid Build Coastguard Worker SDValue GLC, SLC, TFE;
969*9880d681SAndroid Build Coastguard Worker
970*9880d681SAndroid Build Coastguard Worker return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE);
971*9880d681SAndroid Build Coastguard Worker }
SelectMUBUFOffset(SDValue Addr,SDValue & SRsrc,SDValue & Soffset,SDValue & Offset,SDValue & SLC) const972*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFOffset(SDValue Addr, SDValue &SRsrc,
973*9880d681SAndroid Build Coastguard Worker SDValue &Soffset, SDValue &Offset,
974*9880d681SAndroid Build Coastguard Worker SDValue &SLC) const {
975*9880d681SAndroid Build Coastguard Worker SDValue GLC, TFE;
976*9880d681SAndroid Build Coastguard Worker
977*9880d681SAndroid Build Coastguard Worker return SelectMUBUFOffset(Addr, SRsrc, Soffset, Offset, GLC, SLC, TFE);
978*9880d681SAndroid Build Coastguard Worker }
979*9880d681SAndroid Build Coastguard Worker
SelectMUBUFConstant(SDValue Constant,SDValue & SOffset,SDValue & ImmOffset) const980*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFConstant(SDValue Constant,
981*9880d681SAndroid Build Coastguard Worker SDValue &SOffset,
982*9880d681SAndroid Build Coastguard Worker SDValue &ImmOffset) const {
983*9880d681SAndroid Build Coastguard Worker SDLoc DL(Constant);
984*9880d681SAndroid Build Coastguard Worker uint32_t Imm = cast<ConstantSDNode>(Constant)->getZExtValue();
985*9880d681SAndroid Build Coastguard Worker uint32_t Overflow = 0;
986*9880d681SAndroid Build Coastguard Worker
987*9880d681SAndroid Build Coastguard Worker if (Imm >= 4096) {
988*9880d681SAndroid Build Coastguard Worker if (Imm <= 4095 + 64) {
989*9880d681SAndroid Build Coastguard Worker // Use an SOffset inline constant for 1..64
990*9880d681SAndroid Build Coastguard Worker Overflow = Imm - 4095;
991*9880d681SAndroid Build Coastguard Worker Imm = 4095;
992*9880d681SAndroid Build Coastguard Worker } else {
993*9880d681SAndroid Build Coastguard Worker // Try to keep the same value in SOffset for adjacent loads, so that
994*9880d681SAndroid Build Coastguard Worker // the corresponding register contents can be re-used.
995*9880d681SAndroid Build Coastguard Worker //
996*9880d681SAndroid Build Coastguard Worker // Load values with all low-bits set into SOffset, so that a larger
997*9880d681SAndroid Build Coastguard Worker // range of values can be covered using s_movk_i32
998*9880d681SAndroid Build Coastguard Worker uint32_t High = (Imm + 1) & ~4095;
999*9880d681SAndroid Build Coastguard Worker uint32_t Low = (Imm + 1) & 4095;
1000*9880d681SAndroid Build Coastguard Worker Imm = Low;
1001*9880d681SAndroid Build Coastguard Worker Overflow = High - 1;
1002*9880d681SAndroid Build Coastguard Worker }
1003*9880d681SAndroid Build Coastguard Worker }
1004*9880d681SAndroid Build Coastguard Worker
1005*9880d681SAndroid Build Coastguard Worker // There is a hardware bug in SI and CI which prevents address clamping in
1006*9880d681SAndroid Build Coastguard Worker // MUBUF instructions from working correctly with SOffsets. The immediate
1007*9880d681SAndroid Build Coastguard Worker // offset is unaffected.
1008*9880d681SAndroid Build Coastguard Worker if (Overflow > 0 &&
1009*9880d681SAndroid Build Coastguard Worker Subtarget->getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
1010*9880d681SAndroid Build Coastguard Worker return false;
1011*9880d681SAndroid Build Coastguard Worker
1012*9880d681SAndroid Build Coastguard Worker ImmOffset = CurDAG->getTargetConstant(Imm, DL, MVT::i16);
1013*9880d681SAndroid Build Coastguard Worker
1014*9880d681SAndroid Build Coastguard Worker if (Overflow <= 64)
1015*9880d681SAndroid Build Coastguard Worker SOffset = CurDAG->getTargetConstant(Overflow, DL, MVT::i32);
1016*9880d681SAndroid Build Coastguard Worker else
1017*9880d681SAndroid Build Coastguard Worker SOffset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32,
1018*9880d681SAndroid Build Coastguard Worker CurDAG->getTargetConstant(Overflow, DL, MVT::i32)),
1019*9880d681SAndroid Build Coastguard Worker 0);
1020*9880d681SAndroid Build Coastguard Worker
1021*9880d681SAndroid Build Coastguard Worker return true;
1022*9880d681SAndroid Build Coastguard Worker }
1023*9880d681SAndroid Build Coastguard Worker
SelectMUBUFIntrinsicOffset(SDValue Offset,SDValue & SOffset,SDValue & ImmOffset) const1024*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFIntrinsicOffset(SDValue Offset,
1025*9880d681SAndroid Build Coastguard Worker SDValue &SOffset,
1026*9880d681SAndroid Build Coastguard Worker SDValue &ImmOffset) const {
1027*9880d681SAndroid Build Coastguard Worker SDLoc DL(Offset);
1028*9880d681SAndroid Build Coastguard Worker
1029*9880d681SAndroid Build Coastguard Worker if (!isa<ConstantSDNode>(Offset))
1030*9880d681SAndroid Build Coastguard Worker return false;
1031*9880d681SAndroid Build Coastguard Worker
1032*9880d681SAndroid Build Coastguard Worker return SelectMUBUFConstant(Offset, SOffset, ImmOffset);
1033*9880d681SAndroid Build Coastguard Worker }
1034*9880d681SAndroid Build Coastguard Worker
SelectMUBUFIntrinsicVOffset(SDValue Offset,SDValue & SOffset,SDValue & ImmOffset,SDValue & VOffset) const1035*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMUBUFIntrinsicVOffset(SDValue Offset,
1036*9880d681SAndroid Build Coastguard Worker SDValue &SOffset,
1037*9880d681SAndroid Build Coastguard Worker SDValue &ImmOffset,
1038*9880d681SAndroid Build Coastguard Worker SDValue &VOffset) const {
1039*9880d681SAndroid Build Coastguard Worker SDLoc DL(Offset);
1040*9880d681SAndroid Build Coastguard Worker
1041*9880d681SAndroid Build Coastguard Worker // Don't generate an unnecessary voffset for constant offsets.
1042*9880d681SAndroid Build Coastguard Worker if (isa<ConstantSDNode>(Offset)) {
1043*9880d681SAndroid Build Coastguard Worker SDValue Tmp1, Tmp2;
1044*9880d681SAndroid Build Coastguard Worker
1045*9880d681SAndroid Build Coastguard Worker // When necessary, use a voffset in <= CI anyway to work around a hardware
1046*9880d681SAndroid Build Coastguard Worker // bug.
1047*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() > AMDGPUSubtarget::SEA_ISLANDS ||
1048*9880d681SAndroid Build Coastguard Worker SelectMUBUFConstant(Offset, Tmp1, Tmp2))
1049*9880d681SAndroid Build Coastguard Worker return false;
1050*9880d681SAndroid Build Coastguard Worker }
1051*9880d681SAndroid Build Coastguard Worker
1052*9880d681SAndroid Build Coastguard Worker if (CurDAG->isBaseWithConstantOffset(Offset)) {
1053*9880d681SAndroid Build Coastguard Worker SDValue N0 = Offset.getOperand(0);
1054*9880d681SAndroid Build Coastguard Worker SDValue N1 = Offset.getOperand(1);
1055*9880d681SAndroid Build Coastguard Worker if (cast<ConstantSDNode>(N1)->getSExtValue() >= 0 &&
1056*9880d681SAndroid Build Coastguard Worker SelectMUBUFConstant(N1, SOffset, ImmOffset)) {
1057*9880d681SAndroid Build Coastguard Worker VOffset = N0;
1058*9880d681SAndroid Build Coastguard Worker return true;
1059*9880d681SAndroid Build Coastguard Worker }
1060*9880d681SAndroid Build Coastguard Worker }
1061*9880d681SAndroid Build Coastguard Worker
1062*9880d681SAndroid Build Coastguard Worker SOffset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1063*9880d681SAndroid Build Coastguard Worker ImmOffset = CurDAG->getTargetConstant(0, DL, MVT::i16);
1064*9880d681SAndroid Build Coastguard Worker VOffset = Offset;
1065*9880d681SAndroid Build Coastguard Worker
1066*9880d681SAndroid Build Coastguard Worker return true;
1067*9880d681SAndroid Build Coastguard Worker }
1068*9880d681SAndroid Build Coastguard Worker
SelectFlat(SDValue Addr,SDValue & VAddr,SDValue & SLC,SDValue & TFE) const1069*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectFlat(SDValue Addr,
1070*9880d681SAndroid Build Coastguard Worker SDValue &VAddr,
1071*9880d681SAndroid Build Coastguard Worker SDValue &SLC,
1072*9880d681SAndroid Build Coastguard Worker SDValue &TFE) const {
1073*9880d681SAndroid Build Coastguard Worker VAddr = Addr;
1074*9880d681SAndroid Build Coastguard Worker TFE = SLC = CurDAG->getTargetConstant(0, SDLoc(), MVT::i1);
1075*9880d681SAndroid Build Coastguard Worker return true;
1076*9880d681SAndroid Build Coastguard Worker }
1077*9880d681SAndroid Build Coastguard Worker
1078*9880d681SAndroid Build Coastguard Worker ///
1079*9880d681SAndroid Build Coastguard Worker /// \param EncodedOffset This is the immediate value that will be encoded
1080*9880d681SAndroid Build Coastguard Worker /// directly into the instruction. On SI/CI the \p EncodedOffset
1081*9880d681SAndroid Build Coastguard Worker /// will be in units of dwords and on VI+ it will be units of bytes.
isLegalSMRDImmOffset(const AMDGPUSubtarget * ST,int64_t EncodedOffset)1082*9880d681SAndroid Build Coastguard Worker static bool isLegalSMRDImmOffset(const AMDGPUSubtarget *ST,
1083*9880d681SAndroid Build Coastguard Worker int64_t EncodedOffset) {
1084*9880d681SAndroid Build Coastguard Worker return ST->getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS ?
1085*9880d681SAndroid Build Coastguard Worker isUInt<8>(EncodedOffset) : isUInt<20>(EncodedOffset);
1086*9880d681SAndroid Build Coastguard Worker }
1087*9880d681SAndroid Build Coastguard Worker
SelectSMRDOffset(SDValue ByteOffsetNode,SDValue & Offset,bool & Imm) const1088*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode,
1089*9880d681SAndroid Build Coastguard Worker SDValue &Offset, bool &Imm) const {
1090*9880d681SAndroid Build Coastguard Worker
1091*9880d681SAndroid Build Coastguard Worker // FIXME: Handle non-constant offsets.
1092*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C = dyn_cast<ConstantSDNode>(ByteOffsetNode);
1093*9880d681SAndroid Build Coastguard Worker if (!C)
1094*9880d681SAndroid Build Coastguard Worker return false;
1095*9880d681SAndroid Build Coastguard Worker
1096*9880d681SAndroid Build Coastguard Worker SDLoc SL(ByteOffsetNode);
1097*9880d681SAndroid Build Coastguard Worker AMDGPUSubtarget::Generation Gen = Subtarget->getGeneration();
1098*9880d681SAndroid Build Coastguard Worker int64_t ByteOffset = C->getSExtValue();
1099*9880d681SAndroid Build Coastguard Worker int64_t EncodedOffset = Gen < AMDGPUSubtarget::VOLCANIC_ISLANDS ?
1100*9880d681SAndroid Build Coastguard Worker ByteOffset >> 2 : ByteOffset;
1101*9880d681SAndroid Build Coastguard Worker
1102*9880d681SAndroid Build Coastguard Worker if (isLegalSMRDImmOffset(Subtarget, EncodedOffset)) {
1103*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32);
1104*9880d681SAndroid Build Coastguard Worker Imm = true;
1105*9880d681SAndroid Build Coastguard Worker return true;
1106*9880d681SAndroid Build Coastguard Worker }
1107*9880d681SAndroid Build Coastguard Worker
1108*9880d681SAndroid Build Coastguard Worker if (!isUInt<32>(EncodedOffset) || !isUInt<32>(ByteOffset))
1109*9880d681SAndroid Build Coastguard Worker return false;
1110*9880d681SAndroid Build Coastguard Worker
1111*9880d681SAndroid Build Coastguard Worker if (Gen == AMDGPUSubtarget::SEA_ISLANDS && isUInt<32>(EncodedOffset)) {
1112*9880d681SAndroid Build Coastguard Worker // 32-bit Immediates are supported on Sea Islands.
1113*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(EncodedOffset, SL, MVT::i32);
1114*9880d681SAndroid Build Coastguard Worker } else {
1115*9880d681SAndroid Build Coastguard Worker SDValue C32Bit = CurDAG->getTargetConstant(ByteOffset, SL, MVT::i32);
1116*9880d681SAndroid Build Coastguard Worker Offset = SDValue(CurDAG->getMachineNode(AMDGPU::S_MOV_B32, SL, MVT::i32,
1117*9880d681SAndroid Build Coastguard Worker C32Bit), 0);
1118*9880d681SAndroid Build Coastguard Worker }
1119*9880d681SAndroid Build Coastguard Worker Imm = false;
1120*9880d681SAndroid Build Coastguard Worker return true;
1121*9880d681SAndroid Build Coastguard Worker }
1122*9880d681SAndroid Build Coastguard Worker
SelectSMRD(SDValue Addr,SDValue & SBase,SDValue & Offset,bool & Imm) const1123*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectSMRD(SDValue Addr, SDValue &SBase,
1124*9880d681SAndroid Build Coastguard Worker SDValue &Offset, bool &Imm) const {
1125*9880d681SAndroid Build Coastguard Worker
1126*9880d681SAndroid Build Coastguard Worker SDLoc SL(Addr);
1127*9880d681SAndroid Build Coastguard Worker if (CurDAG->isBaseWithConstantOffset(Addr)) {
1128*9880d681SAndroid Build Coastguard Worker SDValue N0 = Addr.getOperand(0);
1129*9880d681SAndroid Build Coastguard Worker SDValue N1 = Addr.getOperand(1);
1130*9880d681SAndroid Build Coastguard Worker
1131*9880d681SAndroid Build Coastguard Worker if (SelectSMRDOffset(N1, Offset, Imm)) {
1132*9880d681SAndroid Build Coastguard Worker SBase = N0;
1133*9880d681SAndroid Build Coastguard Worker return true;
1134*9880d681SAndroid Build Coastguard Worker }
1135*9880d681SAndroid Build Coastguard Worker }
1136*9880d681SAndroid Build Coastguard Worker SBase = Addr;
1137*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, SL, MVT::i32);
1138*9880d681SAndroid Build Coastguard Worker Imm = true;
1139*9880d681SAndroid Build Coastguard Worker return true;
1140*9880d681SAndroid Build Coastguard Worker }
1141*9880d681SAndroid Build Coastguard Worker
SelectSMRDImm(SDValue Addr,SDValue & SBase,SDValue & Offset) const1142*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectSMRDImm(SDValue Addr, SDValue &SBase,
1143*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const {
1144*9880d681SAndroid Build Coastguard Worker bool Imm;
1145*9880d681SAndroid Build Coastguard Worker return SelectSMRD(Addr, SBase, Offset, Imm) && Imm;
1146*9880d681SAndroid Build Coastguard Worker }
1147*9880d681SAndroid Build Coastguard Worker
SelectSMRDImm32(SDValue Addr,SDValue & SBase,SDValue & Offset) const1148*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectSMRDImm32(SDValue Addr, SDValue &SBase,
1149*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const {
1150*9880d681SAndroid Build Coastguard Worker
1151*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() != AMDGPUSubtarget::SEA_ISLANDS)
1152*9880d681SAndroid Build Coastguard Worker return false;
1153*9880d681SAndroid Build Coastguard Worker
1154*9880d681SAndroid Build Coastguard Worker bool Imm;
1155*9880d681SAndroid Build Coastguard Worker if (!SelectSMRD(Addr, SBase, Offset, Imm))
1156*9880d681SAndroid Build Coastguard Worker return false;
1157*9880d681SAndroid Build Coastguard Worker
1158*9880d681SAndroid Build Coastguard Worker return !Imm && isa<ConstantSDNode>(Offset);
1159*9880d681SAndroid Build Coastguard Worker }
1160*9880d681SAndroid Build Coastguard Worker
SelectSMRDSgpr(SDValue Addr,SDValue & SBase,SDValue & Offset) const1161*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectSMRDSgpr(SDValue Addr, SDValue &SBase,
1162*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const {
1163*9880d681SAndroid Build Coastguard Worker bool Imm;
1164*9880d681SAndroid Build Coastguard Worker return SelectSMRD(Addr, SBase, Offset, Imm) && !Imm &&
1165*9880d681SAndroid Build Coastguard Worker !isa<ConstantSDNode>(Offset);
1166*9880d681SAndroid Build Coastguard Worker }
1167*9880d681SAndroid Build Coastguard Worker
SelectSMRDBufferImm(SDValue Addr,SDValue & Offset) const1168*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm(SDValue Addr,
1169*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const {
1170*9880d681SAndroid Build Coastguard Worker bool Imm;
1171*9880d681SAndroid Build Coastguard Worker return SelectSMRDOffset(Addr, Offset, Imm) && Imm;
1172*9880d681SAndroid Build Coastguard Worker }
1173*9880d681SAndroid Build Coastguard Worker
SelectSMRDBufferImm32(SDValue Addr,SDValue & Offset) const1174*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectSMRDBufferImm32(SDValue Addr,
1175*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const {
1176*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() != AMDGPUSubtarget::SEA_ISLANDS)
1177*9880d681SAndroid Build Coastguard Worker return false;
1178*9880d681SAndroid Build Coastguard Worker
1179*9880d681SAndroid Build Coastguard Worker bool Imm;
1180*9880d681SAndroid Build Coastguard Worker if (!SelectSMRDOffset(Addr, Offset, Imm))
1181*9880d681SAndroid Build Coastguard Worker return false;
1182*9880d681SAndroid Build Coastguard Worker
1183*9880d681SAndroid Build Coastguard Worker return !Imm && isa<ConstantSDNode>(Offset);
1184*9880d681SAndroid Build Coastguard Worker }
1185*9880d681SAndroid Build Coastguard Worker
SelectSMRDBufferSgpr(SDValue Addr,SDValue & Offset) const1186*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectSMRDBufferSgpr(SDValue Addr,
1187*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const {
1188*9880d681SAndroid Build Coastguard Worker bool Imm;
1189*9880d681SAndroid Build Coastguard Worker return SelectSMRDOffset(Addr, Offset, Imm) && !Imm &&
1190*9880d681SAndroid Build Coastguard Worker !isa<ConstantSDNode>(Offset);
1191*9880d681SAndroid Build Coastguard Worker }
1192*9880d681SAndroid Build Coastguard Worker
SelectMOVRELOffset(SDValue Index,SDValue & Base,SDValue & Offset) const1193*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectMOVRELOffset(SDValue Index,
1194*9880d681SAndroid Build Coastguard Worker SDValue &Base,
1195*9880d681SAndroid Build Coastguard Worker SDValue &Offset) const {
1196*9880d681SAndroid Build Coastguard Worker SDLoc DL(Index);
1197*9880d681SAndroid Build Coastguard Worker
1198*9880d681SAndroid Build Coastguard Worker if (CurDAG->isBaseWithConstantOffset(Index)) {
1199*9880d681SAndroid Build Coastguard Worker SDValue N0 = Index.getOperand(0);
1200*9880d681SAndroid Build Coastguard Worker SDValue N1 = Index.getOperand(1);
1201*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C1 = cast<ConstantSDNode>(N1);
1202*9880d681SAndroid Build Coastguard Worker
1203*9880d681SAndroid Build Coastguard Worker // (add n0, c0)
1204*9880d681SAndroid Build Coastguard Worker Base = N0;
1205*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(C1->getZExtValue(), DL, MVT::i32);
1206*9880d681SAndroid Build Coastguard Worker return true;
1207*9880d681SAndroid Build Coastguard Worker }
1208*9880d681SAndroid Build Coastguard Worker
1209*9880d681SAndroid Build Coastguard Worker if (isa<ConstantSDNode>(Index))
1210*9880d681SAndroid Build Coastguard Worker return false;
1211*9880d681SAndroid Build Coastguard Worker
1212*9880d681SAndroid Build Coastguard Worker Base = Index;
1213*9880d681SAndroid Build Coastguard Worker Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
1214*9880d681SAndroid Build Coastguard Worker return true;
1215*9880d681SAndroid Build Coastguard Worker }
1216*9880d681SAndroid Build Coastguard Worker
getS_BFE(unsigned Opcode,const SDLoc & DL,SDValue Val,uint32_t Offset,uint32_t Width)1217*9880d681SAndroid Build Coastguard Worker SDNode *AMDGPUDAGToDAGISel::getS_BFE(unsigned Opcode, const SDLoc &DL,
1218*9880d681SAndroid Build Coastguard Worker SDValue Val, uint32_t Offset,
1219*9880d681SAndroid Build Coastguard Worker uint32_t Width) {
1220*9880d681SAndroid Build Coastguard Worker // Transformation function, pack the offset and width of a BFE into
1221*9880d681SAndroid Build Coastguard Worker // the format expected by the S_BFE_I32 / S_BFE_U32. In the second
1222*9880d681SAndroid Build Coastguard Worker // source, bits [5:0] contain the offset and bits [22:16] the width.
1223*9880d681SAndroid Build Coastguard Worker uint32_t PackedVal = Offset | (Width << 16);
1224*9880d681SAndroid Build Coastguard Worker SDValue PackedConst = CurDAG->getTargetConstant(PackedVal, DL, MVT::i32);
1225*9880d681SAndroid Build Coastguard Worker
1226*9880d681SAndroid Build Coastguard Worker return CurDAG->getMachineNode(Opcode, DL, MVT::i32, Val, PackedConst);
1227*9880d681SAndroid Build Coastguard Worker }
1228*9880d681SAndroid Build Coastguard Worker
SelectS_BFEFromShifts(SDNode * N)1229*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::SelectS_BFEFromShifts(SDNode *N) {
1230*9880d681SAndroid Build Coastguard Worker // "(a << b) srl c)" ---> "BFE_U32 a, (c-b), (32-c)
1231*9880d681SAndroid Build Coastguard Worker // "(a << b) sra c)" ---> "BFE_I32 a, (c-b), (32-c)
1232*9880d681SAndroid Build Coastguard Worker // Predicate: 0 < b <= c < 32
1233*9880d681SAndroid Build Coastguard Worker
1234*9880d681SAndroid Build Coastguard Worker const SDValue &Shl = N->getOperand(0);
1235*9880d681SAndroid Build Coastguard Worker ConstantSDNode *B = dyn_cast<ConstantSDNode>(Shl->getOperand(1));
1236*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1));
1237*9880d681SAndroid Build Coastguard Worker
1238*9880d681SAndroid Build Coastguard Worker if (B && C) {
1239*9880d681SAndroid Build Coastguard Worker uint32_t BVal = B->getZExtValue();
1240*9880d681SAndroid Build Coastguard Worker uint32_t CVal = C->getZExtValue();
1241*9880d681SAndroid Build Coastguard Worker
1242*9880d681SAndroid Build Coastguard Worker if (0 < BVal && BVal <= CVal && CVal < 32) {
1243*9880d681SAndroid Build Coastguard Worker bool Signed = N->getOpcode() == ISD::SRA;
1244*9880d681SAndroid Build Coastguard Worker unsigned Opcode = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;
1245*9880d681SAndroid Build Coastguard Worker
1246*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, getS_BFE(Opcode, SDLoc(N), Shl.getOperand(0), CVal - BVal,
1247*9880d681SAndroid Build Coastguard Worker 32 - CVal));
1248*9880d681SAndroid Build Coastguard Worker return;
1249*9880d681SAndroid Build Coastguard Worker }
1250*9880d681SAndroid Build Coastguard Worker }
1251*9880d681SAndroid Build Coastguard Worker SelectCode(N);
1252*9880d681SAndroid Build Coastguard Worker }
1253*9880d681SAndroid Build Coastguard Worker
SelectS_BFE(SDNode * N)1254*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::SelectS_BFE(SDNode *N) {
1255*9880d681SAndroid Build Coastguard Worker switch (N->getOpcode()) {
1256*9880d681SAndroid Build Coastguard Worker case ISD::AND:
1257*9880d681SAndroid Build Coastguard Worker if (N->getOperand(0).getOpcode() == ISD::SRL) {
1258*9880d681SAndroid Build Coastguard Worker // "(a srl b) & mask" ---> "BFE_U32 a, b, popcount(mask)"
1259*9880d681SAndroid Build Coastguard Worker // Predicate: isMask(mask)
1260*9880d681SAndroid Build Coastguard Worker const SDValue &Srl = N->getOperand(0);
1261*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(Srl.getOperand(1));
1262*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(N->getOperand(1));
1263*9880d681SAndroid Build Coastguard Worker
1264*9880d681SAndroid Build Coastguard Worker if (Shift && Mask) {
1265*9880d681SAndroid Build Coastguard Worker uint32_t ShiftVal = Shift->getZExtValue();
1266*9880d681SAndroid Build Coastguard Worker uint32_t MaskVal = Mask->getZExtValue();
1267*9880d681SAndroid Build Coastguard Worker
1268*9880d681SAndroid Build Coastguard Worker if (isMask_32(MaskVal)) {
1269*9880d681SAndroid Build Coastguard Worker uint32_t WidthVal = countPopulation(MaskVal);
1270*9880d681SAndroid Build Coastguard Worker
1271*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N),
1272*9880d681SAndroid Build Coastguard Worker Srl.getOperand(0), ShiftVal, WidthVal));
1273*9880d681SAndroid Build Coastguard Worker return;
1274*9880d681SAndroid Build Coastguard Worker }
1275*9880d681SAndroid Build Coastguard Worker }
1276*9880d681SAndroid Build Coastguard Worker }
1277*9880d681SAndroid Build Coastguard Worker break;
1278*9880d681SAndroid Build Coastguard Worker case ISD::SRL:
1279*9880d681SAndroid Build Coastguard Worker if (N->getOperand(0).getOpcode() == ISD::AND) {
1280*9880d681SAndroid Build Coastguard Worker // "(a & mask) srl b)" ---> "BFE_U32 a, b, popcount(mask >> b)"
1281*9880d681SAndroid Build Coastguard Worker // Predicate: isMask(mask >> b)
1282*9880d681SAndroid Build Coastguard Worker const SDValue &And = N->getOperand(0);
1283*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N->getOperand(1));
1284*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(And->getOperand(1));
1285*9880d681SAndroid Build Coastguard Worker
1286*9880d681SAndroid Build Coastguard Worker if (Shift && Mask) {
1287*9880d681SAndroid Build Coastguard Worker uint32_t ShiftVal = Shift->getZExtValue();
1288*9880d681SAndroid Build Coastguard Worker uint32_t MaskVal = Mask->getZExtValue() >> ShiftVal;
1289*9880d681SAndroid Build Coastguard Worker
1290*9880d681SAndroid Build Coastguard Worker if (isMask_32(MaskVal)) {
1291*9880d681SAndroid Build Coastguard Worker uint32_t WidthVal = countPopulation(MaskVal);
1292*9880d681SAndroid Build Coastguard Worker
1293*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_U32, SDLoc(N),
1294*9880d681SAndroid Build Coastguard Worker And.getOperand(0), ShiftVal, WidthVal));
1295*9880d681SAndroid Build Coastguard Worker return;
1296*9880d681SAndroid Build Coastguard Worker }
1297*9880d681SAndroid Build Coastguard Worker }
1298*9880d681SAndroid Build Coastguard Worker } else if (N->getOperand(0).getOpcode() == ISD::SHL) {
1299*9880d681SAndroid Build Coastguard Worker SelectS_BFEFromShifts(N);
1300*9880d681SAndroid Build Coastguard Worker return;
1301*9880d681SAndroid Build Coastguard Worker }
1302*9880d681SAndroid Build Coastguard Worker break;
1303*9880d681SAndroid Build Coastguard Worker case ISD::SRA:
1304*9880d681SAndroid Build Coastguard Worker if (N->getOperand(0).getOpcode() == ISD::SHL) {
1305*9880d681SAndroid Build Coastguard Worker SelectS_BFEFromShifts(N);
1306*9880d681SAndroid Build Coastguard Worker return;
1307*9880d681SAndroid Build Coastguard Worker }
1308*9880d681SAndroid Build Coastguard Worker break;
1309*9880d681SAndroid Build Coastguard Worker
1310*9880d681SAndroid Build Coastguard Worker case ISD::SIGN_EXTEND_INREG: {
1311*9880d681SAndroid Build Coastguard Worker // sext_inreg (srl x, 16), i8 -> bfe_i32 x, 16, 8
1312*9880d681SAndroid Build Coastguard Worker SDValue Src = N->getOperand(0);
1313*9880d681SAndroid Build Coastguard Worker if (Src.getOpcode() != ISD::SRL)
1314*9880d681SAndroid Build Coastguard Worker break;
1315*9880d681SAndroid Build Coastguard Worker
1316*9880d681SAndroid Build Coastguard Worker const ConstantSDNode *Amt = dyn_cast<ConstantSDNode>(Src.getOperand(1));
1317*9880d681SAndroid Build Coastguard Worker if (!Amt)
1318*9880d681SAndroid Build Coastguard Worker break;
1319*9880d681SAndroid Build Coastguard Worker
1320*9880d681SAndroid Build Coastguard Worker unsigned Width = cast<VTSDNode>(N->getOperand(1))->getVT().getSizeInBits();
1321*9880d681SAndroid Build Coastguard Worker ReplaceNode(N, getS_BFE(AMDGPU::S_BFE_I32, SDLoc(N), Src.getOperand(0),
1322*9880d681SAndroid Build Coastguard Worker Amt->getZExtValue(), Width));
1323*9880d681SAndroid Build Coastguard Worker return;
1324*9880d681SAndroid Build Coastguard Worker }
1325*9880d681SAndroid Build Coastguard Worker }
1326*9880d681SAndroid Build Coastguard Worker
1327*9880d681SAndroid Build Coastguard Worker SelectCode(N);
1328*9880d681SAndroid Build Coastguard Worker }
1329*9880d681SAndroid Build Coastguard Worker
SelectBRCOND(SDNode * N)1330*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::SelectBRCOND(SDNode *N) {
1331*9880d681SAndroid Build Coastguard Worker SDValue Cond = N->getOperand(1);
1332*9880d681SAndroid Build Coastguard Worker
1333*9880d681SAndroid Build Coastguard Worker if (isCBranchSCC(N)) {
1334*9880d681SAndroid Build Coastguard Worker // This brcond will use S_CBRANCH_SCC*, so let tablegen handle it.
1335*9880d681SAndroid Build Coastguard Worker SelectCode(N);
1336*9880d681SAndroid Build Coastguard Worker return;
1337*9880d681SAndroid Build Coastguard Worker }
1338*9880d681SAndroid Build Coastguard Worker
1339*9880d681SAndroid Build Coastguard Worker // The result of VOPC instructions is or'd against ~EXEC before it is
1340*9880d681SAndroid Build Coastguard Worker // written to vcc or another SGPR. This means that the value '1' is always
1341*9880d681SAndroid Build Coastguard Worker // written to the corresponding bit for results that are masked. In order
1342*9880d681SAndroid Build Coastguard Worker // to correctly check against vccz, we need to and VCC with the EXEC
1343*9880d681SAndroid Build Coastguard Worker // register in order to clear the value from the masked bits.
1344*9880d681SAndroid Build Coastguard Worker
1345*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
1346*9880d681SAndroid Build Coastguard Worker
1347*9880d681SAndroid Build Coastguard Worker SDNode *MaskedCond =
1348*9880d681SAndroid Build Coastguard Worker CurDAG->getMachineNode(AMDGPU::S_AND_B64, SL, MVT::i1,
1349*9880d681SAndroid Build Coastguard Worker CurDAG->getRegister(AMDGPU::EXEC, MVT::i1),
1350*9880d681SAndroid Build Coastguard Worker Cond);
1351*9880d681SAndroid Build Coastguard Worker SDValue VCC = CurDAG->getCopyToReg(N->getOperand(0), SL, AMDGPU::VCC,
1352*9880d681SAndroid Build Coastguard Worker SDValue(MaskedCond, 0),
1353*9880d681SAndroid Build Coastguard Worker SDValue()); // Passing SDValue() adds a
1354*9880d681SAndroid Build Coastguard Worker // glue output.
1355*9880d681SAndroid Build Coastguard Worker CurDAG->SelectNodeTo(N, AMDGPU::S_CBRANCH_VCCNZ, MVT::Other,
1356*9880d681SAndroid Build Coastguard Worker N->getOperand(2), // Basic Block
1357*9880d681SAndroid Build Coastguard Worker VCC.getValue(0), // Chain
1358*9880d681SAndroid Build Coastguard Worker VCC.getValue(1)); // Glue
1359*9880d681SAndroid Build Coastguard Worker return;
1360*9880d681SAndroid Build Coastguard Worker }
1361*9880d681SAndroid Build Coastguard Worker
1362*9880d681SAndroid Build Coastguard Worker // This is here because there isn't a way to use the generated sub0_sub1 as the
1363*9880d681SAndroid Build Coastguard Worker // subreg index to EXTRACT_SUBREG in tablegen.
SelectATOMIC_CMP_SWAP(SDNode * N)1364*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::SelectATOMIC_CMP_SWAP(SDNode *N) {
1365*9880d681SAndroid Build Coastguard Worker MemSDNode *Mem = cast<MemSDNode>(N);
1366*9880d681SAndroid Build Coastguard Worker unsigned AS = Mem->getAddressSpace();
1367*9880d681SAndroid Build Coastguard Worker if (AS == AMDGPUAS::FLAT_ADDRESS) {
1368*9880d681SAndroid Build Coastguard Worker SelectCode(N);
1369*9880d681SAndroid Build Coastguard Worker return;
1370*9880d681SAndroid Build Coastguard Worker }
1371*9880d681SAndroid Build Coastguard Worker
1372*9880d681SAndroid Build Coastguard Worker MVT VT = N->getSimpleValueType(0);
1373*9880d681SAndroid Build Coastguard Worker bool Is32 = (VT == MVT::i32);
1374*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
1375*9880d681SAndroid Build Coastguard Worker
1376*9880d681SAndroid Build Coastguard Worker MachineSDNode *CmpSwap = nullptr;
1377*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasAddr64()) {
1378*9880d681SAndroid Build Coastguard Worker SDValue SRsrc, VAddr, SOffset, Offset, GLC, SLC;
1379*9880d681SAndroid Build Coastguard Worker
1380*9880d681SAndroid Build Coastguard Worker if (SelectMUBUFAddr64(Mem->getBasePtr(), SRsrc, VAddr, SOffset, Offset, SLC)) {
1381*9880d681SAndroid Build Coastguard Worker unsigned Opcode = Is32 ? AMDGPU::BUFFER_ATOMIC_CMPSWAP_RTN_ADDR64 :
1382*9880d681SAndroid Build Coastguard Worker AMDGPU::BUFFER_ATOMIC_CMPSWAP_X2_RTN_ADDR64;
1383*9880d681SAndroid Build Coastguard Worker SDValue CmpVal = Mem->getOperand(2);
1384*9880d681SAndroid Build Coastguard Worker
1385*9880d681SAndroid Build Coastguard Worker // XXX - Do we care about glue operands?
1386*9880d681SAndroid Build Coastguard Worker
1387*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = {
1388*9880d681SAndroid Build Coastguard Worker CmpVal, VAddr, SRsrc, SOffset, Offset, SLC, Mem->getChain()
1389*9880d681SAndroid Build Coastguard Worker };
1390*9880d681SAndroid Build Coastguard Worker
1391*9880d681SAndroid Build Coastguard Worker CmpSwap = CurDAG->getMachineNode(Opcode, SL, Mem->getVTList(), Ops);
1392*9880d681SAndroid Build Coastguard Worker }
1393*9880d681SAndroid Build Coastguard Worker }
1394*9880d681SAndroid Build Coastguard Worker
1395*9880d681SAndroid Build Coastguard Worker if (!CmpSwap) {
1396*9880d681SAndroid Build Coastguard Worker SDValue SRsrc, SOffset, Offset, SLC;
1397*9880d681SAndroid Build Coastguard Worker if (SelectMUBUFOffset(Mem->getBasePtr(), SRsrc, SOffset, Offset, SLC)) {
1398*9880d681SAndroid Build Coastguard Worker unsigned Opcode = Is32 ? AMDGPU::BUFFER_ATOMIC_CMPSWAP_RTN_OFFSET :
1399*9880d681SAndroid Build Coastguard Worker AMDGPU::BUFFER_ATOMIC_CMPSWAP_X2_RTN_OFFSET;
1400*9880d681SAndroid Build Coastguard Worker
1401*9880d681SAndroid Build Coastguard Worker SDValue CmpVal = Mem->getOperand(2);
1402*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = {
1403*9880d681SAndroid Build Coastguard Worker CmpVal, SRsrc, SOffset, Offset, SLC, Mem->getChain()
1404*9880d681SAndroid Build Coastguard Worker };
1405*9880d681SAndroid Build Coastguard Worker
1406*9880d681SAndroid Build Coastguard Worker CmpSwap = CurDAG->getMachineNode(Opcode, SL, Mem->getVTList(), Ops);
1407*9880d681SAndroid Build Coastguard Worker }
1408*9880d681SAndroid Build Coastguard Worker }
1409*9880d681SAndroid Build Coastguard Worker
1410*9880d681SAndroid Build Coastguard Worker if (!CmpSwap) {
1411*9880d681SAndroid Build Coastguard Worker SelectCode(N);
1412*9880d681SAndroid Build Coastguard Worker return;
1413*9880d681SAndroid Build Coastguard Worker }
1414*9880d681SAndroid Build Coastguard Worker
1415*9880d681SAndroid Build Coastguard Worker MachineSDNode::mmo_iterator MMOs = MF->allocateMemRefsArray(1);
1416*9880d681SAndroid Build Coastguard Worker *MMOs = Mem->getMemOperand();
1417*9880d681SAndroid Build Coastguard Worker CmpSwap->setMemRefs(MMOs, MMOs + 1);
1418*9880d681SAndroid Build Coastguard Worker
1419*9880d681SAndroid Build Coastguard Worker unsigned SubReg = Is32 ? AMDGPU::sub0 : AMDGPU::sub0_sub1;
1420*9880d681SAndroid Build Coastguard Worker SDValue Extract
1421*9880d681SAndroid Build Coastguard Worker = CurDAG->getTargetExtractSubreg(SubReg, SL, VT, SDValue(CmpSwap, 0));
1422*9880d681SAndroid Build Coastguard Worker
1423*9880d681SAndroid Build Coastguard Worker ReplaceUses(SDValue(N, 0), Extract);
1424*9880d681SAndroid Build Coastguard Worker ReplaceUses(SDValue(N, 1), SDValue(CmpSwap, 1));
1425*9880d681SAndroid Build Coastguard Worker CurDAG->RemoveDeadNode(N);
1426*9880d681SAndroid Build Coastguard Worker }
1427*9880d681SAndroid Build Coastguard Worker
SelectVOP3Mods(SDValue In,SDValue & Src,SDValue & SrcMods) const1428*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectVOP3Mods(SDValue In, SDValue &Src,
1429*9880d681SAndroid Build Coastguard Worker SDValue &SrcMods) const {
1430*9880d681SAndroid Build Coastguard Worker
1431*9880d681SAndroid Build Coastguard Worker unsigned Mods = 0;
1432*9880d681SAndroid Build Coastguard Worker
1433*9880d681SAndroid Build Coastguard Worker Src = In;
1434*9880d681SAndroid Build Coastguard Worker
1435*9880d681SAndroid Build Coastguard Worker if (Src.getOpcode() == ISD::FNEG) {
1436*9880d681SAndroid Build Coastguard Worker Mods |= SISrcMods::NEG;
1437*9880d681SAndroid Build Coastguard Worker Src = Src.getOperand(0);
1438*9880d681SAndroid Build Coastguard Worker }
1439*9880d681SAndroid Build Coastguard Worker
1440*9880d681SAndroid Build Coastguard Worker if (Src.getOpcode() == ISD::FABS) {
1441*9880d681SAndroid Build Coastguard Worker Mods |= SISrcMods::ABS;
1442*9880d681SAndroid Build Coastguard Worker Src = Src.getOperand(0);
1443*9880d681SAndroid Build Coastguard Worker }
1444*9880d681SAndroid Build Coastguard Worker
1445*9880d681SAndroid Build Coastguard Worker SrcMods = CurDAG->getTargetConstant(Mods, SDLoc(In), MVT::i32);
1446*9880d681SAndroid Build Coastguard Worker
1447*9880d681SAndroid Build Coastguard Worker return true;
1448*9880d681SAndroid Build Coastguard Worker }
1449*9880d681SAndroid Build Coastguard Worker
SelectVOP3NoMods(SDValue In,SDValue & Src,SDValue & SrcMods) const1450*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectVOP3NoMods(SDValue In, SDValue &Src,
1451*9880d681SAndroid Build Coastguard Worker SDValue &SrcMods) const {
1452*9880d681SAndroid Build Coastguard Worker bool Res = SelectVOP3Mods(In, Src, SrcMods);
1453*9880d681SAndroid Build Coastguard Worker return Res && cast<ConstantSDNode>(SrcMods)->isNullValue();
1454*9880d681SAndroid Build Coastguard Worker }
1455*9880d681SAndroid Build Coastguard Worker
SelectVOP3Mods0(SDValue In,SDValue & Src,SDValue & SrcMods,SDValue & Clamp,SDValue & Omod) const1456*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectVOP3Mods0(SDValue In, SDValue &Src,
1457*9880d681SAndroid Build Coastguard Worker SDValue &SrcMods, SDValue &Clamp,
1458*9880d681SAndroid Build Coastguard Worker SDValue &Omod) const {
1459*9880d681SAndroid Build Coastguard Worker SDLoc DL(In);
1460*9880d681SAndroid Build Coastguard Worker // FIXME: Handle Clamp and Omod
1461*9880d681SAndroid Build Coastguard Worker Clamp = CurDAG->getTargetConstant(0, DL, MVT::i32);
1462*9880d681SAndroid Build Coastguard Worker Omod = CurDAG->getTargetConstant(0, DL, MVT::i32);
1463*9880d681SAndroid Build Coastguard Worker
1464*9880d681SAndroid Build Coastguard Worker return SelectVOP3Mods(In, Src, SrcMods);
1465*9880d681SAndroid Build Coastguard Worker }
1466*9880d681SAndroid Build Coastguard Worker
SelectVOP3NoMods0(SDValue In,SDValue & Src,SDValue & SrcMods,SDValue & Clamp,SDValue & Omod) const1467*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectVOP3NoMods0(SDValue In, SDValue &Src,
1468*9880d681SAndroid Build Coastguard Worker SDValue &SrcMods, SDValue &Clamp,
1469*9880d681SAndroid Build Coastguard Worker SDValue &Omod) const {
1470*9880d681SAndroid Build Coastguard Worker bool Res = SelectVOP3Mods0(In, Src, SrcMods, Clamp, Omod);
1471*9880d681SAndroid Build Coastguard Worker
1472*9880d681SAndroid Build Coastguard Worker return Res && cast<ConstantSDNode>(SrcMods)->isNullValue() &&
1473*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(Clamp)->isNullValue() &&
1474*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(Omod)->isNullValue();
1475*9880d681SAndroid Build Coastguard Worker }
1476*9880d681SAndroid Build Coastguard Worker
SelectVOP3Mods0Clamp(SDValue In,SDValue & Src,SDValue & SrcMods,SDValue & Omod) const1477*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp(SDValue In, SDValue &Src,
1478*9880d681SAndroid Build Coastguard Worker SDValue &SrcMods,
1479*9880d681SAndroid Build Coastguard Worker SDValue &Omod) const {
1480*9880d681SAndroid Build Coastguard Worker // FIXME: Handle Omod
1481*9880d681SAndroid Build Coastguard Worker Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
1482*9880d681SAndroid Build Coastguard Worker
1483*9880d681SAndroid Build Coastguard Worker return SelectVOP3Mods(In, Src, SrcMods);
1484*9880d681SAndroid Build Coastguard Worker }
1485*9880d681SAndroid Build Coastguard Worker
SelectVOP3Mods0Clamp0OMod(SDValue In,SDValue & Src,SDValue & SrcMods,SDValue & Clamp,SDValue & Omod) const1486*9880d681SAndroid Build Coastguard Worker bool AMDGPUDAGToDAGISel::SelectVOP3Mods0Clamp0OMod(SDValue In, SDValue &Src,
1487*9880d681SAndroid Build Coastguard Worker SDValue &SrcMods,
1488*9880d681SAndroid Build Coastguard Worker SDValue &Clamp,
1489*9880d681SAndroid Build Coastguard Worker SDValue &Omod) const {
1490*9880d681SAndroid Build Coastguard Worker Clamp = Omod = CurDAG->getTargetConstant(0, SDLoc(In), MVT::i32);
1491*9880d681SAndroid Build Coastguard Worker return SelectVOP3Mods(In, Src, SrcMods);
1492*9880d681SAndroid Build Coastguard Worker }
1493*9880d681SAndroid Build Coastguard Worker
PreprocessISelDAG()1494*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::PreprocessISelDAG() {
1495*9880d681SAndroid Build Coastguard Worker MachineFrameInfo *MFI = CurDAG->getMachineFunction().getFrameInfo();
1496*9880d681SAndroid Build Coastguard Worker
1497*9880d681SAndroid Build Coastguard Worker // Handle the perverse case where a frame index is being stored. We don't
1498*9880d681SAndroid Build Coastguard Worker // want to see multiple frame index operands on the same instruction since
1499*9880d681SAndroid Build Coastguard Worker // it complicates things and violates some assumptions about frame index
1500*9880d681SAndroid Build Coastguard Worker // lowering.
1501*9880d681SAndroid Build Coastguard Worker for (int I = MFI->getObjectIndexBegin(), E = MFI->getObjectIndexEnd();
1502*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1503*9880d681SAndroid Build Coastguard Worker SDValue FI = CurDAG->getTargetFrameIndex(I, MVT::i32);
1504*9880d681SAndroid Build Coastguard Worker
1505*9880d681SAndroid Build Coastguard Worker // It's possible that we have a frame index defined in the function that
1506*9880d681SAndroid Build Coastguard Worker // isn't used in this block.
1507*9880d681SAndroid Build Coastguard Worker if (FI.use_empty())
1508*9880d681SAndroid Build Coastguard Worker continue;
1509*9880d681SAndroid Build Coastguard Worker
1510*9880d681SAndroid Build Coastguard Worker // Skip over the AssertZext inserted during lowering.
1511*9880d681SAndroid Build Coastguard Worker SDValue EffectiveFI = FI;
1512*9880d681SAndroid Build Coastguard Worker auto It = FI->use_begin();
1513*9880d681SAndroid Build Coastguard Worker if (It->getOpcode() == ISD::AssertZext && FI->hasOneUse()) {
1514*9880d681SAndroid Build Coastguard Worker EffectiveFI = SDValue(*It, 0);
1515*9880d681SAndroid Build Coastguard Worker It = EffectiveFI->use_begin();
1516*9880d681SAndroid Build Coastguard Worker }
1517*9880d681SAndroid Build Coastguard Worker
1518*9880d681SAndroid Build Coastguard Worker for (auto It = EffectiveFI->use_begin(); !It.atEnd(); ) {
1519*9880d681SAndroid Build Coastguard Worker SDUse &Use = It.getUse();
1520*9880d681SAndroid Build Coastguard Worker SDNode *User = Use.getUser();
1521*9880d681SAndroid Build Coastguard Worker unsigned OpIdx = It.getOperandNo();
1522*9880d681SAndroid Build Coastguard Worker ++It;
1523*9880d681SAndroid Build Coastguard Worker
1524*9880d681SAndroid Build Coastguard Worker if (MemSDNode *M = dyn_cast<MemSDNode>(User)) {
1525*9880d681SAndroid Build Coastguard Worker unsigned PtrIdx = M->getOpcode() == ISD::STORE ? 2 : 1;
1526*9880d681SAndroid Build Coastguard Worker if (OpIdx == PtrIdx)
1527*9880d681SAndroid Build Coastguard Worker continue;
1528*9880d681SAndroid Build Coastguard Worker
1529*9880d681SAndroid Build Coastguard Worker unsigned OpN = M->getNumOperands();
1530*9880d681SAndroid Build Coastguard Worker SDValue NewOps[8];
1531*9880d681SAndroid Build Coastguard Worker
1532*9880d681SAndroid Build Coastguard Worker assert(OpN < array_lengthof(NewOps));
1533*9880d681SAndroid Build Coastguard Worker for (unsigned Op = 0; Op != OpN; ++Op) {
1534*9880d681SAndroid Build Coastguard Worker if (Op != OpIdx) {
1535*9880d681SAndroid Build Coastguard Worker NewOps[Op] = M->getOperand(Op);
1536*9880d681SAndroid Build Coastguard Worker continue;
1537*9880d681SAndroid Build Coastguard Worker }
1538*9880d681SAndroid Build Coastguard Worker
1539*9880d681SAndroid Build Coastguard Worker MachineSDNode *Mov = CurDAG->getMachineNode(AMDGPU::V_MOV_B32_e32,
1540*9880d681SAndroid Build Coastguard Worker SDLoc(M), MVT::i32, FI);
1541*9880d681SAndroid Build Coastguard Worker NewOps[Op] = SDValue(Mov, 0);
1542*9880d681SAndroid Build Coastguard Worker }
1543*9880d681SAndroid Build Coastguard Worker
1544*9880d681SAndroid Build Coastguard Worker CurDAG->UpdateNodeOperands(M, makeArrayRef(NewOps, OpN));
1545*9880d681SAndroid Build Coastguard Worker }
1546*9880d681SAndroid Build Coastguard Worker }
1547*9880d681SAndroid Build Coastguard Worker }
1548*9880d681SAndroid Build Coastguard Worker }
1549*9880d681SAndroid Build Coastguard Worker
PostprocessISelDAG()1550*9880d681SAndroid Build Coastguard Worker void AMDGPUDAGToDAGISel::PostprocessISelDAG() {
1551*9880d681SAndroid Build Coastguard Worker const AMDGPUTargetLowering& Lowering =
1552*9880d681SAndroid Build Coastguard Worker *static_cast<const AMDGPUTargetLowering*>(getTargetLowering());
1553*9880d681SAndroid Build Coastguard Worker bool IsModified = false;
1554*9880d681SAndroid Build Coastguard Worker do {
1555*9880d681SAndroid Build Coastguard Worker IsModified = false;
1556*9880d681SAndroid Build Coastguard Worker // Go over all selected nodes and try to fold them a bit more
1557*9880d681SAndroid Build Coastguard Worker for (SDNode &Node : CurDAG->allnodes()) {
1558*9880d681SAndroid Build Coastguard Worker MachineSDNode *MachineNode = dyn_cast<MachineSDNode>(&Node);
1559*9880d681SAndroid Build Coastguard Worker if (!MachineNode)
1560*9880d681SAndroid Build Coastguard Worker continue;
1561*9880d681SAndroid Build Coastguard Worker
1562*9880d681SAndroid Build Coastguard Worker SDNode *ResNode = Lowering.PostISelFolding(MachineNode, *CurDAG);
1563*9880d681SAndroid Build Coastguard Worker if (ResNode != &Node) {
1564*9880d681SAndroid Build Coastguard Worker ReplaceUses(&Node, ResNode);
1565*9880d681SAndroid Build Coastguard Worker IsModified = true;
1566*9880d681SAndroid Build Coastguard Worker }
1567*9880d681SAndroid Build Coastguard Worker }
1568*9880d681SAndroid Build Coastguard Worker CurDAG->RemoveDeadNodes();
1569*9880d681SAndroid Build Coastguard Worker } while (IsModified);
1570*9880d681SAndroid Build Coastguard Worker }
1571