1*9880d681SAndroid Build Coastguard Worker //===-- R600ISelLowering.cpp - R600 DAG Lowering Implementation -----------===//
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 Custom DAG lowering for R600
12*9880d681SAndroid Build Coastguard Worker //
13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Worker #include "R600ISelLowering.h"
16*9880d681SAndroid Build Coastguard Worker #include "AMDGPUFrameLowering.h"
17*9880d681SAndroid Build Coastguard Worker #include "AMDGPUIntrinsicInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "AMDGPUSubtarget.h"
19*9880d681SAndroid Build Coastguard Worker #include "R600Defines.h"
20*9880d681SAndroid Build Coastguard Worker #include "R600InstrInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "R600MachineFunctionInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/CallingConvLower.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAG.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Argument.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
30*9880d681SAndroid Build Coastguard Worker
31*9880d681SAndroid Build Coastguard Worker using namespace llvm;
32*9880d681SAndroid Build Coastguard Worker
R600TargetLowering(const TargetMachine & TM,const R600Subtarget & STI)33*9880d681SAndroid Build Coastguard Worker R600TargetLowering::R600TargetLowering(const TargetMachine &TM,
34*9880d681SAndroid Build Coastguard Worker const R600Subtarget &STI)
35*9880d681SAndroid Build Coastguard Worker : AMDGPUTargetLowering(TM, STI), Gen(STI.getGeneration()) {
36*9880d681SAndroid Build Coastguard Worker addRegisterClass(MVT::f32, &AMDGPU::R600_Reg32RegClass);
37*9880d681SAndroid Build Coastguard Worker addRegisterClass(MVT::i32, &AMDGPU::R600_Reg32RegClass);
38*9880d681SAndroid Build Coastguard Worker addRegisterClass(MVT::v2f32, &AMDGPU::R600_Reg64RegClass);
39*9880d681SAndroid Build Coastguard Worker addRegisterClass(MVT::v2i32, &AMDGPU::R600_Reg64RegClass);
40*9880d681SAndroid Build Coastguard Worker addRegisterClass(MVT::v4f32, &AMDGPU::R600_Reg128RegClass);
41*9880d681SAndroid Build Coastguard Worker addRegisterClass(MVT::v4i32, &AMDGPU::R600_Reg128RegClass);
42*9880d681SAndroid Build Coastguard Worker
43*9880d681SAndroid Build Coastguard Worker computeRegisterProperties(STI.getRegisterInfo());
44*9880d681SAndroid Build Coastguard Worker
45*9880d681SAndroid Build Coastguard Worker // Legalize loads and stores to the private address space.
46*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::i32, Custom);
47*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::v2i32, Custom);
48*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::v4i32, Custom);
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker // EXTLOAD should be the same as ZEXTLOAD. It is legal for some address
51*9880d681SAndroid Build Coastguard Worker // spaces, so it is custom lowered to handle those where it isn't.
52*9880d681SAndroid Build Coastguard Worker for (MVT VT : MVT::integer_valuetypes()) {
53*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
54*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Custom);
55*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i16, Custom);
56*9880d681SAndroid Build Coastguard Worker
57*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
58*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i8, Custom);
59*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i16, Custom);
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
62*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::i8, Custom);
63*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::i16, Custom);
64*9880d681SAndroid Build Coastguard Worker }
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker // Workaround for LegalizeDAG asserting on expansion of i1 vector loads.
67*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v2i32, MVT::v2i1, Expand);
68*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, MVT::v2i32, MVT::v2i1, Expand);
69*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, MVT::v2i32, MVT::v2i1, Expand);
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v4i32, MVT::v4i1, Expand);
72*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, MVT::v4i32, MVT::v4i1, Expand);
73*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, MVT::v4i32, MVT::v4i1, Expand);
74*9880d681SAndroid Build Coastguard Worker
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::i8, Custom);
77*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::i32, Custom);
78*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::v2i32, Custom);
79*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::v4i32, Custom);
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::i32, MVT::i8, Custom);
82*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::i32, MVT::i16, Custom);
83*9880d681SAndroid Build Coastguard Worker
84*9880d681SAndroid Build Coastguard Worker // Workaround for LegalizeDAG asserting on expansion of i1 vector stores.
85*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2i32, MVT::v2i1, Expand);
86*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v4i32, MVT::v4i1, Expand);
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker // Set condition code actions
89*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETO, MVT::f32, Expand);
90*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETUO, MVT::f32, Expand);
91*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETLT, MVT::f32, Expand);
92*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETLE, MVT::f32, Expand);
93*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETOLT, MVT::f32, Expand);
94*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETOLE, MVT::f32, Expand);
95*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETONE, MVT::f32, Expand);
96*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETUEQ, MVT::f32, Expand);
97*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETUGE, MVT::f32, Expand);
98*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETUGT, MVT::f32, Expand);
99*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETULT, MVT::f32, Expand);
100*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETULE, MVT::f32, Expand);
101*9880d681SAndroid Build Coastguard Worker
102*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETLE, MVT::i32, Expand);
103*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETLT, MVT::i32, Expand);
104*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETULE, MVT::i32, Expand);
105*9880d681SAndroid Build Coastguard Worker setCondCodeAction(ISD::SETULT, MVT::i32, Expand);
106*9880d681SAndroid Build Coastguard Worker
107*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOS, MVT::f32, Custom);
108*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSIN, MVT::f32, Custom);
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SETCC, MVT::v4i32, Expand);
111*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SETCC, MVT::v2i32, Expand);
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BR_CC, MVT::i32, Expand);
114*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BR_CC, MVT::f32, Expand);
115*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BRCOND, MVT::Other, Custom);
116*9880d681SAndroid Build Coastguard Worker
117*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSUB, MVT::f32, Expand);
118*9880d681SAndroid Build Coastguard Worker
119*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
120*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
121*9880d681SAndroid Build Coastguard Worker
122*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SETCC, MVT::i32, Expand);
123*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SETCC, MVT::f32, Expand);
124*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_UINT, MVT::i1, Custom);
125*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
126*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
127*9880d681SAndroid Build Coastguard Worker
128*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::i32, Expand);
129*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::f32, Expand);
130*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::v2i32, Expand);
131*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::v4i32, Expand);
132*9880d681SAndroid Build Coastguard Worker
133*9880d681SAndroid Build Coastguard Worker // ADD, SUB overflow.
134*9880d681SAndroid Build Coastguard Worker // TODO: turn these into Legal?
135*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasCARRY())
136*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UADDO, MVT::i32, Custom);
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasBORROW())
139*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::USUBO, MVT::i32, Custom);
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker // Expand sign extension of vectors
142*9880d681SAndroid Build Coastguard Worker if (!Subtarget->hasBFE())
143*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i1, Expand);
146*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i1, Expand);
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker if (!Subtarget->hasBFE())
149*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
150*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i8, Expand);
151*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i8, Expand);
152*9880d681SAndroid Build Coastguard Worker
153*9880d681SAndroid Build Coastguard Worker if (!Subtarget->hasBFE())
154*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
155*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i16, Expand);
156*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i16, Expand);
157*9880d681SAndroid Build Coastguard Worker
158*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Legal);
159*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v2i32, Expand);
160*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::v4i32, Expand);
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::Other, Expand);
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FrameIndex, MVT::i32, Custom);
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2i32, Custom);
167*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v2f32, Custom);
168*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4i32, Custom);
169*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4f32, Custom);
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v2i32, Custom);
172*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v2f32, Custom);
173*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4i32, Custom);
174*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f32, Custom);
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker // We don't have 64-bit shifts. Thus we need either SHX i64 or SHX_PARTS i32
177*9880d681SAndroid Build Coastguard Worker // to be Legal/Custom in order to avoid library calls.
178*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
179*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom);
180*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom);
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
183*9880d681SAndroid Build Coastguard Worker
184*9880d681SAndroid Build Coastguard Worker const MVT ScalarIntVTs[] = { MVT::i32, MVT::i64 };
185*9880d681SAndroid Build Coastguard Worker for (MVT VT : ScalarIntVTs) {
186*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ADDC, VT, Expand);
187*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SUBC, VT, Expand);
188*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ADDE, VT, Expand);
189*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SUBE, VT, Expand);
190*9880d681SAndroid Build Coastguard Worker }
191*9880d681SAndroid Build Coastguard Worker
192*9880d681SAndroid Build Coastguard Worker setSchedulingPreference(Sched::Source);
193*9880d681SAndroid Build Coastguard Worker
194*9880d681SAndroid Build Coastguard Worker
195*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::FP_ROUND);
196*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::FP_TO_SINT);
197*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::EXTRACT_VECTOR_ELT);
198*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::SELECT_CC);
199*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::INSERT_VECTOR_ELT);
200*9880d681SAndroid Build Coastguard Worker }
201*9880d681SAndroid Build Coastguard Worker
getSubtarget() const202*9880d681SAndroid Build Coastguard Worker const R600Subtarget *R600TargetLowering::getSubtarget() const {
203*9880d681SAndroid Build Coastguard Worker return static_cast<const R600Subtarget *>(Subtarget);
204*9880d681SAndroid Build Coastguard Worker }
205*9880d681SAndroid Build Coastguard Worker
isEOP(MachineBasicBlock::iterator I)206*9880d681SAndroid Build Coastguard Worker static inline bool isEOP(MachineBasicBlock::iterator I) {
207*9880d681SAndroid Build Coastguard Worker return std::next(I)->getOpcode() == AMDGPU::RETURN;
208*9880d681SAndroid Build Coastguard Worker }
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const211*9880d681SAndroid Build Coastguard Worker R600TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
212*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB) const {
213*9880d681SAndroid Build Coastguard Worker MachineFunction * MF = BB->getParent();
214*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MF->getRegInfo();
215*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I = MI;
216*9880d681SAndroid Build Coastguard Worker const R600InstrInfo *TII = getSubtarget()->getInstrInfo();
217*9880d681SAndroid Build Coastguard Worker
218*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
219*9880d681SAndroid Build Coastguard Worker default:
220*9880d681SAndroid Build Coastguard Worker // Replace LDS_*_RET instruction that don't have any uses with the
221*9880d681SAndroid Build Coastguard Worker // equivalent LDS_*_NORET instruction.
222*9880d681SAndroid Build Coastguard Worker if (TII->isLDSRetInstr(MI.getOpcode())) {
223*9880d681SAndroid Build Coastguard Worker int DstIdx = TII->getOperandIdx(MI.getOpcode(), AMDGPU::OpName::dst);
224*9880d681SAndroid Build Coastguard Worker assert(DstIdx != -1);
225*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder NewMI;
226*9880d681SAndroid Build Coastguard Worker // FIXME: getLDSNoRetOp method only handles LDS_1A1D LDS ops. Add
227*9880d681SAndroid Build Coastguard Worker // LDS_1A2D support and remove this special case.
228*9880d681SAndroid Build Coastguard Worker if (!MRI.use_empty(MI.getOperand(DstIdx).getReg()) ||
229*9880d681SAndroid Build Coastguard Worker MI.getOpcode() == AMDGPU::LDS_CMPST_RET)
230*9880d681SAndroid Build Coastguard Worker return BB;
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker NewMI = BuildMI(*BB, I, BB->findDebugLoc(I),
233*9880d681SAndroid Build Coastguard Worker TII->get(AMDGPU::getLDSNoRetOp(MI.getOpcode())));
234*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, e = MI.getNumOperands(); i < e; ++i) {
235*9880d681SAndroid Build Coastguard Worker NewMI.addOperand(MI.getOperand(i));
236*9880d681SAndroid Build Coastguard Worker }
237*9880d681SAndroid Build Coastguard Worker } else {
238*9880d681SAndroid Build Coastguard Worker return AMDGPUTargetLowering::EmitInstrWithCustomInserter(MI, BB);
239*9880d681SAndroid Build Coastguard Worker }
240*9880d681SAndroid Build Coastguard Worker break;
241*9880d681SAndroid Build Coastguard Worker case AMDGPU::CLAMP_R600: {
242*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = TII->buildDefaultInstruction(
243*9880d681SAndroid Build Coastguard Worker *BB, I, AMDGPU::MOV, MI.getOperand(0).getReg(),
244*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).getReg());
245*9880d681SAndroid Build Coastguard Worker TII->addFlag(*NewMI, 0, MO_FLAG_CLAMP);
246*9880d681SAndroid Build Coastguard Worker break;
247*9880d681SAndroid Build Coastguard Worker }
248*9880d681SAndroid Build Coastguard Worker
249*9880d681SAndroid Build Coastguard Worker case AMDGPU::FABS_R600: {
250*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = TII->buildDefaultInstruction(
251*9880d681SAndroid Build Coastguard Worker *BB, I, AMDGPU::MOV, MI.getOperand(0).getReg(),
252*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).getReg());
253*9880d681SAndroid Build Coastguard Worker TII->addFlag(*NewMI, 0, MO_FLAG_ABS);
254*9880d681SAndroid Build Coastguard Worker break;
255*9880d681SAndroid Build Coastguard Worker }
256*9880d681SAndroid Build Coastguard Worker
257*9880d681SAndroid Build Coastguard Worker case AMDGPU::FNEG_R600: {
258*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = TII->buildDefaultInstruction(
259*9880d681SAndroid Build Coastguard Worker *BB, I, AMDGPU::MOV, MI.getOperand(0).getReg(),
260*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).getReg());
261*9880d681SAndroid Build Coastguard Worker TII->addFlag(*NewMI, 0, MO_FLAG_NEG);
262*9880d681SAndroid Build Coastguard Worker break;
263*9880d681SAndroid Build Coastguard Worker }
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker case AMDGPU::MASK_WRITE: {
266*9880d681SAndroid Build Coastguard Worker unsigned maskedRegister = MI.getOperand(0).getReg();
267*9880d681SAndroid Build Coastguard Worker assert(TargetRegisterInfo::isVirtualRegister(maskedRegister));
268*9880d681SAndroid Build Coastguard Worker MachineInstr * defInstr = MRI.getVRegDef(maskedRegister);
269*9880d681SAndroid Build Coastguard Worker TII->addFlag(*defInstr, 0, MO_FLAG_MASK);
270*9880d681SAndroid Build Coastguard Worker break;
271*9880d681SAndroid Build Coastguard Worker }
272*9880d681SAndroid Build Coastguard Worker
273*9880d681SAndroid Build Coastguard Worker case AMDGPU::MOV_IMM_F32:
274*9880d681SAndroid Build Coastguard Worker TII->buildMovImm(*BB, I, MI.getOperand(0).getReg(), MI.getOperand(1)
275*9880d681SAndroid Build Coastguard Worker .getFPImm()
276*9880d681SAndroid Build Coastguard Worker ->getValueAPF()
277*9880d681SAndroid Build Coastguard Worker .bitcastToAPInt()
278*9880d681SAndroid Build Coastguard Worker .getZExtValue());
279*9880d681SAndroid Build Coastguard Worker break;
280*9880d681SAndroid Build Coastguard Worker case AMDGPU::MOV_IMM_I32:
281*9880d681SAndroid Build Coastguard Worker TII->buildMovImm(*BB, I, MI.getOperand(0).getReg(),
282*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).getImm());
283*9880d681SAndroid Build Coastguard Worker break;
284*9880d681SAndroid Build Coastguard Worker case AMDGPU::MOV_IMM_GLOBAL_ADDR: {
285*9880d681SAndroid Build Coastguard Worker //TODO: Perhaps combine this instruction with the next if possible
286*9880d681SAndroid Build Coastguard Worker auto MIB = TII->buildDefaultInstruction(
287*9880d681SAndroid Build Coastguard Worker *BB, MI, AMDGPU::MOV, MI.getOperand(0).getReg(), AMDGPU::ALU_LITERAL_X);
288*9880d681SAndroid Build Coastguard Worker int Idx = TII->getOperandIdx(*MIB, AMDGPU::OpName::literal);
289*9880d681SAndroid Build Coastguard Worker //TODO: Ugh this is rather ugly
290*9880d681SAndroid Build Coastguard Worker MIB->getOperand(Idx) = MI.getOperand(1);
291*9880d681SAndroid Build Coastguard Worker break;
292*9880d681SAndroid Build Coastguard Worker }
293*9880d681SAndroid Build Coastguard Worker case AMDGPU::CONST_COPY: {
294*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = TII->buildDefaultInstruction(
295*9880d681SAndroid Build Coastguard Worker *BB, MI, AMDGPU::MOV, MI.getOperand(0).getReg(), AMDGPU::ALU_CONST);
296*9880d681SAndroid Build Coastguard Worker TII->setImmOperand(*NewMI, AMDGPU::OpName::src0_sel,
297*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).getImm());
298*9880d681SAndroid Build Coastguard Worker break;
299*9880d681SAndroid Build Coastguard Worker }
300*9880d681SAndroid Build Coastguard Worker
301*9880d681SAndroid Build Coastguard Worker case AMDGPU::RAT_WRITE_CACHELESS_32_eg:
302*9880d681SAndroid Build Coastguard Worker case AMDGPU::RAT_WRITE_CACHELESS_64_eg:
303*9880d681SAndroid Build Coastguard Worker case AMDGPU::RAT_WRITE_CACHELESS_128_eg: {
304*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(MI.getOpcode()))
305*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(0))
306*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(1))
307*9880d681SAndroid Build Coastguard Worker .addImm(isEOP(I)); // Set End of program bit
308*9880d681SAndroid Build Coastguard Worker break;
309*9880d681SAndroid Build Coastguard Worker }
310*9880d681SAndroid Build Coastguard Worker case AMDGPU::RAT_STORE_TYPED_eg: {
311*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(MI.getOpcode()))
312*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(0))
313*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(1))
314*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(2))
315*9880d681SAndroid Build Coastguard Worker .addImm(isEOP(I)); // Set End of program bit
316*9880d681SAndroid Build Coastguard Worker break;
317*9880d681SAndroid Build Coastguard Worker }
318*9880d681SAndroid Build Coastguard Worker
319*9880d681SAndroid Build Coastguard Worker case AMDGPU::TXD: {
320*9880d681SAndroid Build Coastguard Worker unsigned T0 = MRI.createVirtualRegister(&AMDGPU::R600_Reg128RegClass);
321*9880d681SAndroid Build Coastguard Worker unsigned T1 = MRI.createVirtualRegister(&AMDGPU::R600_Reg128RegClass);
322*9880d681SAndroid Build Coastguard Worker MachineOperand &RID = MI.getOperand(4);
323*9880d681SAndroid Build Coastguard Worker MachineOperand &SID = MI.getOperand(5);
324*9880d681SAndroid Build Coastguard Worker unsigned TextureId = MI.getOperand(6).getImm();
325*9880d681SAndroid Build Coastguard Worker unsigned SrcX = 0, SrcY = 1, SrcZ = 2, SrcW = 3;
326*9880d681SAndroid Build Coastguard Worker unsigned CTX = 1, CTY = 1, CTZ = 1, CTW = 1;
327*9880d681SAndroid Build Coastguard Worker
328*9880d681SAndroid Build Coastguard Worker switch (TextureId) {
329*9880d681SAndroid Build Coastguard Worker case 5: // Rect
330*9880d681SAndroid Build Coastguard Worker CTX = CTY = 0;
331*9880d681SAndroid Build Coastguard Worker break;
332*9880d681SAndroid Build Coastguard Worker case 6: // Shadow1D
333*9880d681SAndroid Build Coastguard Worker SrcW = SrcZ;
334*9880d681SAndroid Build Coastguard Worker break;
335*9880d681SAndroid Build Coastguard Worker case 7: // Shadow2D
336*9880d681SAndroid Build Coastguard Worker SrcW = SrcZ;
337*9880d681SAndroid Build Coastguard Worker break;
338*9880d681SAndroid Build Coastguard Worker case 8: // ShadowRect
339*9880d681SAndroid Build Coastguard Worker CTX = CTY = 0;
340*9880d681SAndroid Build Coastguard Worker SrcW = SrcZ;
341*9880d681SAndroid Build Coastguard Worker break;
342*9880d681SAndroid Build Coastguard Worker case 9: // 1DArray
343*9880d681SAndroid Build Coastguard Worker SrcZ = SrcY;
344*9880d681SAndroid Build Coastguard Worker CTZ = 0;
345*9880d681SAndroid Build Coastguard Worker break;
346*9880d681SAndroid Build Coastguard Worker case 10: // 2DArray
347*9880d681SAndroid Build Coastguard Worker CTZ = 0;
348*9880d681SAndroid Build Coastguard Worker break;
349*9880d681SAndroid Build Coastguard Worker case 11: // Shadow1DArray
350*9880d681SAndroid Build Coastguard Worker SrcZ = SrcY;
351*9880d681SAndroid Build Coastguard Worker CTZ = 0;
352*9880d681SAndroid Build Coastguard Worker break;
353*9880d681SAndroid Build Coastguard Worker case 12: // Shadow2DArray
354*9880d681SAndroid Build Coastguard Worker CTZ = 0;
355*9880d681SAndroid Build Coastguard Worker break;
356*9880d681SAndroid Build Coastguard Worker }
357*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SET_GRADIENTS_H),
358*9880d681SAndroid Build Coastguard Worker T0)
359*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(3))
360*9880d681SAndroid Build Coastguard Worker .addImm(SrcX)
361*9880d681SAndroid Build Coastguard Worker .addImm(SrcY)
362*9880d681SAndroid Build Coastguard Worker .addImm(SrcZ)
363*9880d681SAndroid Build Coastguard Worker .addImm(SrcW)
364*9880d681SAndroid Build Coastguard Worker .addImm(0)
365*9880d681SAndroid Build Coastguard Worker .addImm(0)
366*9880d681SAndroid Build Coastguard Worker .addImm(0)
367*9880d681SAndroid Build Coastguard Worker .addImm(0)
368*9880d681SAndroid Build Coastguard Worker .addImm(1)
369*9880d681SAndroid Build Coastguard Worker .addImm(2)
370*9880d681SAndroid Build Coastguard Worker .addImm(3)
371*9880d681SAndroid Build Coastguard Worker .addOperand(RID)
372*9880d681SAndroid Build Coastguard Worker .addOperand(SID)
373*9880d681SAndroid Build Coastguard Worker .addImm(CTX)
374*9880d681SAndroid Build Coastguard Worker .addImm(CTY)
375*9880d681SAndroid Build Coastguard Worker .addImm(CTZ)
376*9880d681SAndroid Build Coastguard Worker .addImm(CTW);
377*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SET_GRADIENTS_V),
378*9880d681SAndroid Build Coastguard Worker T1)
379*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(2))
380*9880d681SAndroid Build Coastguard Worker .addImm(SrcX)
381*9880d681SAndroid Build Coastguard Worker .addImm(SrcY)
382*9880d681SAndroid Build Coastguard Worker .addImm(SrcZ)
383*9880d681SAndroid Build Coastguard Worker .addImm(SrcW)
384*9880d681SAndroid Build Coastguard Worker .addImm(0)
385*9880d681SAndroid Build Coastguard Worker .addImm(0)
386*9880d681SAndroid Build Coastguard Worker .addImm(0)
387*9880d681SAndroid Build Coastguard Worker .addImm(0)
388*9880d681SAndroid Build Coastguard Worker .addImm(1)
389*9880d681SAndroid Build Coastguard Worker .addImm(2)
390*9880d681SAndroid Build Coastguard Worker .addImm(3)
391*9880d681SAndroid Build Coastguard Worker .addOperand(RID)
392*9880d681SAndroid Build Coastguard Worker .addOperand(SID)
393*9880d681SAndroid Build Coastguard Worker .addImm(CTX)
394*9880d681SAndroid Build Coastguard Worker .addImm(CTY)
395*9880d681SAndroid Build Coastguard Worker .addImm(CTZ)
396*9880d681SAndroid Build Coastguard Worker .addImm(CTW);
397*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SAMPLE_G))
398*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(0))
399*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(1))
400*9880d681SAndroid Build Coastguard Worker .addImm(SrcX)
401*9880d681SAndroid Build Coastguard Worker .addImm(SrcY)
402*9880d681SAndroid Build Coastguard Worker .addImm(SrcZ)
403*9880d681SAndroid Build Coastguard Worker .addImm(SrcW)
404*9880d681SAndroid Build Coastguard Worker .addImm(0)
405*9880d681SAndroid Build Coastguard Worker .addImm(0)
406*9880d681SAndroid Build Coastguard Worker .addImm(0)
407*9880d681SAndroid Build Coastguard Worker .addImm(0)
408*9880d681SAndroid Build Coastguard Worker .addImm(1)
409*9880d681SAndroid Build Coastguard Worker .addImm(2)
410*9880d681SAndroid Build Coastguard Worker .addImm(3)
411*9880d681SAndroid Build Coastguard Worker .addOperand(RID)
412*9880d681SAndroid Build Coastguard Worker .addOperand(SID)
413*9880d681SAndroid Build Coastguard Worker .addImm(CTX)
414*9880d681SAndroid Build Coastguard Worker .addImm(CTY)
415*9880d681SAndroid Build Coastguard Worker .addImm(CTZ)
416*9880d681SAndroid Build Coastguard Worker .addImm(CTW)
417*9880d681SAndroid Build Coastguard Worker .addReg(T0, RegState::Implicit)
418*9880d681SAndroid Build Coastguard Worker .addReg(T1, RegState::Implicit);
419*9880d681SAndroid Build Coastguard Worker break;
420*9880d681SAndroid Build Coastguard Worker }
421*9880d681SAndroid Build Coastguard Worker
422*9880d681SAndroid Build Coastguard Worker case AMDGPU::TXD_SHADOW: {
423*9880d681SAndroid Build Coastguard Worker unsigned T0 = MRI.createVirtualRegister(&AMDGPU::R600_Reg128RegClass);
424*9880d681SAndroid Build Coastguard Worker unsigned T1 = MRI.createVirtualRegister(&AMDGPU::R600_Reg128RegClass);
425*9880d681SAndroid Build Coastguard Worker MachineOperand &RID = MI.getOperand(4);
426*9880d681SAndroid Build Coastguard Worker MachineOperand &SID = MI.getOperand(5);
427*9880d681SAndroid Build Coastguard Worker unsigned TextureId = MI.getOperand(6).getImm();
428*9880d681SAndroid Build Coastguard Worker unsigned SrcX = 0, SrcY = 1, SrcZ = 2, SrcW = 3;
429*9880d681SAndroid Build Coastguard Worker unsigned CTX = 1, CTY = 1, CTZ = 1, CTW = 1;
430*9880d681SAndroid Build Coastguard Worker
431*9880d681SAndroid Build Coastguard Worker switch (TextureId) {
432*9880d681SAndroid Build Coastguard Worker case 5: // Rect
433*9880d681SAndroid Build Coastguard Worker CTX = CTY = 0;
434*9880d681SAndroid Build Coastguard Worker break;
435*9880d681SAndroid Build Coastguard Worker case 6: // Shadow1D
436*9880d681SAndroid Build Coastguard Worker SrcW = SrcZ;
437*9880d681SAndroid Build Coastguard Worker break;
438*9880d681SAndroid Build Coastguard Worker case 7: // Shadow2D
439*9880d681SAndroid Build Coastguard Worker SrcW = SrcZ;
440*9880d681SAndroid Build Coastguard Worker break;
441*9880d681SAndroid Build Coastguard Worker case 8: // ShadowRect
442*9880d681SAndroid Build Coastguard Worker CTX = CTY = 0;
443*9880d681SAndroid Build Coastguard Worker SrcW = SrcZ;
444*9880d681SAndroid Build Coastguard Worker break;
445*9880d681SAndroid Build Coastguard Worker case 9: // 1DArray
446*9880d681SAndroid Build Coastguard Worker SrcZ = SrcY;
447*9880d681SAndroid Build Coastguard Worker CTZ = 0;
448*9880d681SAndroid Build Coastguard Worker break;
449*9880d681SAndroid Build Coastguard Worker case 10: // 2DArray
450*9880d681SAndroid Build Coastguard Worker CTZ = 0;
451*9880d681SAndroid Build Coastguard Worker break;
452*9880d681SAndroid Build Coastguard Worker case 11: // Shadow1DArray
453*9880d681SAndroid Build Coastguard Worker SrcZ = SrcY;
454*9880d681SAndroid Build Coastguard Worker CTZ = 0;
455*9880d681SAndroid Build Coastguard Worker break;
456*9880d681SAndroid Build Coastguard Worker case 12: // Shadow2DArray
457*9880d681SAndroid Build Coastguard Worker CTZ = 0;
458*9880d681SAndroid Build Coastguard Worker break;
459*9880d681SAndroid Build Coastguard Worker }
460*9880d681SAndroid Build Coastguard Worker
461*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SET_GRADIENTS_H),
462*9880d681SAndroid Build Coastguard Worker T0)
463*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(3))
464*9880d681SAndroid Build Coastguard Worker .addImm(SrcX)
465*9880d681SAndroid Build Coastguard Worker .addImm(SrcY)
466*9880d681SAndroid Build Coastguard Worker .addImm(SrcZ)
467*9880d681SAndroid Build Coastguard Worker .addImm(SrcW)
468*9880d681SAndroid Build Coastguard Worker .addImm(0)
469*9880d681SAndroid Build Coastguard Worker .addImm(0)
470*9880d681SAndroid Build Coastguard Worker .addImm(0)
471*9880d681SAndroid Build Coastguard Worker .addImm(0)
472*9880d681SAndroid Build Coastguard Worker .addImm(1)
473*9880d681SAndroid Build Coastguard Worker .addImm(2)
474*9880d681SAndroid Build Coastguard Worker .addImm(3)
475*9880d681SAndroid Build Coastguard Worker .addOperand(RID)
476*9880d681SAndroid Build Coastguard Worker .addOperand(SID)
477*9880d681SAndroid Build Coastguard Worker .addImm(CTX)
478*9880d681SAndroid Build Coastguard Worker .addImm(CTY)
479*9880d681SAndroid Build Coastguard Worker .addImm(CTZ)
480*9880d681SAndroid Build Coastguard Worker .addImm(CTW);
481*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SET_GRADIENTS_V),
482*9880d681SAndroid Build Coastguard Worker T1)
483*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(2))
484*9880d681SAndroid Build Coastguard Worker .addImm(SrcX)
485*9880d681SAndroid Build Coastguard Worker .addImm(SrcY)
486*9880d681SAndroid Build Coastguard Worker .addImm(SrcZ)
487*9880d681SAndroid Build Coastguard Worker .addImm(SrcW)
488*9880d681SAndroid Build Coastguard Worker .addImm(0)
489*9880d681SAndroid Build Coastguard Worker .addImm(0)
490*9880d681SAndroid Build Coastguard Worker .addImm(0)
491*9880d681SAndroid Build Coastguard Worker .addImm(0)
492*9880d681SAndroid Build Coastguard Worker .addImm(1)
493*9880d681SAndroid Build Coastguard Worker .addImm(2)
494*9880d681SAndroid Build Coastguard Worker .addImm(3)
495*9880d681SAndroid Build Coastguard Worker .addOperand(RID)
496*9880d681SAndroid Build Coastguard Worker .addOperand(SID)
497*9880d681SAndroid Build Coastguard Worker .addImm(CTX)
498*9880d681SAndroid Build Coastguard Worker .addImm(CTY)
499*9880d681SAndroid Build Coastguard Worker .addImm(CTZ)
500*9880d681SAndroid Build Coastguard Worker .addImm(CTW);
501*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::TEX_SAMPLE_C_G))
502*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(0))
503*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(1))
504*9880d681SAndroid Build Coastguard Worker .addImm(SrcX)
505*9880d681SAndroid Build Coastguard Worker .addImm(SrcY)
506*9880d681SAndroid Build Coastguard Worker .addImm(SrcZ)
507*9880d681SAndroid Build Coastguard Worker .addImm(SrcW)
508*9880d681SAndroid Build Coastguard Worker .addImm(0)
509*9880d681SAndroid Build Coastguard Worker .addImm(0)
510*9880d681SAndroid Build Coastguard Worker .addImm(0)
511*9880d681SAndroid Build Coastguard Worker .addImm(0)
512*9880d681SAndroid Build Coastguard Worker .addImm(1)
513*9880d681SAndroid Build Coastguard Worker .addImm(2)
514*9880d681SAndroid Build Coastguard Worker .addImm(3)
515*9880d681SAndroid Build Coastguard Worker .addOperand(RID)
516*9880d681SAndroid Build Coastguard Worker .addOperand(SID)
517*9880d681SAndroid Build Coastguard Worker .addImm(CTX)
518*9880d681SAndroid Build Coastguard Worker .addImm(CTY)
519*9880d681SAndroid Build Coastguard Worker .addImm(CTZ)
520*9880d681SAndroid Build Coastguard Worker .addImm(CTW)
521*9880d681SAndroid Build Coastguard Worker .addReg(T0, RegState::Implicit)
522*9880d681SAndroid Build Coastguard Worker .addReg(T1, RegState::Implicit);
523*9880d681SAndroid Build Coastguard Worker break;
524*9880d681SAndroid Build Coastguard Worker }
525*9880d681SAndroid Build Coastguard Worker
526*9880d681SAndroid Build Coastguard Worker case AMDGPU::BRANCH:
527*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::JUMP))
528*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(0));
529*9880d681SAndroid Build Coastguard Worker break;
530*9880d681SAndroid Build Coastguard Worker
531*9880d681SAndroid Build Coastguard Worker case AMDGPU::BRANCH_COND_f32: {
532*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI =
533*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::PRED_X),
534*9880d681SAndroid Build Coastguard Worker AMDGPU::PREDICATE_BIT)
535*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(1))
536*9880d681SAndroid Build Coastguard Worker .addImm(OPCODE_IS_NOT_ZERO)
537*9880d681SAndroid Build Coastguard Worker .addImm(0); // Flags
538*9880d681SAndroid Build Coastguard Worker TII->addFlag(*NewMI, 0, MO_FLAG_PUSH);
539*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::JUMP_COND))
540*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(0))
541*9880d681SAndroid Build Coastguard Worker .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
542*9880d681SAndroid Build Coastguard Worker break;
543*9880d681SAndroid Build Coastguard Worker }
544*9880d681SAndroid Build Coastguard Worker
545*9880d681SAndroid Build Coastguard Worker case AMDGPU::BRANCH_COND_i32: {
546*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI =
547*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::PRED_X),
548*9880d681SAndroid Build Coastguard Worker AMDGPU::PREDICATE_BIT)
549*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(1))
550*9880d681SAndroid Build Coastguard Worker .addImm(OPCODE_IS_NOT_ZERO_INT)
551*9880d681SAndroid Build Coastguard Worker .addImm(0); // Flags
552*9880d681SAndroid Build Coastguard Worker TII->addFlag(*NewMI, 0, MO_FLAG_PUSH);
553*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDGPU::JUMP_COND))
554*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(0))
555*9880d681SAndroid Build Coastguard Worker .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
556*9880d681SAndroid Build Coastguard Worker break;
557*9880d681SAndroid Build Coastguard Worker }
558*9880d681SAndroid Build Coastguard Worker
559*9880d681SAndroid Build Coastguard Worker case AMDGPU::EG_ExportSwz:
560*9880d681SAndroid Build Coastguard Worker case AMDGPU::R600_ExportSwz: {
561*9880d681SAndroid Build Coastguard Worker // Instruction is left unmodified if its not the last one of its type
562*9880d681SAndroid Build Coastguard Worker bool isLastInstructionOfItsType = true;
563*9880d681SAndroid Build Coastguard Worker unsigned InstExportType = MI.getOperand(1).getImm();
564*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator NextExportInst = std::next(I),
565*9880d681SAndroid Build Coastguard Worker EndBlock = BB->end(); NextExportInst != EndBlock;
566*9880d681SAndroid Build Coastguard Worker NextExportInst = std::next(NextExportInst)) {
567*9880d681SAndroid Build Coastguard Worker if (NextExportInst->getOpcode() == AMDGPU::EG_ExportSwz ||
568*9880d681SAndroid Build Coastguard Worker NextExportInst->getOpcode() == AMDGPU::R600_ExportSwz) {
569*9880d681SAndroid Build Coastguard Worker unsigned CurrentInstExportType = NextExportInst->getOperand(1)
570*9880d681SAndroid Build Coastguard Worker .getImm();
571*9880d681SAndroid Build Coastguard Worker if (CurrentInstExportType == InstExportType) {
572*9880d681SAndroid Build Coastguard Worker isLastInstructionOfItsType = false;
573*9880d681SAndroid Build Coastguard Worker break;
574*9880d681SAndroid Build Coastguard Worker }
575*9880d681SAndroid Build Coastguard Worker }
576*9880d681SAndroid Build Coastguard Worker }
577*9880d681SAndroid Build Coastguard Worker bool EOP = isEOP(I);
578*9880d681SAndroid Build Coastguard Worker if (!EOP && !isLastInstructionOfItsType)
579*9880d681SAndroid Build Coastguard Worker return BB;
580*9880d681SAndroid Build Coastguard Worker unsigned CfInst = (MI.getOpcode() == AMDGPU::EG_ExportSwz) ? 84 : 40;
581*9880d681SAndroid Build Coastguard Worker BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(MI.getOpcode()))
582*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(0))
583*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(1))
584*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(2))
585*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(3))
586*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(4))
587*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(5))
588*9880d681SAndroid Build Coastguard Worker .addOperand(MI.getOperand(6))
589*9880d681SAndroid Build Coastguard Worker .addImm(CfInst)
590*9880d681SAndroid Build Coastguard Worker .addImm(EOP);
591*9880d681SAndroid Build Coastguard Worker break;
592*9880d681SAndroid Build Coastguard Worker }
593*9880d681SAndroid Build Coastguard Worker case AMDGPU::RETURN: {
594*9880d681SAndroid Build Coastguard Worker // RETURN instructions must have the live-out registers as implicit uses,
595*9880d681SAndroid Build Coastguard Worker // otherwise they appear dead.
596*9880d681SAndroid Build Coastguard Worker R600MachineFunctionInfo *MFI = MF->getInfo<R600MachineFunctionInfo>();
597*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder MIB(*MF, MI);
598*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = MFI->LiveOuts.size(); i != e; ++i)
599*9880d681SAndroid Build Coastguard Worker MIB.addReg(MFI->LiveOuts[i], RegState::Implicit);
600*9880d681SAndroid Build Coastguard Worker return BB;
601*9880d681SAndroid Build Coastguard Worker }
602*9880d681SAndroid Build Coastguard Worker }
603*9880d681SAndroid Build Coastguard Worker
604*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
605*9880d681SAndroid Build Coastguard Worker return BB;
606*9880d681SAndroid Build Coastguard Worker }
607*9880d681SAndroid Build Coastguard Worker
608*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
609*9880d681SAndroid Build Coastguard Worker // Custom DAG Lowering Operations
610*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
611*9880d681SAndroid Build Coastguard Worker
LowerOperation(SDValue Op,SelectionDAG & DAG) const612*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
613*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
614*9880d681SAndroid Build Coastguard Worker R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
615*9880d681SAndroid Build Coastguard Worker switch (Op.getOpcode()) {
616*9880d681SAndroid Build Coastguard Worker default: return AMDGPUTargetLowering::LowerOperation(Op, DAG);
617*9880d681SAndroid Build Coastguard Worker case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG);
618*9880d681SAndroid Build Coastguard Worker case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG);
619*9880d681SAndroid Build Coastguard Worker case ISD::SHL_PARTS: return LowerSHLParts(Op, DAG);
620*9880d681SAndroid Build Coastguard Worker case ISD::SRA_PARTS:
621*9880d681SAndroid Build Coastguard Worker case ISD::SRL_PARTS: return LowerSRXParts(Op, DAG);
622*9880d681SAndroid Build Coastguard Worker case ISD::UADDO: return LowerUADDSUBO(Op, DAG, ISD::ADD, AMDGPUISD::CARRY);
623*9880d681SAndroid Build Coastguard Worker case ISD::USUBO: return LowerUADDSUBO(Op, DAG, ISD::SUB, AMDGPUISD::BORROW);
624*9880d681SAndroid Build Coastguard Worker case ISD::FCOS:
625*9880d681SAndroid Build Coastguard Worker case ISD::FSIN: return LowerTrig(Op, DAG);
626*9880d681SAndroid Build Coastguard Worker case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
627*9880d681SAndroid Build Coastguard Worker case ISD::STORE: return LowerSTORE(Op, DAG);
628*9880d681SAndroid Build Coastguard Worker case ISD::LOAD: {
629*9880d681SAndroid Build Coastguard Worker SDValue Result = LowerLOAD(Op, DAG);
630*9880d681SAndroid Build Coastguard Worker assert((!Result.getNode() ||
631*9880d681SAndroid Build Coastguard Worker Result.getNode()->getNumValues() == 2) &&
632*9880d681SAndroid Build Coastguard Worker "Load should return a value and a chain");
633*9880d681SAndroid Build Coastguard Worker return Result;
634*9880d681SAndroid Build Coastguard Worker }
635*9880d681SAndroid Build Coastguard Worker
636*9880d681SAndroid Build Coastguard Worker case ISD::BRCOND: return LowerBRCOND(Op, DAG);
637*9880d681SAndroid Build Coastguard Worker case ISD::GlobalAddress: return LowerGlobalAddress(MFI, Op, DAG);
638*9880d681SAndroid Build Coastguard Worker case ISD::FrameIndex: return lowerFrameIndex(Op, DAG);
639*9880d681SAndroid Build Coastguard Worker case ISD::INTRINSIC_VOID: {
640*9880d681SAndroid Build Coastguard Worker SDValue Chain = Op.getOperand(0);
641*9880d681SAndroid Build Coastguard Worker unsigned IntrinsicID =
642*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
643*9880d681SAndroid Build Coastguard Worker switch (IntrinsicID) {
644*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::R600_store_swizzle: {
645*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
646*9880d681SAndroid Build Coastguard Worker const SDValue Args[8] = {
647*9880d681SAndroid Build Coastguard Worker Chain,
648*9880d681SAndroid Build Coastguard Worker Op.getOperand(2), // Export Value
649*9880d681SAndroid Build Coastguard Worker Op.getOperand(3), // ArrayBase
650*9880d681SAndroid Build Coastguard Worker Op.getOperand(4), // Type
651*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32), // SWZ_X
652*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, MVT::i32), // SWZ_Y
653*9880d681SAndroid Build Coastguard Worker DAG.getConstant(2, DL, MVT::i32), // SWZ_Z
654*9880d681SAndroid Build Coastguard Worker DAG.getConstant(3, DL, MVT::i32) // SWZ_W
655*9880d681SAndroid Build Coastguard Worker };
656*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::EXPORT, DL, Op.getValueType(), Args);
657*9880d681SAndroid Build Coastguard Worker }
658*9880d681SAndroid Build Coastguard Worker
659*9880d681SAndroid Build Coastguard Worker // default for switch(IntrinsicID)
660*9880d681SAndroid Build Coastguard Worker default: break;
661*9880d681SAndroid Build Coastguard Worker }
662*9880d681SAndroid Build Coastguard Worker // break out of case ISD::INTRINSIC_VOID in switch(Op.getOpcode())
663*9880d681SAndroid Build Coastguard Worker break;
664*9880d681SAndroid Build Coastguard Worker }
665*9880d681SAndroid Build Coastguard Worker case ISD::INTRINSIC_WO_CHAIN: {
666*9880d681SAndroid Build Coastguard Worker unsigned IntrinsicID =
667*9880d681SAndroid Build Coastguard Worker cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
668*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
669*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
670*9880d681SAndroid Build Coastguard Worker switch(IntrinsicID) {
671*9880d681SAndroid Build Coastguard Worker default: return AMDGPUTargetLowering::LowerOperation(Op, DAG);
672*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_tex:
673*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_texc:
674*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txl:
675*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txlc:
676*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txb:
677*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txbc:
678*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txf:
679*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txq:
680*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_ddx:
681*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_ddy: {
682*9880d681SAndroid Build Coastguard Worker unsigned TextureOp;
683*9880d681SAndroid Build Coastguard Worker switch (IntrinsicID) {
684*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_tex:
685*9880d681SAndroid Build Coastguard Worker TextureOp = 0;
686*9880d681SAndroid Build Coastguard Worker break;
687*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_texc:
688*9880d681SAndroid Build Coastguard Worker TextureOp = 1;
689*9880d681SAndroid Build Coastguard Worker break;
690*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txl:
691*9880d681SAndroid Build Coastguard Worker TextureOp = 2;
692*9880d681SAndroid Build Coastguard Worker break;
693*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txlc:
694*9880d681SAndroid Build Coastguard Worker TextureOp = 3;
695*9880d681SAndroid Build Coastguard Worker break;
696*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txb:
697*9880d681SAndroid Build Coastguard Worker TextureOp = 4;
698*9880d681SAndroid Build Coastguard Worker break;
699*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txbc:
700*9880d681SAndroid Build Coastguard Worker TextureOp = 5;
701*9880d681SAndroid Build Coastguard Worker break;
702*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txf:
703*9880d681SAndroid Build Coastguard Worker TextureOp = 6;
704*9880d681SAndroid Build Coastguard Worker break;
705*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_txq:
706*9880d681SAndroid Build Coastguard Worker TextureOp = 7;
707*9880d681SAndroid Build Coastguard Worker break;
708*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_ddx:
709*9880d681SAndroid Build Coastguard Worker TextureOp = 8;
710*9880d681SAndroid Build Coastguard Worker break;
711*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_ddy:
712*9880d681SAndroid Build Coastguard Worker TextureOp = 9;
713*9880d681SAndroid Build Coastguard Worker break;
714*9880d681SAndroid Build Coastguard Worker default:
715*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknow Texture Operation");
716*9880d681SAndroid Build Coastguard Worker }
717*9880d681SAndroid Build Coastguard Worker
718*9880d681SAndroid Build Coastguard Worker SDValue TexArgs[19] = {
719*9880d681SAndroid Build Coastguard Worker DAG.getConstant(TextureOp, DL, MVT::i32),
720*9880d681SAndroid Build Coastguard Worker Op.getOperand(1),
721*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32),
722*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, MVT::i32),
723*9880d681SAndroid Build Coastguard Worker DAG.getConstant(2, DL, MVT::i32),
724*9880d681SAndroid Build Coastguard Worker DAG.getConstant(3, DL, MVT::i32),
725*9880d681SAndroid Build Coastguard Worker Op.getOperand(2),
726*9880d681SAndroid Build Coastguard Worker Op.getOperand(3),
727*9880d681SAndroid Build Coastguard Worker Op.getOperand(4),
728*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32),
729*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, MVT::i32),
730*9880d681SAndroid Build Coastguard Worker DAG.getConstant(2, DL, MVT::i32),
731*9880d681SAndroid Build Coastguard Worker DAG.getConstant(3, DL, MVT::i32),
732*9880d681SAndroid Build Coastguard Worker Op.getOperand(5),
733*9880d681SAndroid Build Coastguard Worker Op.getOperand(6),
734*9880d681SAndroid Build Coastguard Worker Op.getOperand(7),
735*9880d681SAndroid Build Coastguard Worker Op.getOperand(8),
736*9880d681SAndroid Build Coastguard Worker Op.getOperand(9),
737*9880d681SAndroid Build Coastguard Worker Op.getOperand(10)
738*9880d681SAndroid Build Coastguard Worker };
739*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::TEXTURE_FETCH, DL, MVT::v4f32, TexArgs);
740*9880d681SAndroid Build Coastguard Worker }
741*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::r600_dot4: {
742*9880d681SAndroid Build Coastguard Worker SDValue Args[8] = {
743*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, Op.getOperand(1),
744*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32)),
745*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, Op.getOperand(2),
746*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32)),
747*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, Op.getOperand(1),
748*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, MVT::i32)),
749*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, Op.getOperand(2),
750*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, MVT::i32)),
751*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, Op.getOperand(1),
752*9880d681SAndroid Build Coastguard Worker DAG.getConstant(2, DL, MVT::i32)),
753*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, Op.getOperand(2),
754*9880d681SAndroid Build Coastguard Worker DAG.getConstant(2, DL, MVT::i32)),
755*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, Op.getOperand(1),
756*9880d681SAndroid Build Coastguard Worker DAG.getConstant(3, DL, MVT::i32)),
757*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::f32, Op.getOperand(2),
758*9880d681SAndroid Build Coastguard Worker DAG.getConstant(3, DL, MVT::i32))
759*9880d681SAndroid Build Coastguard Worker };
760*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::DOT4, DL, MVT::f32, Args);
761*9880d681SAndroid Build Coastguard Worker }
762*9880d681SAndroid Build Coastguard Worker
763*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_implicitarg_ptr: {
764*9880d681SAndroid Build Coastguard Worker MVT PtrVT = getPointerTy(DAG.getDataLayout(), AMDGPUAS::PARAM_I_ADDRESS);
765*9880d681SAndroid Build Coastguard Worker uint32_t ByteOffset = getImplicitParameterOffset(MFI, FIRST_IMPLICIT);
766*9880d681SAndroid Build Coastguard Worker return DAG.getConstant(ByteOffset, DL, PtrVT);
767*9880d681SAndroid Build Coastguard Worker }
768*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_ngroups_x:
769*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 0);
770*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_ngroups_y:
771*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 1);
772*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_ngroups_z:
773*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 2);
774*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_global_size_x:
775*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 3);
776*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_global_size_y:
777*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 4);
778*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_global_size_z:
779*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 5);
780*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_local_size_x:
781*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 6);
782*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_local_size_y:
783*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 7);
784*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_local_size_z:
785*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, 8);
786*9880d681SAndroid Build Coastguard Worker
787*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_workdim:
788*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::AMDGPU_read_workdim: { // Legacy name.
789*9880d681SAndroid Build Coastguard Worker uint32_t ByteOffset = getImplicitParameterOffset(MFI, GRID_DIM);
790*9880d681SAndroid Build Coastguard Worker return LowerImplicitParameter(DAG, VT, DL, ByteOffset / 4);
791*9880d681SAndroid Build Coastguard Worker }
792*9880d681SAndroid Build Coastguard Worker
793*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_tgid_x:
794*9880d681SAndroid Build Coastguard Worker return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
795*9880d681SAndroid Build Coastguard Worker AMDGPU::T1_X, VT);
796*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_tgid_y:
797*9880d681SAndroid Build Coastguard Worker return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
798*9880d681SAndroid Build Coastguard Worker AMDGPU::T1_Y, VT);
799*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_tgid_z:
800*9880d681SAndroid Build Coastguard Worker return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
801*9880d681SAndroid Build Coastguard Worker AMDGPU::T1_Z, VT);
802*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_tidig_x:
803*9880d681SAndroid Build Coastguard Worker return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
804*9880d681SAndroid Build Coastguard Worker AMDGPU::T0_X, VT);
805*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_tidig_y:
806*9880d681SAndroid Build Coastguard Worker return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
807*9880d681SAndroid Build Coastguard Worker AMDGPU::T0_Y, VT);
808*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_read_tidig_z:
809*9880d681SAndroid Build Coastguard Worker return CreateLiveInRegister(DAG, &AMDGPU::R600_TReg32RegClass,
810*9880d681SAndroid Build Coastguard Worker AMDGPU::T0_Z, VT);
811*9880d681SAndroid Build Coastguard Worker
812*9880d681SAndroid Build Coastguard Worker // FIXME: Should be renamed to r600 prefix
813*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::AMDGPU_rsq_clamped:
814*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::RSQ_CLAMP, DL, VT, Op.getOperand(1));
815*9880d681SAndroid Build Coastguard Worker
816*9880d681SAndroid Build Coastguard Worker case Intrinsic::r600_rsq:
817*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::AMDGPU_rsq: // Legacy name
818*9880d681SAndroid Build Coastguard Worker // XXX - I'm assuming SI's RSQ_LEGACY matches R600's behavior.
819*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::RSQ_LEGACY, DL, VT, Op.getOperand(1));
820*9880d681SAndroid Build Coastguard Worker }
821*9880d681SAndroid Build Coastguard Worker // break out of case ISD::INTRINSIC_WO_CHAIN in switch(Op.getOpcode())
822*9880d681SAndroid Build Coastguard Worker break;
823*9880d681SAndroid Build Coastguard Worker }
824*9880d681SAndroid Build Coastguard Worker } // end switch(Op.getOpcode())
825*9880d681SAndroid Build Coastguard Worker return SDValue();
826*9880d681SAndroid Build Coastguard Worker }
827*9880d681SAndroid Build Coastguard Worker
ReplaceNodeResults(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const828*9880d681SAndroid Build Coastguard Worker void R600TargetLowering::ReplaceNodeResults(SDNode *N,
829*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &Results,
830*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
831*9880d681SAndroid Build Coastguard Worker switch (N->getOpcode()) {
832*9880d681SAndroid Build Coastguard Worker default:
833*9880d681SAndroid Build Coastguard Worker AMDGPUTargetLowering::ReplaceNodeResults(N, Results, DAG);
834*9880d681SAndroid Build Coastguard Worker return;
835*9880d681SAndroid Build Coastguard Worker case ISD::FP_TO_UINT:
836*9880d681SAndroid Build Coastguard Worker if (N->getValueType(0) == MVT::i1) {
837*9880d681SAndroid Build Coastguard Worker Results.push_back(LowerFPTOUINT(N->getOperand(0), DAG));
838*9880d681SAndroid Build Coastguard Worker return;
839*9880d681SAndroid Build Coastguard Worker }
840*9880d681SAndroid Build Coastguard Worker // Fall-through. Since we don't care about out of bounds values
841*9880d681SAndroid Build Coastguard Worker // we can use FP_TO_SINT for uints too. The DAGLegalizer code for uint
842*9880d681SAndroid Build Coastguard Worker // considers some extra cases which are not necessary here.
843*9880d681SAndroid Build Coastguard Worker case ISD::FP_TO_SINT: {
844*9880d681SAndroid Build Coastguard Worker SDValue Result;
845*9880d681SAndroid Build Coastguard Worker if (expandFP_TO_SINT(N, Result, DAG))
846*9880d681SAndroid Build Coastguard Worker Results.push_back(Result);
847*9880d681SAndroid Build Coastguard Worker return;
848*9880d681SAndroid Build Coastguard Worker }
849*9880d681SAndroid Build Coastguard Worker case ISD::SDIVREM: {
850*9880d681SAndroid Build Coastguard Worker SDValue Op = SDValue(N, 1);
851*9880d681SAndroid Build Coastguard Worker SDValue RES = LowerSDIVREM(Op, DAG);
852*9880d681SAndroid Build Coastguard Worker Results.push_back(RES);
853*9880d681SAndroid Build Coastguard Worker Results.push_back(RES.getValue(1));
854*9880d681SAndroid Build Coastguard Worker break;
855*9880d681SAndroid Build Coastguard Worker }
856*9880d681SAndroid Build Coastguard Worker case ISD::UDIVREM: {
857*9880d681SAndroid Build Coastguard Worker SDValue Op = SDValue(N, 0);
858*9880d681SAndroid Build Coastguard Worker LowerUDIVREM64(Op, DAG, Results);
859*9880d681SAndroid Build Coastguard Worker break;
860*9880d681SAndroid Build Coastguard Worker }
861*9880d681SAndroid Build Coastguard Worker }
862*9880d681SAndroid Build Coastguard Worker }
863*9880d681SAndroid Build Coastguard Worker
vectorToVerticalVector(SelectionDAG & DAG,SDValue Vector) const864*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::vectorToVerticalVector(SelectionDAG &DAG,
865*9880d681SAndroid Build Coastguard Worker SDValue Vector) const {
866*9880d681SAndroid Build Coastguard Worker
867*9880d681SAndroid Build Coastguard Worker SDLoc DL(Vector);
868*9880d681SAndroid Build Coastguard Worker EVT VecVT = Vector.getValueType();
869*9880d681SAndroid Build Coastguard Worker EVT EltVT = VecVT.getVectorElementType();
870*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> Args;
871*9880d681SAndroid Build Coastguard Worker
872*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = VecVT.getVectorNumElements();
873*9880d681SAndroid Build Coastguard Worker i != e; ++i) {
874*9880d681SAndroid Build Coastguard Worker Args.push_back(DAG.getNode(
875*9880d681SAndroid Build Coastguard Worker ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Vector,
876*9880d681SAndroid Build Coastguard Worker DAG.getConstant(i, DL, getVectorIdxTy(DAG.getDataLayout()))));
877*9880d681SAndroid Build Coastguard Worker }
878*9880d681SAndroid Build Coastguard Worker
879*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::BUILD_VERTICAL_VECTOR, DL, VecVT, Args);
880*9880d681SAndroid Build Coastguard Worker }
881*9880d681SAndroid Build Coastguard Worker
LowerEXTRACT_VECTOR_ELT(SDValue Op,SelectionDAG & DAG) const882*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op,
883*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
884*9880d681SAndroid Build Coastguard Worker
885*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
886*9880d681SAndroid Build Coastguard Worker SDValue Vector = Op.getOperand(0);
887*9880d681SAndroid Build Coastguard Worker SDValue Index = Op.getOperand(1);
888*9880d681SAndroid Build Coastguard Worker
889*9880d681SAndroid Build Coastguard Worker if (isa<ConstantSDNode>(Index) ||
890*9880d681SAndroid Build Coastguard Worker Vector.getOpcode() == AMDGPUISD::BUILD_VERTICAL_VECTOR)
891*9880d681SAndroid Build Coastguard Worker return Op;
892*9880d681SAndroid Build Coastguard Worker
893*9880d681SAndroid Build Coastguard Worker Vector = vectorToVerticalVector(DAG, Vector);
894*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, Op.getValueType(),
895*9880d681SAndroid Build Coastguard Worker Vector, Index);
896*9880d681SAndroid Build Coastguard Worker }
897*9880d681SAndroid Build Coastguard Worker
LowerINSERT_VECTOR_ELT(SDValue Op,SelectionDAG & DAG) const898*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op,
899*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
900*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
901*9880d681SAndroid Build Coastguard Worker SDValue Vector = Op.getOperand(0);
902*9880d681SAndroid Build Coastguard Worker SDValue Value = Op.getOperand(1);
903*9880d681SAndroid Build Coastguard Worker SDValue Index = Op.getOperand(2);
904*9880d681SAndroid Build Coastguard Worker
905*9880d681SAndroid Build Coastguard Worker if (isa<ConstantSDNode>(Index) ||
906*9880d681SAndroid Build Coastguard Worker Vector.getOpcode() == AMDGPUISD::BUILD_VERTICAL_VECTOR)
907*9880d681SAndroid Build Coastguard Worker return Op;
908*9880d681SAndroid Build Coastguard Worker
909*9880d681SAndroid Build Coastguard Worker Vector = vectorToVerticalVector(DAG, Vector);
910*9880d681SAndroid Build Coastguard Worker SDValue Insert = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, Op.getValueType(),
911*9880d681SAndroid Build Coastguard Worker Vector, Value, Index);
912*9880d681SAndroid Build Coastguard Worker return vectorToVerticalVector(DAG, Insert);
913*9880d681SAndroid Build Coastguard Worker }
914*9880d681SAndroid Build Coastguard Worker
LowerGlobalAddress(AMDGPUMachineFunction * MFI,SDValue Op,SelectionDAG & DAG) const915*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerGlobalAddress(AMDGPUMachineFunction *MFI,
916*9880d681SAndroid Build Coastguard Worker SDValue Op,
917*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
918*9880d681SAndroid Build Coastguard Worker
919*9880d681SAndroid Build Coastguard Worker GlobalAddressSDNode *GSD = cast<GlobalAddressSDNode>(Op);
920*9880d681SAndroid Build Coastguard Worker if (GSD->getAddressSpace() != AMDGPUAS::CONSTANT_ADDRESS)
921*9880d681SAndroid Build Coastguard Worker return AMDGPUTargetLowering::LowerGlobalAddress(MFI, Op, DAG);
922*9880d681SAndroid Build Coastguard Worker
923*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = DAG.getDataLayout();
924*9880d681SAndroid Build Coastguard Worker const GlobalValue *GV = GSD->getGlobal();
925*9880d681SAndroid Build Coastguard Worker MVT ConstPtrVT = getPointerTy(DL, AMDGPUAS::CONSTANT_ADDRESS);
926*9880d681SAndroid Build Coastguard Worker
927*9880d681SAndroid Build Coastguard Worker SDValue GA = DAG.getTargetGlobalAddress(GV, SDLoc(GSD), ConstPtrVT);
928*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::CONST_DATA_PTR, SDLoc(GSD), ConstPtrVT, GA);
929*9880d681SAndroid Build Coastguard Worker }
930*9880d681SAndroid Build Coastguard Worker
LowerTrig(SDValue Op,SelectionDAG & DAG) const931*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerTrig(SDValue Op, SelectionDAG &DAG) const {
932*9880d681SAndroid Build Coastguard Worker // On hw >= R700, COS/SIN input must be between -1. and 1.
933*9880d681SAndroid Build Coastguard Worker // Thus we lower them to TRIG ( FRACT ( x / 2Pi + 0.5) - 0.5)
934*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
935*9880d681SAndroid Build Coastguard Worker SDValue Arg = Op.getOperand(0);
936*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
937*9880d681SAndroid Build Coastguard Worker
938*9880d681SAndroid Build Coastguard Worker // TODO: Should this propagate fast-math-flags?
939*9880d681SAndroid Build Coastguard Worker SDValue FractPart = DAG.getNode(AMDGPUISD::FRACT, DL, VT,
940*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::FADD, DL, VT,
941*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::FMUL, DL, VT, Arg,
942*9880d681SAndroid Build Coastguard Worker DAG.getConstantFP(0.15915494309, DL, MVT::f32)),
943*9880d681SAndroid Build Coastguard Worker DAG.getConstantFP(0.5, DL, MVT::f32)));
944*9880d681SAndroid Build Coastguard Worker unsigned TrigNode;
945*9880d681SAndroid Build Coastguard Worker switch (Op.getOpcode()) {
946*9880d681SAndroid Build Coastguard Worker case ISD::FCOS:
947*9880d681SAndroid Build Coastguard Worker TrigNode = AMDGPUISD::COS_HW;
948*9880d681SAndroid Build Coastguard Worker break;
949*9880d681SAndroid Build Coastguard Worker case ISD::FSIN:
950*9880d681SAndroid Build Coastguard Worker TrigNode = AMDGPUISD::SIN_HW;
951*9880d681SAndroid Build Coastguard Worker break;
952*9880d681SAndroid Build Coastguard Worker default:
953*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Wrong trig opcode");
954*9880d681SAndroid Build Coastguard Worker }
955*9880d681SAndroid Build Coastguard Worker SDValue TrigVal = DAG.getNode(TrigNode, DL, VT,
956*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::FADD, DL, VT, FractPart,
957*9880d681SAndroid Build Coastguard Worker DAG.getConstantFP(-0.5, DL, MVT::f32)));
958*9880d681SAndroid Build Coastguard Worker if (Gen >= R600Subtarget::R700)
959*9880d681SAndroid Build Coastguard Worker return TrigVal;
960*9880d681SAndroid Build Coastguard Worker // On R600 hw, COS/SIN input must be between -Pi and Pi.
961*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::FMUL, DL, VT, TrigVal,
962*9880d681SAndroid Build Coastguard Worker DAG.getConstantFP(3.14159265359, DL, MVT::f32));
963*9880d681SAndroid Build Coastguard Worker }
964*9880d681SAndroid Build Coastguard Worker
LowerSHLParts(SDValue Op,SelectionDAG & DAG) const965*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerSHLParts(SDValue Op, SelectionDAG &DAG) const {
966*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
967*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
968*9880d681SAndroid Build Coastguard Worker
969*9880d681SAndroid Build Coastguard Worker SDValue Lo = Op.getOperand(0);
970*9880d681SAndroid Build Coastguard Worker SDValue Hi = Op.getOperand(1);
971*9880d681SAndroid Build Coastguard Worker SDValue Shift = Op.getOperand(2);
972*9880d681SAndroid Build Coastguard Worker SDValue Zero = DAG.getConstant(0, DL, VT);
973*9880d681SAndroid Build Coastguard Worker SDValue One = DAG.getConstant(1, DL, VT);
974*9880d681SAndroid Build Coastguard Worker
975*9880d681SAndroid Build Coastguard Worker SDValue Width = DAG.getConstant(VT.getSizeInBits(), DL, VT);
976*9880d681SAndroid Build Coastguard Worker SDValue Width1 = DAG.getConstant(VT.getSizeInBits() - 1, DL, VT);
977*9880d681SAndroid Build Coastguard Worker SDValue BigShift = DAG.getNode(ISD::SUB, DL, VT, Shift, Width);
978*9880d681SAndroid Build Coastguard Worker SDValue CompShift = DAG.getNode(ISD::SUB, DL, VT, Width1, Shift);
979*9880d681SAndroid Build Coastguard Worker
980*9880d681SAndroid Build Coastguard Worker // The dance around Width1 is necessary for 0 special case.
981*9880d681SAndroid Build Coastguard Worker // Without it the CompShift might be 32, producing incorrect results in
982*9880d681SAndroid Build Coastguard Worker // Overflow. So we do the shift in two steps, the alternative is to
983*9880d681SAndroid Build Coastguard Worker // add a conditional to filter the special case.
984*9880d681SAndroid Build Coastguard Worker
985*9880d681SAndroid Build Coastguard Worker SDValue Overflow = DAG.getNode(ISD::SRL, DL, VT, Lo, CompShift);
986*9880d681SAndroid Build Coastguard Worker Overflow = DAG.getNode(ISD::SRL, DL, VT, Overflow, One);
987*9880d681SAndroid Build Coastguard Worker
988*9880d681SAndroid Build Coastguard Worker SDValue HiSmall = DAG.getNode(ISD::SHL, DL, VT, Hi, Shift);
989*9880d681SAndroid Build Coastguard Worker HiSmall = DAG.getNode(ISD::OR, DL, VT, HiSmall, Overflow);
990*9880d681SAndroid Build Coastguard Worker SDValue LoSmall = DAG.getNode(ISD::SHL, DL, VT, Lo, Shift);
991*9880d681SAndroid Build Coastguard Worker
992*9880d681SAndroid Build Coastguard Worker SDValue HiBig = DAG.getNode(ISD::SHL, DL, VT, Lo, BigShift);
993*9880d681SAndroid Build Coastguard Worker SDValue LoBig = Zero;
994*9880d681SAndroid Build Coastguard Worker
995*9880d681SAndroid Build Coastguard Worker Hi = DAG.getSelectCC(DL, Shift, Width, HiSmall, HiBig, ISD::SETULT);
996*9880d681SAndroid Build Coastguard Worker Lo = DAG.getSelectCC(DL, Shift, Width, LoSmall, LoBig, ISD::SETULT);
997*9880d681SAndroid Build Coastguard Worker
998*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::MERGE_VALUES, DL, DAG.getVTList(VT,VT), Lo, Hi);
999*9880d681SAndroid Build Coastguard Worker }
1000*9880d681SAndroid Build Coastguard Worker
LowerSRXParts(SDValue Op,SelectionDAG & DAG) const1001*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerSRXParts(SDValue Op, SelectionDAG &DAG) const {
1002*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1003*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1004*9880d681SAndroid Build Coastguard Worker
1005*9880d681SAndroid Build Coastguard Worker SDValue Lo = Op.getOperand(0);
1006*9880d681SAndroid Build Coastguard Worker SDValue Hi = Op.getOperand(1);
1007*9880d681SAndroid Build Coastguard Worker SDValue Shift = Op.getOperand(2);
1008*9880d681SAndroid Build Coastguard Worker SDValue Zero = DAG.getConstant(0, DL, VT);
1009*9880d681SAndroid Build Coastguard Worker SDValue One = DAG.getConstant(1, DL, VT);
1010*9880d681SAndroid Build Coastguard Worker
1011*9880d681SAndroid Build Coastguard Worker const bool SRA = Op.getOpcode() == ISD::SRA_PARTS;
1012*9880d681SAndroid Build Coastguard Worker
1013*9880d681SAndroid Build Coastguard Worker SDValue Width = DAG.getConstant(VT.getSizeInBits(), DL, VT);
1014*9880d681SAndroid Build Coastguard Worker SDValue Width1 = DAG.getConstant(VT.getSizeInBits() - 1, DL, VT);
1015*9880d681SAndroid Build Coastguard Worker SDValue BigShift = DAG.getNode(ISD::SUB, DL, VT, Shift, Width);
1016*9880d681SAndroid Build Coastguard Worker SDValue CompShift = DAG.getNode(ISD::SUB, DL, VT, Width1, Shift);
1017*9880d681SAndroid Build Coastguard Worker
1018*9880d681SAndroid Build Coastguard Worker // The dance around Width1 is necessary for 0 special case.
1019*9880d681SAndroid Build Coastguard Worker // Without it the CompShift might be 32, producing incorrect results in
1020*9880d681SAndroid Build Coastguard Worker // Overflow. So we do the shift in two steps, the alternative is to
1021*9880d681SAndroid Build Coastguard Worker // add a conditional to filter the special case.
1022*9880d681SAndroid Build Coastguard Worker
1023*9880d681SAndroid Build Coastguard Worker SDValue Overflow = DAG.getNode(ISD::SHL, DL, VT, Hi, CompShift);
1024*9880d681SAndroid Build Coastguard Worker Overflow = DAG.getNode(ISD::SHL, DL, VT, Overflow, One);
1025*9880d681SAndroid Build Coastguard Worker
1026*9880d681SAndroid Build Coastguard Worker SDValue HiSmall = DAG.getNode(SRA ? ISD::SRA : ISD::SRL, DL, VT, Hi, Shift);
1027*9880d681SAndroid Build Coastguard Worker SDValue LoSmall = DAG.getNode(ISD::SRL, DL, VT, Lo, Shift);
1028*9880d681SAndroid Build Coastguard Worker LoSmall = DAG.getNode(ISD::OR, DL, VT, LoSmall, Overflow);
1029*9880d681SAndroid Build Coastguard Worker
1030*9880d681SAndroid Build Coastguard Worker SDValue LoBig = DAG.getNode(SRA ? ISD::SRA : ISD::SRL, DL, VT, Hi, BigShift);
1031*9880d681SAndroid Build Coastguard Worker SDValue HiBig = SRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, Width1) : Zero;
1032*9880d681SAndroid Build Coastguard Worker
1033*9880d681SAndroid Build Coastguard Worker Hi = DAG.getSelectCC(DL, Shift, Width, HiSmall, HiBig, ISD::SETULT);
1034*9880d681SAndroid Build Coastguard Worker Lo = DAG.getSelectCC(DL, Shift, Width, LoSmall, LoBig, ISD::SETULT);
1035*9880d681SAndroid Build Coastguard Worker
1036*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::MERGE_VALUES, DL, DAG.getVTList(VT,VT), Lo, Hi);
1037*9880d681SAndroid Build Coastguard Worker }
1038*9880d681SAndroid Build Coastguard Worker
LowerUADDSUBO(SDValue Op,SelectionDAG & DAG,unsigned mainop,unsigned ovf) const1039*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerUADDSUBO(SDValue Op, SelectionDAG &DAG,
1040*9880d681SAndroid Build Coastguard Worker unsigned mainop, unsigned ovf) const {
1041*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1042*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1043*9880d681SAndroid Build Coastguard Worker
1044*9880d681SAndroid Build Coastguard Worker SDValue Lo = Op.getOperand(0);
1045*9880d681SAndroid Build Coastguard Worker SDValue Hi = Op.getOperand(1);
1046*9880d681SAndroid Build Coastguard Worker
1047*9880d681SAndroid Build Coastguard Worker SDValue OVF = DAG.getNode(ovf, DL, VT, Lo, Hi);
1048*9880d681SAndroid Build Coastguard Worker // Extend sign.
1049*9880d681SAndroid Build Coastguard Worker OVF = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, OVF,
1050*9880d681SAndroid Build Coastguard Worker DAG.getValueType(MVT::i1));
1051*9880d681SAndroid Build Coastguard Worker
1052*9880d681SAndroid Build Coastguard Worker SDValue Res = DAG.getNode(mainop, DL, VT, Lo, Hi);
1053*9880d681SAndroid Build Coastguard Worker
1054*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::MERGE_VALUES, DL, DAG.getVTList(VT, VT), Res, OVF);
1055*9880d681SAndroid Build Coastguard Worker }
1056*9880d681SAndroid Build Coastguard Worker
LowerFPTOUINT(SDValue Op,SelectionDAG & DAG) const1057*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerFPTOUINT(SDValue Op, SelectionDAG &DAG) const {
1058*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1059*9880d681SAndroid Build Coastguard Worker return DAG.getNode(
1060*9880d681SAndroid Build Coastguard Worker ISD::SETCC,
1061*9880d681SAndroid Build Coastguard Worker DL,
1062*9880d681SAndroid Build Coastguard Worker MVT::i1,
1063*9880d681SAndroid Build Coastguard Worker Op, DAG.getConstantFP(0.0f, DL, MVT::f32),
1064*9880d681SAndroid Build Coastguard Worker DAG.getCondCode(ISD::SETNE)
1065*9880d681SAndroid Build Coastguard Worker );
1066*9880d681SAndroid Build Coastguard Worker }
1067*9880d681SAndroid Build Coastguard Worker
LowerImplicitParameter(SelectionDAG & DAG,EVT VT,const SDLoc & DL,unsigned DwordOffset) const1068*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerImplicitParameter(SelectionDAG &DAG, EVT VT,
1069*9880d681SAndroid Build Coastguard Worker const SDLoc &DL,
1070*9880d681SAndroid Build Coastguard Worker unsigned DwordOffset) const {
1071*9880d681SAndroid Build Coastguard Worker unsigned ByteOffset = DwordOffset * 4;
1072*9880d681SAndroid Build Coastguard Worker PointerType * PtrType = PointerType::get(VT.getTypeForEVT(*DAG.getContext()),
1073*9880d681SAndroid Build Coastguard Worker AMDGPUAS::CONSTANT_BUFFER_0);
1074*9880d681SAndroid Build Coastguard Worker
1075*9880d681SAndroid Build Coastguard Worker // We shouldn't be using an offset wider than 16-bits for implicit parameters.
1076*9880d681SAndroid Build Coastguard Worker assert(isInt<16>(ByteOffset));
1077*9880d681SAndroid Build Coastguard Worker
1078*9880d681SAndroid Build Coastguard Worker return DAG.getLoad(VT, DL, DAG.getEntryNode(),
1079*9880d681SAndroid Build Coastguard Worker DAG.getConstant(ByteOffset, DL, MVT::i32), // PTR
1080*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(ConstantPointerNull::get(PtrType)),
1081*9880d681SAndroid Build Coastguard Worker false, false, false, 0);
1082*9880d681SAndroid Build Coastguard Worker }
1083*9880d681SAndroid Build Coastguard Worker
isZero(SDValue Op) const1084*9880d681SAndroid Build Coastguard Worker bool R600TargetLowering::isZero(SDValue Op) const {
1085*9880d681SAndroid Build Coastguard Worker if(ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(Op)) {
1086*9880d681SAndroid Build Coastguard Worker return Cst->isNullValue();
1087*9880d681SAndroid Build Coastguard Worker } else if(ConstantFPSDNode *CstFP = dyn_cast<ConstantFPSDNode>(Op)){
1088*9880d681SAndroid Build Coastguard Worker return CstFP->isZero();
1089*9880d681SAndroid Build Coastguard Worker } else {
1090*9880d681SAndroid Build Coastguard Worker return false;
1091*9880d681SAndroid Build Coastguard Worker }
1092*9880d681SAndroid Build Coastguard Worker }
1093*9880d681SAndroid Build Coastguard Worker
isHWTrueValue(SDValue Op) const1094*9880d681SAndroid Build Coastguard Worker bool R600TargetLowering::isHWTrueValue(SDValue Op) const {
1095*9880d681SAndroid Build Coastguard Worker if (ConstantFPSDNode * CFP = dyn_cast<ConstantFPSDNode>(Op)) {
1096*9880d681SAndroid Build Coastguard Worker return CFP->isExactlyValue(1.0);
1097*9880d681SAndroid Build Coastguard Worker }
1098*9880d681SAndroid Build Coastguard Worker return isAllOnesConstant(Op);
1099*9880d681SAndroid Build Coastguard Worker }
1100*9880d681SAndroid Build Coastguard Worker
isHWFalseValue(SDValue Op) const1101*9880d681SAndroid Build Coastguard Worker bool R600TargetLowering::isHWFalseValue(SDValue Op) const {
1102*9880d681SAndroid Build Coastguard Worker if (ConstantFPSDNode * CFP = dyn_cast<ConstantFPSDNode>(Op)) {
1103*9880d681SAndroid Build Coastguard Worker return CFP->getValueAPF().isZero();
1104*9880d681SAndroid Build Coastguard Worker }
1105*9880d681SAndroid Build Coastguard Worker return isNullConstant(Op);
1106*9880d681SAndroid Build Coastguard Worker }
1107*9880d681SAndroid Build Coastguard Worker
LowerSELECT_CC(SDValue Op,SelectionDAG & DAG) const1108*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
1109*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1110*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1111*9880d681SAndroid Build Coastguard Worker
1112*9880d681SAndroid Build Coastguard Worker SDValue LHS = Op.getOperand(0);
1113*9880d681SAndroid Build Coastguard Worker SDValue RHS = Op.getOperand(1);
1114*9880d681SAndroid Build Coastguard Worker SDValue True = Op.getOperand(2);
1115*9880d681SAndroid Build Coastguard Worker SDValue False = Op.getOperand(3);
1116*9880d681SAndroid Build Coastguard Worker SDValue CC = Op.getOperand(4);
1117*9880d681SAndroid Build Coastguard Worker SDValue Temp;
1118*9880d681SAndroid Build Coastguard Worker
1119*9880d681SAndroid Build Coastguard Worker if (VT == MVT::f32) {
1120*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo DCI(DAG, AfterLegalizeVectorOps, true, nullptr);
1121*9880d681SAndroid Build Coastguard Worker SDValue MinMax = CombineFMinMaxLegacy(DL, VT, LHS, RHS, True, False, CC, DCI);
1122*9880d681SAndroid Build Coastguard Worker if (MinMax)
1123*9880d681SAndroid Build Coastguard Worker return MinMax;
1124*9880d681SAndroid Build Coastguard Worker }
1125*9880d681SAndroid Build Coastguard Worker
1126*9880d681SAndroid Build Coastguard Worker // LHS and RHS are guaranteed to be the same value type
1127*9880d681SAndroid Build Coastguard Worker EVT CompareVT = LHS.getValueType();
1128*9880d681SAndroid Build Coastguard Worker
1129*9880d681SAndroid Build Coastguard Worker // Check if we can lower this to a native operation.
1130*9880d681SAndroid Build Coastguard Worker
1131*9880d681SAndroid Build Coastguard Worker // Try to lower to a SET* instruction:
1132*9880d681SAndroid Build Coastguard Worker //
1133*9880d681SAndroid Build Coastguard Worker // SET* can match the following patterns:
1134*9880d681SAndroid Build Coastguard Worker //
1135*9880d681SAndroid Build Coastguard Worker // select_cc f32, f32, -1, 0, cc_supported
1136*9880d681SAndroid Build Coastguard Worker // select_cc f32, f32, 1.0f, 0.0f, cc_supported
1137*9880d681SAndroid Build Coastguard Worker // select_cc i32, i32, -1, 0, cc_supported
1138*9880d681SAndroid Build Coastguard Worker //
1139*9880d681SAndroid Build Coastguard Worker
1140*9880d681SAndroid Build Coastguard Worker // Move hardware True/False values to the correct operand.
1141*9880d681SAndroid Build Coastguard Worker ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get();
1142*9880d681SAndroid Build Coastguard Worker ISD::CondCode InverseCC =
1143*9880d681SAndroid Build Coastguard Worker ISD::getSetCCInverse(CCOpcode, CompareVT == MVT::i32);
1144*9880d681SAndroid Build Coastguard Worker if (isHWTrueValue(False) && isHWFalseValue(True)) {
1145*9880d681SAndroid Build Coastguard Worker if (isCondCodeLegal(InverseCC, CompareVT.getSimpleVT())) {
1146*9880d681SAndroid Build Coastguard Worker std::swap(False, True);
1147*9880d681SAndroid Build Coastguard Worker CC = DAG.getCondCode(InverseCC);
1148*9880d681SAndroid Build Coastguard Worker } else {
1149*9880d681SAndroid Build Coastguard Worker ISD::CondCode SwapInvCC = ISD::getSetCCSwappedOperands(InverseCC);
1150*9880d681SAndroid Build Coastguard Worker if (isCondCodeLegal(SwapInvCC, CompareVT.getSimpleVT())) {
1151*9880d681SAndroid Build Coastguard Worker std::swap(False, True);
1152*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1153*9880d681SAndroid Build Coastguard Worker CC = DAG.getCondCode(SwapInvCC);
1154*9880d681SAndroid Build Coastguard Worker }
1155*9880d681SAndroid Build Coastguard Worker }
1156*9880d681SAndroid Build Coastguard Worker }
1157*9880d681SAndroid Build Coastguard Worker
1158*9880d681SAndroid Build Coastguard Worker if (isHWTrueValue(True) && isHWFalseValue(False) &&
1159*9880d681SAndroid Build Coastguard Worker (CompareVT == VT || VT == MVT::i32)) {
1160*9880d681SAndroid Build Coastguard Worker // This can be matched by a SET* instruction.
1161*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::SELECT_CC, DL, VT, LHS, RHS, True, False, CC);
1162*9880d681SAndroid Build Coastguard Worker }
1163*9880d681SAndroid Build Coastguard Worker
1164*9880d681SAndroid Build Coastguard Worker // Try to lower to a CND* instruction:
1165*9880d681SAndroid Build Coastguard Worker //
1166*9880d681SAndroid Build Coastguard Worker // CND* can match the following patterns:
1167*9880d681SAndroid Build Coastguard Worker //
1168*9880d681SAndroid Build Coastguard Worker // select_cc f32, 0.0, f32, f32, cc_supported
1169*9880d681SAndroid Build Coastguard Worker // select_cc f32, 0.0, i32, i32, cc_supported
1170*9880d681SAndroid Build Coastguard Worker // select_cc i32, 0, f32, f32, cc_supported
1171*9880d681SAndroid Build Coastguard Worker // select_cc i32, 0, i32, i32, cc_supported
1172*9880d681SAndroid Build Coastguard Worker //
1173*9880d681SAndroid Build Coastguard Worker
1174*9880d681SAndroid Build Coastguard Worker // Try to move the zero value to the RHS
1175*9880d681SAndroid Build Coastguard Worker if (isZero(LHS)) {
1176*9880d681SAndroid Build Coastguard Worker ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get();
1177*9880d681SAndroid Build Coastguard Worker // Try swapping the operands
1178*9880d681SAndroid Build Coastguard Worker ISD::CondCode CCSwapped = ISD::getSetCCSwappedOperands(CCOpcode);
1179*9880d681SAndroid Build Coastguard Worker if (isCondCodeLegal(CCSwapped, CompareVT.getSimpleVT())) {
1180*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1181*9880d681SAndroid Build Coastguard Worker CC = DAG.getCondCode(CCSwapped);
1182*9880d681SAndroid Build Coastguard Worker } else {
1183*9880d681SAndroid Build Coastguard Worker // Try inverting the conditon and then swapping the operands
1184*9880d681SAndroid Build Coastguard Worker ISD::CondCode CCInv = ISD::getSetCCInverse(CCOpcode, CompareVT.isInteger());
1185*9880d681SAndroid Build Coastguard Worker CCSwapped = ISD::getSetCCSwappedOperands(CCInv);
1186*9880d681SAndroid Build Coastguard Worker if (isCondCodeLegal(CCSwapped, CompareVT.getSimpleVT())) {
1187*9880d681SAndroid Build Coastguard Worker std::swap(True, False);
1188*9880d681SAndroid Build Coastguard Worker std::swap(LHS, RHS);
1189*9880d681SAndroid Build Coastguard Worker CC = DAG.getCondCode(CCSwapped);
1190*9880d681SAndroid Build Coastguard Worker }
1191*9880d681SAndroid Build Coastguard Worker }
1192*9880d681SAndroid Build Coastguard Worker }
1193*9880d681SAndroid Build Coastguard Worker if (isZero(RHS)) {
1194*9880d681SAndroid Build Coastguard Worker SDValue Cond = LHS;
1195*9880d681SAndroid Build Coastguard Worker SDValue Zero = RHS;
1196*9880d681SAndroid Build Coastguard Worker ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get();
1197*9880d681SAndroid Build Coastguard Worker if (CompareVT != VT) {
1198*9880d681SAndroid Build Coastguard Worker // Bitcast True / False to the correct types. This will end up being
1199*9880d681SAndroid Build Coastguard Worker // a nop, but it allows us to define only a single pattern in the
1200*9880d681SAndroid Build Coastguard Worker // .TD files for each CND* instruction rather than having to have
1201*9880d681SAndroid Build Coastguard Worker // one pattern for integer True/False and one for fp True/False
1202*9880d681SAndroid Build Coastguard Worker True = DAG.getNode(ISD::BITCAST, DL, CompareVT, True);
1203*9880d681SAndroid Build Coastguard Worker False = DAG.getNode(ISD::BITCAST, DL, CompareVT, False);
1204*9880d681SAndroid Build Coastguard Worker }
1205*9880d681SAndroid Build Coastguard Worker
1206*9880d681SAndroid Build Coastguard Worker switch (CCOpcode) {
1207*9880d681SAndroid Build Coastguard Worker case ISD::SETONE:
1208*9880d681SAndroid Build Coastguard Worker case ISD::SETUNE:
1209*9880d681SAndroid Build Coastguard Worker case ISD::SETNE:
1210*9880d681SAndroid Build Coastguard Worker CCOpcode = ISD::getSetCCInverse(CCOpcode, CompareVT == MVT::i32);
1211*9880d681SAndroid Build Coastguard Worker Temp = True;
1212*9880d681SAndroid Build Coastguard Worker True = False;
1213*9880d681SAndroid Build Coastguard Worker False = Temp;
1214*9880d681SAndroid Build Coastguard Worker break;
1215*9880d681SAndroid Build Coastguard Worker default:
1216*9880d681SAndroid Build Coastguard Worker break;
1217*9880d681SAndroid Build Coastguard Worker }
1218*9880d681SAndroid Build Coastguard Worker SDValue SelectNode = DAG.getNode(ISD::SELECT_CC, DL, CompareVT,
1219*9880d681SAndroid Build Coastguard Worker Cond, Zero,
1220*9880d681SAndroid Build Coastguard Worker True, False,
1221*9880d681SAndroid Build Coastguard Worker DAG.getCondCode(CCOpcode));
1222*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, DL, VT, SelectNode);
1223*9880d681SAndroid Build Coastguard Worker }
1224*9880d681SAndroid Build Coastguard Worker
1225*9880d681SAndroid Build Coastguard Worker // If we make it this for it means we have no native instructions to handle
1226*9880d681SAndroid Build Coastguard Worker // this SELECT_CC, so we must lower it.
1227*9880d681SAndroid Build Coastguard Worker SDValue HWTrue, HWFalse;
1228*9880d681SAndroid Build Coastguard Worker
1229*9880d681SAndroid Build Coastguard Worker if (CompareVT == MVT::f32) {
1230*9880d681SAndroid Build Coastguard Worker HWTrue = DAG.getConstantFP(1.0f, DL, CompareVT);
1231*9880d681SAndroid Build Coastguard Worker HWFalse = DAG.getConstantFP(0.0f, DL, CompareVT);
1232*9880d681SAndroid Build Coastguard Worker } else if (CompareVT == MVT::i32) {
1233*9880d681SAndroid Build Coastguard Worker HWTrue = DAG.getConstant(-1, DL, CompareVT);
1234*9880d681SAndroid Build Coastguard Worker HWFalse = DAG.getConstant(0, DL, CompareVT);
1235*9880d681SAndroid Build Coastguard Worker }
1236*9880d681SAndroid Build Coastguard Worker else {
1237*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unhandled value type in LowerSELECT_CC");
1238*9880d681SAndroid Build Coastguard Worker }
1239*9880d681SAndroid Build Coastguard Worker
1240*9880d681SAndroid Build Coastguard Worker // Lower this unsupported SELECT_CC into a combination of two supported
1241*9880d681SAndroid Build Coastguard Worker // SELECT_CC operations.
1242*9880d681SAndroid Build Coastguard Worker SDValue Cond = DAG.getNode(ISD::SELECT_CC, DL, CompareVT, LHS, RHS, HWTrue, HWFalse, CC);
1243*9880d681SAndroid Build Coastguard Worker
1244*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::SELECT_CC, DL, VT,
1245*9880d681SAndroid Build Coastguard Worker Cond, HWFalse,
1246*9880d681SAndroid Build Coastguard Worker True, False,
1247*9880d681SAndroid Build Coastguard Worker DAG.getCondCode(ISD::SETNE));
1248*9880d681SAndroid Build Coastguard Worker }
1249*9880d681SAndroid Build Coastguard Worker
1250*9880d681SAndroid Build Coastguard Worker /// LLVM generates byte-addressed pointers. For indirect addressing, we need to
1251*9880d681SAndroid Build Coastguard Worker /// convert these pointers to a register index. Each register holds
1252*9880d681SAndroid Build Coastguard Worker /// 16 bytes, (4 x 32bit sub-register), but we need to take into account the
1253*9880d681SAndroid Build Coastguard Worker /// \p StackWidth, which tells us how many of the 4 sub-registrers will be used
1254*9880d681SAndroid Build Coastguard Worker /// for indirect addressing.
stackPtrToRegIndex(SDValue Ptr,unsigned StackWidth,SelectionDAG & DAG) const1255*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::stackPtrToRegIndex(SDValue Ptr,
1256*9880d681SAndroid Build Coastguard Worker unsigned StackWidth,
1257*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1258*9880d681SAndroid Build Coastguard Worker unsigned SRLPad;
1259*9880d681SAndroid Build Coastguard Worker switch(StackWidth) {
1260*9880d681SAndroid Build Coastguard Worker case 1:
1261*9880d681SAndroid Build Coastguard Worker SRLPad = 2;
1262*9880d681SAndroid Build Coastguard Worker break;
1263*9880d681SAndroid Build Coastguard Worker case 2:
1264*9880d681SAndroid Build Coastguard Worker SRLPad = 3;
1265*9880d681SAndroid Build Coastguard Worker break;
1266*9880d681SAndroid Build Coastguard Worker case 4:
1267*9880d681SAndroid Build Coastguard Worker SRLPad = 4;
1268*9880d681SAndroid Build Coastguard Worker break;
1269*9880d681SAndroid Build Coastguard Worker default: llvm_unreachable("Invalid stack width");
1270*9880d681SAndroid Build Coastguard Worker }
1271*9880d681SAndroid Build Coastguard Worker
1272*9880d681SAndroid Build Coastguard Worker SDLoc DL(Ptr);
1273*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::SRL, DL, Ptr.getValueType(), Ptr,
1274*9880d681SAndroid Build Coastguard Worker DAG.getConstant(SRLPad, DL, MVT::i32));
1275*9880d681SAndroid Build Coastguard Worker }
1276*9880d681SAndroid Build Coastguard Worker
getStackAddress(unsigned StackWidth,unsigned ElemIdx,unsigned & Channel,unsigned & PtrIncr) const1277*9880d681SAndroid Build Coastguard Worker void R600TargetLowering::getStackAddress(unsigned StackWidth,
1278*9880d681SAndroid Build Coastguard Worker unsigned ElemIdx,
1279*9880d681SAndroid Build Coastguard Worker unsigned &Channel,
1280*9880d681SAndroid Build Coastguard Worker unsigned &PtrIncr) const {
1281*9880d681SAndroid Build Coastguard Worker switch (StackWidth) {
1282*9880d681SAndroid Build Coastguard Worker default:
1283*9880d681SAndroid Build Coastguard Worker case 1:
1284*9880d681SAndroid Build Coastguard Worker Channel = 0;
1285*9880d681SAndroid Build Coastguard Worker if (ElemIdx > 0) {
1286*9880d681SAndroid Build Coastguard Worker PtrIncr = 1;
1287*9880d681SAndroid Build Coastguard Worker } else {
1288*9880d681SAndroid Build Coastguard Worker PtrIncr = 0;
1289*9880d681SAndroid Build Coastguard Worker }
1290*9880d681SAndroid Build Coastguard Worker break;
1291*9880d681SAndroid Build Coastguard Worker case 2:
1292*9880d681SAndroid Build Coastguard Worker Channel = ElemIdx % 2;
1293*9880d681SAndroid Build Coastguard Worker if (ElemIdx == 2) {
1294*9880d681SAndroid Build Coastguard Worker PtrIncr = 1;
1295*9880d681SAndroid Build Coastguard Worker } else {
1296*9880d681SAndroid Build Coastguard Worker PtrIncr = 0;
1297*9880d681SAndroid Build Coastguard Worker }
1298*9880d681SAndroid Build Coastguard Worker break;
1299*9880d681SAndroid Build Coastguard Worker case 4:
1300*9880d681SAndroid Build Coastguard Worker Channel = ElemIdx;
1301*9880d681SAndroid Build Coastguard Worker PtrIncr = 0;
1302*9880d681SAndroid Build Coastguard Worker break;
1303*9880d681SAndroid Build Coastguard Worker }
1304*9880d681SAndroid Build Coastguard Worker }
1305*9880d681SAndroid Build Coastguard Worker
lowerPrivateTruncStore(StoreSDNode * Store,SelectionDAG & DAG) const1306*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::lowerPrivateTruncStore(StoreSDNode *Store,
1307*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1308*9880d681SAndroid Build Coastguard Worker SDLoc DL(Store);
1309*9880d681SAndroid Build Coastguard Worker
1310*9880d681SAndroid Build Coastguard Worker unsigned Mask = 0;
1311*9880d681SAndroid Build Coastguard Worker if (Store->getMemoryVT() == MVT::i8) {
1312*9880d681SAndroid Build Coastguard Worker Mask = 0xff;
1313*9880d681SAndroid Build Coastguard Worker } else if (Store->getMemoryVT() == MVT::i16) {
1314*9880d681SAndroid Build Coastguard Worker Mask = 0xffff;
1315*9880d681SAndroid Build Coastguard Worker }
1316*9880d681SAndroid Build Coastguard Worker
1317*9880d681SAndroid Build Coastguard Worker SDValue Chain = Store->getChain();
1318*9880d681SAndroid Build Coastguard Worker SDValue BasePtr = Store->getBasePtr();
1319*9880d681SAndroid Build Coastguard Worker EVT MemVT = Store->getMemoryVT();
1320*9880d681SAndroid Build Coastguard Worker
1321*9880d681SAndroid Build Coastguard Worker SDValue Ptr = DAG.getNode(ISD::SRL, DL, MVT::i32, BasePtr,
1322*9880d681SAndroid Build Coastguard Worker DAG.getConstant(2, DL, MVT::i32));
1323*9880d681SAndroid Build Coastguard Worker SDValue Dst = DAG.getNode(AMDGPUISD::REGISTER_LOAD, DL, MVT::i32,
1324*9880d681SAndroid Build Coastguard Worker Chain, Ptr,
1325*9880d681SAndroid Build Coastguard Worker DAG.getTargetConstant(0, DL, MVT::i32));
1326*9880d681SAndroid Build Coastguard Worker
1327*9880d681SAndroid Build Coastguard Worker SDValue ByteIdx = DAG.getNode(ISD::AND, DL, MVT::i32, BasePtr,
1328*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0x3, DL, MVT::i32));
1329*9880d681SAndroid Build Coastguard Worker
1330*9880d681SAndroid Build Coastguard Worker SDValue ShiftAmt = DAG.getNode(ISD::SHL, DL, MVT::i32, ByteIdx,
1331*9880d681SAndroid Build Coastguard Worker DAG.getConstant(3, DL, MVT::i32));
1332*9880d681SAndroid Build Coastguard Worker
1333*9880d681SAndroid Build Coastguard Worker SDValue SExtValue = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i32,
1334*9880d681SAndroid Build Coastguard Worker Store->getValue());
1335*9880d681SAndroid Build Coastguard Worker
1336*9880d681SAndroid Build Coastguard Worker SDValue MaskedValue = DAG.getZeroExtendInReg(SExtValue, DL, MemVT);
1337*9880d681SAndroid Build Coastguard Worker
1338*9880d681SAndroid Build Coastguard Worker SDValue ShiftedValue = DAG.getNode(ISD::SHL, DL, MVT::i32,
1339*9880d681SAndroid Build Coastguard Worker MaskedValue, ShiftAmt);
1340*9880d681SAndroid Build Coastguard Worker
1341*9880d681SAndroid Build Coastguard Worker SDValue DstMask = DAG.getNode(ISD::SHL, DL, MVT::i32,
1342*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Mask, DL, MVT::i32),
1343*9880d681SAndroid Build Coastguard Worker ShiftAmt);
1344*9880d681SAndroid Build Coastguard Worker DstMask = DAG.getNode(ISD::XOR, DL, MVT::i32, DstMask,
1345*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0xffffffff, DL, MVT::i32));
1346*9880d681SAndroid Build Coastguard Worker Dst = DAG.getNode(ISD::AND, DL, MVT::i32, Dst, DstMask);
1347*9880d681SAndroid Build Coastguard Worker
1348*9880d681SAndroid Build Coastguard Worker SDValue Value = DAG.getNode(ISD::OR, DL, MVT::i32, Dst, ShiftedValue);
1349*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::REGISTER_STORE, DL, MVT::Other,
1350*9880d681SAndroid Build Coastguard Worker Chain, Value, Ptr,
1351*9880d681SAndroid Build Coastguard Worker DAG.getTargetConstant(0, DL, MVT::i32));
1352*9880d681SAndroid Build Coastguard Worker }
1353*9880d681SAndroid Build Coastguard Worker
LowerSTORE(SDValue Op,SelectionDAG & DAG) const1354*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerSTORE(SDValue Op, SelectionDAG &DAG) const {
1355*9880d681SAndroid Build Coastguard Worker if (SDValue Result = AMDGPUTargetLowering::MergeVectorStore(Op, DAG))
1356*9880d681SAndroid Build Coastguard Worker return Result;
1357*9880d681SAndroid Build Coastguard Worker
1358*9880d681SAndroid Build Coastguard Worker StoreSDNode *StoreNode = cast<StoreSDNode>(Op);
1359*9880d681SAndroid Build Coastguard Worker unsigned AS = StoreNode->getAddressSpace();
1360*9880d681SAndroid Build Coastguard Worker SDValue Value = StoreNode->getValue();
1361*9880d681SAndroid Build Coastguard Worker EVT ValueVT = Value.getValueType();
1362*9880d681SAndroid Build Coastguard Worker
1363*9880d681SAndroid Build Coastguard Worker if ((AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::PRIVATE_ADDRESS) &&
1364*9880d681SAndroid Build Coastguard Worker ValueVT.isVector()) {
1365*9880d681SAndroid Build Coastguard Worker return SplitVectorStore(Op, DAG);
1366*9880d681SAndroid Build Coastguard Worker }
1367*9880d681SAndroid Build Coastguard Worker
1368*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1369*9880d681SAndroid Build Coastguard Worker SDValue Chain = StoreNode->getChain();
1370*9880d681SAndroid Build Coastguard Worker SDValue Ptr = StoreNode->getBasePtr();
1371*9880d681SAndroid Build Coastguard Worker
1372*9880d681SAndroid Build Coastguard Worker if (AS == AMDGPUAS::GLOBAL_ADDRESS) {
1373*9880d681SAndroid Build Coastguard Worker if (StoreNode->isTruncatingStore()) {
1374*9880d681SAndroid Build Coastguard Worker EVT VT = Value.getValueType();
1375*9880d681SAndroid Build Coastguard Worker assert(VT.bitsLE(MVT::i32));
1376*9880d681SAndroid Build Coastguard Worker EVT MemVT = StoreNode->getMemoryVT();
1377*9880d681SAndroid Build Coastguard Worker SDValue MaskConstant;
1378*9880d681SAndroid Build Coastguard Worker if (MemVT == MVT::i8) {
1379*9880d681SAndroid Build Coastguard Worker MaskConstant = DAG.getConstant(0xFF, DL, MVT::i32);
1380*9880d681SAndroid Build Coastguard Worker } else {
1381*9880d681SAndroid Build Coastguard Worker assert(MemVT == MVT::i16);
1382*9880d681SAndroid Build Coastguard Worker MaskConstant = DAG.getConstant(0xFFFF, DL, MVT::i32);
1383*9880d681SAndroid Build Coastguard Worker }
1384*9880d681SAndroid Build Coastguard Worker SDValue DWordAddr = DAG.getNode(ISD::SRL, DL, VT, Ptr,
1385*9880d681SAndroid Build Coastguard Worker DAG.getConstant(2, DL, MVT::i32));
1386*9880d681SAndroid Build Coastguard Worker SDValue ByteIndex = DAG.getNode(ISD::AND, DL, Ptr.getValueType(), Ptr,
1387*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0x00000003, DL, VT));
1388*9880d681SAndroid Build Coastguard Worker SDValue TruncValue = DAG.getNode(ISD::AND, DL, VT, Value, MaskConstant);
1389*9880d681SAndroid Build Coastguard Worker SDValue Shift = DAG.getNode(ISD::SHL, DL, VT, ByteIndex,
1390*9880d681SAndroid Build Coastguard Worker DAG.getConstant(3, DL, VT));
1391*9880d681SAndroid Build Coastguard Worker SDValue ShiftedValue = DAG.getNode(ISD::SHL, DL, VT, TruncValue, Shift);
1392*9880d681SAndroid Build Coastguard Worker SDValue Mask = DAG.getNode(ISD::SHL, DL, VT, MaskConstant, Shift);
1393*9880d681SAndroid Build Coastguard Worker // XXX: If we add a 64-bit ZW register class, then we could use a 2 x i32
1394*9880d681SAndroid Build Coastguard Worker // vector instead.
1395*9880d681SAndroid Build Coastguard Worker SDValue Src[4] = {
1396*9880d681SAndroid Build Coastguard Worker ShiftedValue,
1397*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32),
1398*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32),
1399*9880d681SAndroid Build Coastguard Worker Mask
1400*9880d681SAndroid Build Coastguard Worker };
1401*9880d681SAndroid Build Coastguard Worker SDValue Input = DAG.getBuildVector(MVT::v4i32, DL, Src);
1402*9880d681SAndroid Build Coastguard Worker SDValue Args[3] = { Chain, Input, DWordAddr };
1403*9880d681SAndroid Build Coastguard Worker return DAG.getMemIntrinsicNode(AMDGPUISD::STORE_MSKOR, DL,
1404*9880d681SAndroid Build Coastguard Worker Op->getVTList(), Args, MemVT,
1405*9880d681SAndroid Build Coastguard Worker StoreNode->getMemOperand());
1406*9880d681SAndroid Build Coastguard Worker } else if (Ptr->getOpcode() != AMDGPUISD::DWORDADDR &&
1407*9880d681SAndroid Build Coastguard Worker ValueVT.bitsGE(MVT::i32)) {
1408*9880d681SAndroid Build Coastguard Worker // Convert pointer from byte address to dword address.
1409*9880d681SAndroid Build Coastguard Worker Ptr = DAG.getNode(AMDGPUISD::DWORDADDR, DL, Ptr.getValueType(),
1410*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::SRL, DL, Ptr.getValueType(),
1411*9880d681SAndroid Build Coastguard Worker Ptr, DAG.getConstant(2, DL, MVT::i32)));
1412*9880d681SAndroid Build Coastguard Worker
1413*9880d681SAndroid Build Coastguard Worker if (StoreNode->isTruncatingStore() || StoreNode->isIndexed()) {
1414*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Truncated and indexed stores not supported yet");
1415*9880d681SAndroid Build Coastguard Worker } else {
1416*9880d681SAndroid Build Coastguard Worker Chain = DAG.getStore(Chain, DL, Value, Ptr, StoreNode->getMemOperand());
1417*9880d681SAndroid Build Coastguard Worker }
1418*9880d681SAndroid Build Coastguard Worker return Chain;
1419*9880d681SAndroid Build Coastguard Worker }
1420*9880d681SAndroid Build Coastguard Worker }
1421*9880d681SAndroid Build Coastguard Worker
1422*9880d681SAndroid Build Coastguard Worker if (AS != AMDGPUAS::PRIVATE_ADDRESS)
1423*9880d681SAndroid Build Coastguard Worker return SDValue();
1424*9880d681SAndroid Build Coastguard Worker
1425*9880d681SAndroid Build Coastguard Worker EVT MemVT = StoreNode->getMemoryVT();
1426*9880d681SAndroid Build Coastguard Worker if (MemVT.bitsLT(MVT::i32))
1427*9880d681SAndroid Build Coastguard Worker return lowerPrivateTruncStore(StoreNode, DAG);
1428*9880d681SAndroid Build Coastguard Worker
1429*9880d681SAndroid Build Coastguard Worker // Lowering for indirect addressing
1430*9880d681SAndroid Build Coastguard Worker const MachineFunction &MF = DAG.getMachineFunction();
1431*9880d681SAndroid Build Coastguard Worker const R600FrameLowering *TFL = getSubtarget()->getFrameLowering();
1432*9880d681SAndroid Build Coastguard Worker unsigned StackWidth = TFL->getStackWidth(MF);
1433*9880d681SAndroid Build Coastguard Worker
1434*9880d681SAndroid Build Coastguard Worker Ptr = stackPtrToRegIndex(Ptr, StackWidth, DAG);
1435*9880d681SAndroid Build Coastguard Worker
1436*9880d681SAndroid Build Coastguard Worker if (ValueVT.isVector()) {
1437*9880d681SAndroid Build Coastguard Worker unsigned NumElemVT = ValueVT.getVectorNumElements();
1438*9880d681SAndroid Build Coastguard Worker EVT ElemVT = ValueVT.getVectorElementType();
1439*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 4> Stores(NumElemVT);
1440*9880d681SAndroid Build Coastguard Worker
1441*9880d681SAndroid Build Coastguard Worker assert(NumElemVT >= StackWidth && "Stack width cannot be greater than "
1442*9880d681SAndroid Build Coastguard Worker "vector width in load");
1443*9880d681SAndroid Build Coastguard Worker
1444*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumElemVT; ++i) {
1445*9880d681SAndroid Build Coastguard Worker unsigned Channel, PtrIncr;
1446*9880d681SAndroid Build Coastguard Worker getStackAddress(StackWidth, i, Channel, PtrIncr);
1447*9880d681SAndroid Build Coastguard Worker Ptr = DAG.getNode(ISD::ADD, DL, MVT::i32, Ptr,
1448*9880d681SAndroid Build Coastguard Worker DAG.getConstant(PtrIncr, DL, MVT::i32));
1449*9880d681SAndroid Build Coastguard Worker SDValue Elem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ElemVT,
1450*9880d681SAndroid Build Coastguard Worker Value, DAG.getConstant(i, DL, MVT::i32));
1451*9880d681SAndroid Build Coastguard Worker
1452*9880d681SAndroid Build Coastguard Worker Stores[i] = DAG.getNode(AMDGPUISD::REGISTER_STORE, DL, MVT::Other,
1453*9880d681SAndroid Build Coastguard Worker Chain, Elem, Ptr,
1454*9880d681SAndroid Build Coastguard Worker DAG.getTargetConstant(Channel, DL, MVT::i32));
1455*9880d681SAndroid Build Coastguard Worker }
1456*9880d681SAndroid Build Coastguard Worker Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Stores);
1457*9880d681SAndroid Build Coastguard Worker } else {
1458*9880d681SAndroid Build Coastguard Worker if (ValueVT == MVT::i8) {
1459*9880d681SAndroid Build Coastguard Worker Value = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, Value);
1460*9880d681SAndroid Build Coastguard Worker }
1461*9880d681SAndroid Build Coastguard Worker Chain = DAG.getNode(AMDGPUISD::REGISTER_STORE, DL, MVT::Other, Chain, Value, Ptr,
1462*9880d681SAndroid Build Coastguard Worker DAG.getTargetConstant(0, DL, MVT::i32)); // Channel
1463*9880d681SAndroid Build Coastguard Worker }
1464*9880d681SAndroid Build Coastguard Worker
1465*9880d681SAndroid Build Coastguard Worker return Chain;
1466*9880d681SAndroid Build Coastguard Worker }
1467*9880d681SAndroid Build Coastguard Worker
1468*9880d681SAndroid Build Coastguard Worker // return (512 + (kc_bank << 12)
1469*9880d681SAndroid Build Coastguard Worker static int
ConstantAddressBlock(unsigned AddressSpace)1470*9880d681SAndroid Build Coastguard Worker ConstantAddressBlock(unsigned AddressSpace) {
1471*9880d681SAndroid Build Coastguard Worker switch (AddressSpace) {
1472*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_0:
1473*9880d681SAndroid Build Coastguard Worker return 512;
1474*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_1:
1475*9880d681SAndroid Build Coastguard Worker return 512 + 4096;
1476*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_2:
1477*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 2;
1478*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_3:
1479*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 3;
1480*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_4:
1481*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 4;
1482*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_5:
1483*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 5;
1484*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_6:
1485*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 6;
1486*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_7:
1487*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 7;
1488*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_8:
1489*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 8;
1490*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_9:
1491*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 9;
1492*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_10:
1493*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 10;
1494*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_11:
1495*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 11;
1496*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_12:
1497*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 12;
1498*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_13:
1499*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 13;
1500*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_14:
1501*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 14;
1502*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_BUFFER_15:
1503*9880d681SAndroid Build Coastguard Worker return 512 + 4096 * 15;
1504*9880d681SAndroid Build Coastguard Worker default:
1505*9880d681SAndroid Build Coastguard Worker return -1;
1506*9880d681SAndroid Build Coastguard Worker }
1507*9880d681SAndroid Build Coastguard Worker }
1508*9880d681SAndroid Build Coastguard Worker
lowerPrivateExtLoad(SDValue Op,SelectionDAG & DAG) const1509*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::lowerPrivateExtLoad(SDValue Op,
1510*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1511*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1512*9880d681SAndroid Build Coastguard Worker LoadSDNode *Load = cast<LoadSDNode>(Op);
1513*9880d681SAndroid Build Coastguard Worker ISD::LoadExtType ExtType = Load->getExtensionType();
1514*9880d681SAndroid Build Coastguard Worker EVT MemVT = Load->getMemoryVT();
1515*9880d681SAndroid Build Coastguard Worker
1516*9880d681SAndroid Build Coastguard Worker // <SI && AS=PRIVATE && EXTLOAD && size < 32bit,
1517*9880d681SAndroid Build Coastguard Worker // register (2-)byte extract.
1518*9880d681SAndroid Build Coastguard Worker
1519*9880d681SAndroid Build Coastguard Worker // Get Register holding the target.
1520*9880d681SAndroid Build Coastguard Worker SDValue Ptr = DAG.getNode(ISD::SRL, DL, MVT::i32, Load->getBasePtr(),
1521*9880d681SAndroid Build Coastguard Worker DAG.getConstant(2, DL, MVT::i32));
1522*9880d681SAndroid Build Coastguard Worker // Load the Register.
1523*9880d681SAndroid Build Coastguard Worker SDValue Ret = DAG.getNode(AMDGPUISD::REGISTER_LOAD, DL, Op.getValueType(),
1524*9880d681SAndroid Build Coastguard Worker Load->getChain(),
1525*9880d681SAndroid Build Coastguard Worker Ptr,
1526*9880d681SAndroid Build Coastguard Worker DAG.getTargetConstant(0, DL, MVT::i32),
1527*9880d681SAndroid Build Coastguard Worker Op.getOperand(2));
1528*9880d681SAndroid Build Coastguard Worker
1529*9880d681SAndroid Build Coastguard Worker // Get offset within the register.
1530*9880d681SAndroid Build Coastguard Worker SDValue ByteIdx = DAG.getNode(ISD::AND, DL, MVT::i32,
1531*9880d681SAndroid Build Coastguard Worker Load->getBasePtr(),
1532*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0x3, DL, MVT::i32));
1533*9880d681SAndroid Build Coastguard Worker
1534*9880d681SAndroid Build Coastguard Worker // Bit offset of target byte (byteIdx * 8).
1535*9880d681SAndroid Build Coastguard Worker SDValue ShiftAmt = DAG.getNode(ISD::SHL, DL, MVT::i32, ByteIdx,
1536*9880d681SAndroid Build Coastguard Worker DAG.getConstant(3, DL, MVT::i32));
1537*9880d681SAndroid Build Coastguard Worker
1538*9880d681SAndroid Build Coastguard Worker // Shift to the right.
1539*9880d681SAndroid Build Coastguard Worker Ret = DAG.getNode(ISD::SRL, DL, MVT::i32, Ret, ShiftAmt);
1540*9880d681SAndroid Build Coastguard Worker
1541*9880d681SAndroid Build Coastguard Worker // Eliminate the upper bits by setting them to ...
1542*9880d681SAndroid Build Coastguard Worker EVT MemEltVT = MemVT.getScalarType();
1543*9880d681SAndroid Build Coastguard Worker
1544*9880d681SAndroid Build Coastguard Worker // ... ones.
1545*9880d681SAndroid Build Coastguard Worker if (ExtType == ISD::SEXTLOAD) {
1546*9880d681SAndroid Build Coastguard Worker SDValue MemEltVTNode = DAG.getValueType(MemEltVT);
1547*9880d681SAndroid Build Coastguard Worker
1548*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = {
1549*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i32, Ret, MemEltVTNode),
1550*9880d681SAndroid Build Coastguard Worker Load->getChain()
1551*9880d681SAndroid Build Coastguard Worker };
1552*9880d681SAndroid Build Coastguard Worker
1553*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, DL);
1554*9880d681SAndroid Build Coastguard Worker }
1555*9880d681SAndroid Build Coastguard Worker
1556*9880d681SAndroid Build Coastguard Worker // ... or zeros.
1557*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = {
1558*9880d681SAndroid Build Coastguard Worker DAG.getZeroExtendInReg(Ret, DL, MemEltVT),
1559*9880d681SAndroid Build Coastguard Worker Load->getChain()
1560*9880d681SAndroid Build Coastguard Worker };
1561*9880d681SAndroid Build Coastguard Worker
1562*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, DL);
1563*9880d681SAndroid Build Coastguard Worker }
1564*9880d681SAndroid Build Coastguard Worker
LowerLOAD(SDValue Op,SelectionDAG & DAG) const1565*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerLOAD(SDValue Op, SelectionDAG &DAG) const {
1566*9880d681SAndroid Build Coastguard Worker LoadSDNode *LoadNode = cast<LoadSDNode>(Op);
1567*9880d681SAndroid Build Coastguard Worker unsigned AS = LoadNode->getAddressSpace();
1568*9880d681SAndroid Build Coastguard Worker EVT MemVT = LoadNode->getMemoryVT();
1569*9880d681SAndroid Build Coastguard Worker ISD::LoadExtType ExtType = LoadNode->getExtensionType();
1570*9880d681SAndroid Build Coastguard Worker
1571*9880d681SAndroid Build Coastguard Worker if (AS == AMDGPUAS::PRIVATE_ADDRESS &&
1572*9880d681SAndroid Build Coastguard Worker ExtType != ISD::NON_EXTLOAD && MemVT.bitsLT(MVT::i32)) {
1573*9880d681SAndroid Build Coastguard Worker return lowerPrivateExtLoad(Op, DAG);
1574*9880d681SAndroid Build Coastguard Worker }
1575*9880d681SAndroid Build Coastguard Worker
1576*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1577*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1578*9880d681SAndroid Build Coastguard Worker SDValue Chain = LoadNode->getChain();
1579*9880d681SAndroid Build Coastguard Worker SDValue Ptr = LoadNode->getBasePtr();
1580*9880d681SAndroid Build Coastguard Worker
1581*9880d681SAndroid Build Coastguard Worker if (LoadNode->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS && VT.isVector()) {
1582*9880d681SAndroid Build Coastguard Worker SDValue MergedValues[2] = {
1583*9880d681SAndroid Build Coastguard Worker scalarizeVectorLoad(LoadNode, DAG),
1584*9880d681SAndroid Build Coastguard Worker Chain
1585*9880d681SAndroid Build Coastguard Worker };
1586*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(MergedValues, DL);
1587*9880d681SAndroid Build Coastguard Worker }
1588*9880d681SAndroid Build Coastguard Worker
1589*9880d681SAndroid Build Coastguard Worker int ConstantBlock = ConstantAddressBlock(LoadNode->getAddressSpace());
1590*9880d681SAndroid Build Coastguard Worker if (ConstantBlock > -1 &&
1591*9880d681SAndroid Build Coastguard Worker ((LoadNode->getExtensionType() == ISD::NON_EXTLOAD) ||
1592*9880d681SAndroid Build Coastguard Worker (LoadNode->getExtensionType() == ISD::ZEXTLOAD))) {
1593*9880d681SAndroid Build Coastguard Worker SDValue Result;
1594*9880d681SAndroid Build Coastguard Worker if (isa<ConstantExpr>(LoadNode->getMemOperand()->getValue()) ||
1595*9880d681SAndroid Build Coastguard Worker isa<Constant>(LoadNode->getMemOperand()->getValue()) ||
1596*9880d681SAndroid Build Coastguard Worker isa<ConstantSDNode>(Ptr)) {
1597*9880d681SAndroid Build Coastguard Worker SDValue Slots[4];
1598*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++) {
1599*9880d681SAndroid Build Coastguard Worker // We want Const position encoded with the following formula :
1600*9880d681SAndroid Build Coastguard Worker // (((512 + (kc_bank << 12) + const_index) << 2) + chan)
1601*9880d681SAndroid Build Coastguard Worker // const_index is Ptr computed by llvm using an alignment of 16.
1602*9880d681SAndroid Build Coastguard Worker // Thus we add (((512 + (kc_bank << 12)) + chan ) * 4 here and
1603*9880d681SAndroid Build Coastguard Worker // then div by 4 at the ISel step
1604*9880d681SAndroid Build Coastguard Worker SDValue NewPtr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr,
1605*9880d681SAndroid Build Coastguard Worker DAG.getConstant(4 * i + ConstantBlock * 16, DL, MVT::i32));
1606*9880d681SAndroid Build Coastguard Worker Slots[i] = DAG.getNode(AMDGPUISD::CONST_ADDRESS, DL, MVT::i32, NewPtr);
1607*9880d681SAndroid Build Coastguard Worker }
1608*9880d681SAndroid Build Coastguard Worker EVT NewVT = MVT::v4i32;
1609*9880d681SAndroid Build Coastguard Worker unsigned NumElements = 4;
1610*9880d681SAndroid Build Coastguard Worker if (VT.isVector()) {
1611*9880d681SAndroid Build Coastguard Worker NewVT = VT;
1612*9880d681SAndroid Build Coastguard Worker NumElements = VT.getVectorNumElements();
1613*9880d681SAndroid Build Coastguard Worker }
1614*9880d681SAndroid Build Coastguard Worker Result = DAG.getBuildVector(NewVT, DL, makeArrayRef(Slots, NumElements));
1615*9880d681SAndroid Build Coastguard Worker } else {
1616*9880d681SAndroid Build Coastguard Worker // non-constant ptr can't be folded, keeps it as a v4f32 load
1617*9880d681SAndroid Build Coastguard Worker Result = DAG.getNode(AMDGPUISD::CONST_ADDRESS, DL, MVT::v4i32,
1618*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::SRL, DL, MVT::i32, Ptr,
1619*9880d681SAndroid Build Coastguard Worker DAG.getConstant(4, DL, MVT::i32)),
1620*9880d681SAndroid Build Coastguard Worker DAG.getConstant(LoadNode->getAddressSpace() -
1621*9880d681SAndroid Build Coastguard Worker AMDGPUAS::CONSTANT_BUFFER_0, DL, MVT::i32)
1622*9880d681SAndroid Build Coastguard Worker );
1623*9880d681SAndroid Build Coastguard Worker }
1624*9880d681SAndroid Build Coastguard Worker
1625*9880d681SAndroid Build Coastguard Worker if (!VT.isVector()) {
1626*9880d681SAndroid Build Coastguard Worker Result = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, MVT::i32, Result,
1627*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, MVT::i32));
1628*9880d681SAndroid Build Coastguard Worker }
1629*9880d681SAndroid Build Coastguard Worker
1630*9880d681SAndroid Build Coastguard Worker SDValue MergedValues[2] = {
1631*9880d681SAndroid Build Coastguard Worker Result,
1632*9880d681SAndroid Build Coastguard Worker Chain
1633*9880d681SAndroid Build Coastguard Worker };
1634*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(MergedValues, DL);
1635*9880d681SAndroid Build Coastguard Worker }
1636*9880d681SAndroid Build Coastguard Worker
1637*9880d681SAndroid Build Coastguard Worker SDValue LoweredLoad;
1638*9880d681SAndroid Build Coastguard Worker
1639*9880d681SAndroid Build Coastguard Worker // For most operations returning SDValue() will result in the node being
1640*9880d681SAndroid Build Coastguard Worker // expanded by the DAG Legalizer. This is not the case for ISD::LOAD, so we
1641*9880d681SAndroid Build Coastguard Worker // need to manually expand loads that may be legal in some address spaces and
1642*9880d681SAndroid Build Coastguard Worker // illegal in others. SEXT loads from CONSTANT_BUFFER_0 are supported for
1643*9880d681SAndroid Build Coastguard Worker // compute shaders, since the data is sign extended when it is uploaded to the
1644*9880d681SAndroid Build Coastguard Worker // buffer. However SEXT loads from other address spaces are not supported, so
1645*9880d681SAndroid Build Coastguard Worker // we need to expand them here.
1646*9880d681SAndroid Build Coastguard Worker if (LoadNode->getExtensionType() == ISD::SEXTLOAD) {
1647*9880d681SAndroid Build Coastguard Worker EVT MemVT = LoadNode->getMemoryVT();
1648*9880d681SAndroid Build Coastguard Worker assert(!MemVT.isVector() && (MemVT == MVT::i16 || MemVT == MVT::i8));
1649*9880d681SAndroid Build Coastguard Worker SDValue NewLoad = DAG.getExtLoad(ISD::EXTLOAD, DL, VT, Chain, Ptr,
1650*9880d681SAndroid Build Coastguard Worker LoadNode->getPointerInfo(), MemVT,
1651*9880d681SAndroid Build Coastguard Worker LoadNode->isVolatile(),
1652*9880d681SAndroid Build Coastguard Worker LoadNode->isNonTemporal(),
1653*9880d681SAndroid Build Coastguard Worker LoadNode->isInvariant(),
1654*9880d681SAndroid Build Coastguard Worker LoadNode->getAlignment());
1655*9880d681SAndroid Build Coastguard Worker SDValue Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, NewLoad,
1656*9880d681SAndroid Build Coastguard Worker DAG.getValueType(MemVT));
1657*9880d681SAndroid Build Coastguard Worker
1658*9880d681SAndroid Build Coastguard Worker SDValue MergedValues[2] = { Res, Chain };
1659*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(MergedValues, DL);
1660*9880d681SAndroid Build Coastguard Worker }
1661*9880d681SAndroid Build Coastguard Worker
1662*9880d681SAndroid Build Coastguard Worker if (LoadNode->getAddressSpace() != AMDGPUAS::PRIVATE_ADDRESS) {
1663*9880d681SAndroid Build Coastguard Worker return SDValue();
1664*9880d681SAndroid Build Coastguard Worker }
1665*9880d681SAndroid Build Coastguard Worker
1666*9880d681SAndroid Build Coastguard Worker // Lowering for indirect addressing
1667*9880d681SAndroid Build Coastguard Worker const MachineFunction &MF = DAG.getMachineFunction();
1668*9880d681SAndroid Build Coastguard Worker const R600FrameLowering *TFL = getSubtarget()->getFrameLowering();
1669*9880d681SAndroid Build Coastguard Worker unsigned StackWidth = TFL->getStackWidth(MF);
1670*9880d681SAndroid Build Coastguard Worker
1671*9880d681SAndroid Build Coastguard Worker Ptr = stackPtrToRegIndex(Ptr, StackWidth, DAG);
1672*9880d681SAndroid Build Coastguard Worker
1673*9880d681SAndroid Build Coastguard Worker if (VT.isVector()) {
1674*9880d681SAndroid Build Coastguard Worker unsigned NumElemVT = VT.getVectorNumElements();
1675*9880d681SAndroid Build Coastguard Worker EVT ElemVT = VT.getVectorElementType();
1676*9880d681SAndroid Build Coastguard Worker SDValue Loads[4];
1677*9880d681SAndroid Build Coastguard Worker
1678*9880d681SAndroid Build Coastguard Worker assert(NumElemVT <= 4);
1679*9880d681SAndroid Build Coastguard Worker assert(NumElemVT >= StackWidth && "Stack width cannot be greater than "
1680*9880d681SAndroid Build Coastguard Worker "vector width in load");
1681*9880d681SAndroid Build Coastguard Worker
1682*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumElemVT; ++i) {
1683*9880d681SAndroid Build Coastguard Worker unsigned Channel, PtrIncr;
1684*9880d681SAndroid Build Coastguard Worker getStackAddress(StackWidth, i, Channel, PtrIncr);
1685*9880d681SAndroid Build Coastguard Worker Ptr = DAG.getNode(ISD::ADD, DL, MVT::i32, Ptr,
1686*9880d681SAndroid Build Coastguard Worker DAG.getConstant(PtrIncr, DL, MVT::i32));
1687*9880d681SAndroid Build Coastguard Worker Loads[i] = DAG.getNode(AMDGPUISD::REGISTER_LOAD, DL, ElemVT,
1688*9880d681SAndroid Build Coastguard Worker Chain, Ptr,
1689*9880d681SAndroid Build Coastguard Worker DAG.getTargetConstant(Channel, DL, MVT::i32),
1690*9880d681SAndroid Build Coastguard Worker Op.getOperand(2));
1691*9880d681SAndroid Build Coastguard Worker }
1692*9880d681SAndroid Build Coastguard Worker EVT TargetVT = EVT::getVectorVT(*DAG.getContext(), ElemVT, NumElemVT);
1693*9880d681SAndroid Build Coastguard Worker LoweredLoad = DAG.getBuildVector(TargetVT, DL, makeArrayRef(Loads, NumElemVT));
1694*9880d681SAndroid Build Coastguard Worker } else {
1695*9880d681SAndroid Build Coastguard Worker LoweredLoad = DAG.getNode(AMDGPUISD::REGISTER_LOAD, DL, VT,
1696*9880d681SAndroid Build Coastguard Worker Chain, Ptr,
1697*9880d681SAndroid Build Coastguard Worker DAG.getTargetConstant(0, DL, MVT::i32), // Channel
1698*9880d681SAndroid Build Coastguard Worker Op.getOperand(2));
1699*9880d681SAndroid Build Coastguard Worker }
1700*9880d681SAndroid Build Coastguard Worker
1701*9880d681SAndroid Build Coastguard Worker SDValue Ops[2] = {
1702*9880d681SAndroid Build Coastguard Worker LoweredLoad,
1703*9880d681SAndroid Build Coastguard Worker Chain
1704*9880d681SAndroid Build Coastguard Worker };
1705*9880d681SAndroid Build Coastguard Worker
1706*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, DL);
1707*9880d681SAndroid Build Coastguard Worker }
1708*9880d681SAndroid Build Coastguard Worker
LowerBRCOND(SDValue Op,SelectionDAG & DAG) const1709*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
1710*9880d681SAndroid Build Coastguard Worker SDValue Chain = Op.getOperand(0);
1711*9880d681SAndroid Build Coastguard Worker SDValue Cond = Op.getOperand(1);
1712*9880d681SAndroid Build Coastguard Worker SDValue Jump = Op.getOperand(2);
1713*9880d681SAndroid Build Coastguard Worker
1714*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::BRANCH_COND, SDLoc(Op), Op.getValueType(),
1715*9880d681SAndroid Build Coastguard Worker Chain, Jump, Cond);
1716*9880d681SAndroid Build Coastguard Worker }
1717*9880d681SAndroid Build Coastguard Worker
lowerFrameIndex(SDValue Op,SelectionDAG & DAG) const1718*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::lowerFrameIndex(SDValue Op,
1719*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1720*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
1721*9880d681SAndroid Build Coastguard Worker const R600FrameLowering *TFL = getSubtarget()->getFrameLowering();
1722*9880d681SAndroid Build Coastguard Worker
1723*9880d681SAndroid Build Coastguard Worker FrameIndexSDNode *FIN = cast<FrameIndexSDNode>(Op);
1724*9880d681SAndroid Build Coastguard Worker
1725*9880d681SAndroid Build Coastguard Worker unsigned FrameIndex = FIN->getIndex();
1726*9880d681SAndroid Build Coastguard Worker unsigned IgnoredFrameReg;
1727*9880d681SAndroid Build Coastguard Worker unsigned Offset =
1728*9880d681SAndroid Build Coastguard Worker TFL->getFrameIndexReference(MF, FrameIndex, IgnoredFrameReg);
1729*9880d681SAndroid Build Coastguard Worker return DAG.getConstant(Offset * 4 * TFL->getStackWidth(MF), SDLoc(Op),
1730*9880d681SAndroid Build Coastguard Worker Op.getValueType());
1731*9880d681SAndroid Build Coastguard Worker }
1732*9880d681SAndroid Build Coastguard Worker
1733*9880d681SAndroid Build Coastguard Worker /// XXX Only kernel functions are supported, so we can assume for now that
1734*9880d681SAndroid Build Coastguard Worker /// every function is a kernel function, but in the future we should use
1735*9880d681SAndroid Build Coastguard Worker /// separate calling conventions for kernel and non-kernel functions.
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const1736*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::LowerFormalArguments(
1737*9880d681SAndroid Build Coastguard Worker SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1738*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
1739*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
1740*9880d681SAndroid Build Coastguard Worker SmallVector<CCValAssign, 16> ArgLocs;
1741*9880d681SAndroid Build Coastguard Worker CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
1742*9880d681SAndroid Build Coastguard Worker *DAG.getContext());
1743*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
1744*9880d681SAndroid Build Coastguard Worker R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();
1745*9880d681SAndroid Build Coastguard Worker
1746*9880d681SAndroid Build Coastguard Worker SmallVector<ISD::InputArg, 8> LocalIns;
1747*9880d681SAndroid Build Coastguard Worker
1748*9880d681SAndroid Build Coastguard Worker getOriginalFunctionArgs(DAG, MF.getFunction(), Ins, LocalIns);
1749*9880d681SAndroid Build Coastguard Worker
1750*9880d681SAndroid Build Coastguard Worker AnalyzeFormalArguments(CCInfo, LocalIns);
1751*9880d681SAndroid Build Coastguard Worker
1752*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Ins.size(); i < e; ++i) {
1753*9880d681SAndroid Build Coastguard Worker CCValAssign &VA = ArgLocs[i];
1754*9880d681SAndroid Build Coastguard Worker const ISD::InputArg &In = Ins[i];
1755*9880d681SAndroid Build Coastguard Worker EVT VT = In.VT;
1756*9880d681SAndroid Build Coastguard Worker EVT MemVT = VA.getLocVT();
1757*9880d681SAndroid Build Coastguard Worker if (!VT.isVector() && MemVT.isVector()) {
1758*9880d681SAndroid Build Coastguard Worker // Get load source type if scalarized.
1759*9880d681SAndroid Build Coastguard Worker MemVT = MemVT.getVectorElementType();
1760*9880d681SAndroid Build Coastguard Worker }
1761*9880d681SAndroid Build Coastguard Worker
1762*9880d681SAndroid Build Coastguard Worker if (AMDGPU::isShader(CallConv)) {
1763*9880d681SAndroid Build Coastguard Worker unsigned Reg = MF.addLiveIn(VA.getLocReg(), &AMDGPU::R600_Reg128RegClass);
1764*9880d681SAndroid Build Coastguard Worker SDValue Register = DAG.getCopyFromReg(Chain, DL, Reg, VT);
1765*9880d681SAndroid Build Coastguard Worker InVals.push_back(Register);
1766*9880d681SAndroid Build Coastguard Worker continue;
1767*9880d681SAndroid Build Coastguard Worker }
1768*9880d681SAndroid Build Coastguard Worker
1769*9880d681SAndroid Build Coastguard Worker PointerType *PtrTy = PointerType::get(VT.getTypeForEVT(*DAG.getContext()),
1770*9880d681SAndroid Build Coastguard Worker AMDGPUAS::CONSTANT_BUFFER_0);
1771*9880d681SAndroid Build Coastguard Worker
1772*9880d681SAndroid Build Coastguard Worker // i64 isn't a legal type, so the register type used ends up as i32, which
1773*9880d681SAndroid Build Coastguard Worker // isn't expected here. It attempts to create this sextload, but it ends up
1774*9880d681SAndroid Build Coastguard Worker // being invalid. Somehow this seems to work with i64 arguments, but breaks
1775*9880d681SAndroid Build Coastguard Worker // for <1 x i64>.
1776*9880d681SAndroid Build Coastguard Worker
1777*9880d681SAndroid Build Coastguard Worker // The first 36 bytes of the input buffer contains information about
1778*9880d681SAndroid Build Coastguard Worker // thread group and global sizes.
1779*9880d681SAndroid Build Coastguard Worker ISD::LoadExtType Ext = ISD::NON_EXTLOAD;
1780*9880d681SAndroid Build Coastguard Worker if (MemVT.getScalarSizeInBits() != VT.getScalarSizeInBits()) {
1781*9880d681SAndroid Build Coastguard Worker // FIXME: This should really check the extload type, but the handling of
1782*9880d681SAndroid Build Coastguard Worker // extload vector parameters seems to be broken.
1783*9880d681SAndroid Build Coastguard Worker
1784*9880d681SAndroid Build Coastguard Worker // Ext = In.Flags.isSExt() ? ISD::SEXTLOAD : ISD::ZEXTLOAD;
1785*9880d681SAndroid Build Coastguard Worker Ext = ISD::SEXTLOAD;
1786*9880d681SAndroid Build Coastguard Worker }
1787*9880d681SAndroid Build Coastguard Worker
1788*9880d681SAndroid Build Coastguard Worker // Compute the offset from the value.
1789*9880d681SAndroid Build Coastguard Worker // XXX - I think PartOffset should give you this, but it seems to give the
1790*9880d681SAndroid Build Coastguard Worker // size of the register which isn't useful.
1791*9880d681SAndroid Build Coastguard Worker
1792*9880d681SAndroid Build Coastguard Worker unsigned ValBase = ArgLocs[In.getOrigArgIndex()].getLocMemOffset();
1793*9880d681SAndroid Build Coastguard Worker unsigned PartOffset = VA.getLocMemOffset();
1794*9880d681SAndroid Build Coastguard Worker unsigned Offset = 36 + VA.getLocMemOffset();
1795*9880d681SAndroid Build Coastguard Worker
1796*9880d681SAndroid Build Coastguard Worker MachinePointerInfo PtrInfo(UndefValue::get(PtrTy), PartOffset - ValBase);
1797*9880d681SAndroid Build Coastguard Worker SDValue Arg = DAG.getLoad(ISD::UNINDEXED, Ext, VT, DL, Chain,
1798*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Offset, DL, MVT::i32),
1799*9880d681SAndroid Build Coastguard Worker DAG.getUNDEF(MVT::i32),
1800*9880d681SAndroid Build Coastguard Worker PtrInfo,
1801*9880d681SAndroid Build Coastguard Worker MemVT, false, true, true, 4);
1802*9880d681SAndroid Build Coastguard Worker
1803*9880d681SAndroid Build Coastguard Worker // 4 is the preferred alignment for the CONSTANT memory space.
1804*9880d681SAndroid Build Coastguard Worker InVals.push_back(Arg);
1805*9880d681SAndroid Build Coastguard Worker MFI->ABIArgOffset = Offset + MemVT.getStoreSize();
1806*9880d681SAndroid Build Coastguard Worker }
1807*9880d681SAndroid Build Coastguard Worker return Chain;
1808*9880d681SAndroid Build Coastguard Worker }
1809*9880d681SAndroid Build Coastguard Worker
getSetCCResultType(const DataLayout & DL,LLVMContext &,EVT VT) const1810*9880d681SAndroid Build Coastguard Worker EVT R600TargetLowering::getSetCCResultType(const DataLayout &DL, LLVMContext &,
1811*9880d681SAndroid Build Coastguard Worker EVT VT) const {
1812*9880d681SAndroid Build Coastguard Worker if (!VT.isVector())
1813*9880d681SAndroid Build Coastguard Worker return MVT::i32;
1814*9880d681SAndroid Build Coastguard Worker return VT.changeVectorElementTypeToInteger();
1815*9880d681SAndroid Build Coastguard Worker }
1816*9880d681SAndroid Build Coastguard Worker
allowsMisalignedMemoryAccesses(EVT VT,unsigned AddrSpace,unsigned Align,bool * IsFast) const1817*9880d681SAndroid Build Coastguard Worker bool R600TargetLowering::allowsMisalignedMemoryAccesses(EVT VT,
1818*9880d681SAndroid Build Coastguard Worker unsigned AddrSpace,
1819*9880d681SAndroid Build Coastguard Worker unsigned Align,
1820*9880d681SAndroid Build Coastguard Worker bool *IsFast) const {
1821*9880d681SAndroid Build Coastguard Worker if (IsFast)
1822*9880d681SAndroid Build Coastguard Worker *IsFast = false;
1823*9880d681SAndroid Build Coastguard Worker
1824*9880d681SAndroid Build Coastguard Worker if (!VT.isSimple() || VT == MVT::Other)
1825*9880d681SAndroid Build Coastguard Worker return false;
1826*9880d681SAndroid Build Coastguard Worker
1827*9880d681SAndroid Build Coastguard Worker if (VT.bitsLT(MVT::i32))
1828*9880d681SAndroid Build Coastguard Worker return false;
1829*9880d681SAndroid Build Coastguard Worker
1830*9880d681SAndroid Build Coastguard Worker // TODO: This is a rough estimate.
1831*9880d681SAndroid Build Coastguard Worker if (IsFast)
1832*9880d681SAndroid Build Coastguard Worker *IsFast = true;
1833*9880d681SAndroid Build Coastguard Worker
1834*9880d681SAndroid Build Coastguard Worker return VT.bitsGT(MVT::i32) && Align % 4 == 0;
1835*9880d681SAndroid Build Coastguard Worker }
1836*9880d681SAndroid Build Coastguard Worker
CompactSwizzlableVector(SelectionDAG & DAG,SDValue VectorEntry,DenseMap<unsigned,unsigned> & RemapSwizzle)1837*9880d681SAndroid Build Coastguard Worker static SDValue CompactSwizzlableVector(
1838*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG, SDValue VectorEntry,
1839*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, unsigned> &RemapSwizzle) {
1840*9880d681SAndroid Build Coastguard Worker assert(VectorEntry.getOpcode() == ISD::BUILD_VECTOR);
1841*9880d681SAndroid Build Coastguard Worker assert(RemapSwizzle.empty());
1842*9880d681SAndroid Build Coastguard Worker SDValue NewBldVec[4] = {
1843*9880d681SAndroid Build Coastguard Worker VectorEntry.getOperand(0),
1844*9880d681SAndroid Build Coastguard Worker VectorEntry.getOperand(1),
1845*9880d681SAndroid Build Coastguard Worker VectorEntry.getOperand(2),
1846*9880d681SAndroid Build Coastguard Worker VectorEntry.getOperand(3)
1847*9880d681SAndroid Build Coastguard Worker };
1848*9880d681SAndroid Build Coastguard Worker
1849*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++) {
1850*9880d681SAndroid Build Coastguard Worker if (NewBldVec[i].isUndef())
1851*9880d681SAndroid Build Coastguard Worker // We mask write here to teach later passes that the ith element of this
1852*9880d681SAndroid Build Coastguard Worker // vector is undef. Thus we can use it to reduce 128 bits reg usage,
1853*9880d681SAndroid Build Coastguard Worker // break false dependencies and additionnaly make assembly easier to read.
1854*9880d681SAndroid Build Coastguard Worker RemapSwizzle[i] = 7; // SEL_MASK_WRITE
1855*9880d681SAndroid Build Coastguard Worker if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(NewBldVec[i])) {
1856*9880d681SAndroid Build Coastguard Worker if (C->isZero()) {
1857*9880d681SAndroid Build Coastguard Worker RemapSwizzle[i] = 4; // SEL_0
1858*9880d681SAndroid Build Coastguard Worker NewBldVec[i] = DAG.getUNDEF(MVT::f32);
1859*9880d681SAndroid Build Coastguard Worker } else if (C->isExactlyValue(1.0)) {
1860*9880d681SAndroid Build Coastguard Worker RemapSwizzle[i] = 5; // SEL_1
1861*9880d681SAndroid Build Coastguard Worker NewBldVec[i] = DAG.getUNDEF(MVT::f32);
1862*9880d681SAndroid Build Coastguard Worker }
1863*9880d681SAndroid Build Coastguard Worker }
1864*9880d681SAndroid Build Coastguard Worker
1865*9880d681SAndroid Build Coastguard Worker if (NewBldVec[i].isUndef())
1866*9880d681SAndroid Build Coastguard Worker continue;
1867*9880d681SAndroid Build Coastguard Worker for (unsigned j = 0; j < i; j++) {
1868*9880d681SAndroid Build Coastguard Worker if (NewBldVec[i] == NewBldVec[j]) {
1869*9880d681SAndroid Build Coastguard Worker NewBldVec[i] = DAG.getUNDEF(NewBldVec[i].getValueType());
1870*9880d681SAndroid Build Coastguard Worker RemapSwizzle[i] = j;
1871*9880d681SAndroid Build Coastguard Worker break;
1872*9880d681SAndroid Build Coastguard Worker }
1873*9880d681SAndroid Build Coastguard Worker }
1874*9880d681SAndroid Build Coastguard Worker }
1875*9880d681SAndroid Build Coastguard Worker
1876*9880d681SAndroid Build Coastguard Worker return DAG.getBuildVector(VectorEntry.getValueType(), SDLoc(VectorEntry),
1877*9880d681SAndroid Build Coastguard Worker NewBldVec);
1878*9880d681SAndroid Build Coastguard Worker }
1879*9880d681SAndroid Build Coastguard Worker
ReorganizeVector(SelectionDAG & DAG,SDValue VectorEntry,DenseMap<unsigned,unsigned> & RemapSwizzle)1880*9880d681SAndroid Build Coastguard Worker static SDValue ReorganizeVector(SelectionDAG &DAG, SDValue VectorEntry,
1881*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, unsigned> &RemapSwizzle) {
1882*9880d681SAndroid Build Coastguard Worker assert(VectorEntry.getOpcode() == ISD::BUILD_VECTOR);
1883*9880d681SAndroid Build Coastguard Worker assert(RemapSwizzle.empty());
1884*9880d681SAndroid Build Coastguard Worker SDValue NewBldVec[4] = {
1885*9880d681SAndroid Build Coastguard Worker VectorEntry.getOperand(0),
1886*9880d681SAndroid Build Coastguard Worker VectorEntry.getOperand(1),
1887*9880d681SAndroid Build Coastguard Worker VectorEntry.getOperand(2),
1888*9880d681SAndroid Build Coastguard Worker VectorEntry.getOperand(3)
1889*9880d681SAndroid Build Coastguard Worker };
1890*9880d681SAndroid Build Coastguard Worker bool isUnmovable[4] = { false, false, false, false };
1891*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++) {
1892*9880d681SAndroid Build Coastguard Worker RemapSwizzle[i] = i;
1893*9880d681SAndroid Build Coastguard Worker if (NewBldVec[i].getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
1894*9880d681SAndroid Build Coastguard Worker unsigned Idx = dyn_cast<ConstantSDNode>(NewBldVec[i].getOperand(1))
1895*9880d681SAndroid Build Coastguard Worker ->getZExtValue();
1896*9880d681SAndroid Build Coastguard Worker if (i == Idx)
1897*9880d681SAndroid Build Coastguard Worker isUnmovable[Idx] = true;
1898*9880d681SAndroid Build Coastguard Worker }
1899*9880d681SAndroid Build Coastguard Worker }
1900*9880d681SAndroid Build Coastguard Worker
1901*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++) {
1902*9880d681SAndroid Build Coastguard Worker if (NewBldVec[i].getOpcode() == ISD::EXTRACT_VECTOR_ELT) {
1903*9880d681SAndroid Build Coastguard Worker unsigned Idx = dyn_cast<ConstantSDNode>(NewBldVec[i].getOperand(1))
1904*9880d681SAndroid Build Coastguard Worker ->getZExtValue();
1905*9880d681SAndroid Build Coastguard Worker if (isUnmovable[Idx])
1906*9880d681SAndroid Build Coastguard Worker continue;
1907*9880d681SAndroid Build Coastguard Worker // Swap i and Idx
1908*9880d681SAndroid Build Coastguard Worker std::swap(NewBldVec[Idx], NewBldVec[i]);
1909*9880d681SAndroid Build Coastguard Worker std::swap(RemapSwizzle[i], RemapSwizzle[Idx]);
1910*9880d681SAndroid Build Coastguard Worker break;
1911*9880d681SAndroid Build Coastguard Worker }
1912*9880d681SAndroid Build Coastguard Worker }
1913*9880d681SAndroid Build Coastguard Worker
1914*9880d681SAndroid Build Coastguard Worker return DAG.getBuildVector(VectorEntry.getValueType(), SDLoc(VectorEntry),
1915*9880d681SAndroid Build Coastguard Worker NewBldVec);
1916*9880d681SAndroid Build Coastguard Worker }
1917*9880d681SAndroid Build Coastguard Worker
OptimizeSwizzle(SDValue BuildVector,SDValue Swz[4],SelectionDAG & DAG,const SDLoc & DL) const1918*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::OptimizeSwizzle(SDValue BuildVector, SDValue Swz[4],
1919*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
1920*9880d681SAndroid Build Coastguard Worker const SDLoc &DL) const {
1921*9880d681SAndroid Build Coastguard Worker assert(BuildVector.getOpcode() == ISD::BUILD_VECTOR);
1922*9880d681SAndroid Build Coastguard Worker // Old -> New swizzle values
1923*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, unsigned> SwizzleRemap;
1924*9880d681SAndroid Build Coastguard Worker
1925*9880d681SAndroid Build Coastguard Worker BuildVector = CompactSwizzlableVector(DAG, BuildVector, SwizzleRemap);
1926*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++) {
1927*9880d681SAndroid Build Coastguard Worker unsigned Idx = cast<ConstantSDNode>(Swz[i])->getZExtValue();
1928*9880d681SAndroid Build Coastguard Worker if (SwizzleRemap.find(Idx) != SwizzleRemap.end())
1929*9880d681SAndroid Build Coastguard Worker Swz[i] = DAG.getConstant(SwizzleRemap[Idx], DL, MVT::i32);
1930*9880d681SAndroid Build Coastguard Worker }
1931*9880d681SAndroid Build Coastguard Worker
1932*9880d681SAndroid Build Coastguard Worker SwizzleRemap.clear();
1933*9880d681SAndroid Build Coastguard Worker BuildVector = ReorganizeVector(DAG, BuildVector, SwizzleRemap);
1934*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++) {
1935*9880d681SAndroid Build Coastguard Worker unsigned Idx = cast<ConstantSDNode>(Swz[i])->getZExtValue();
1936*9880d681SAndroid Build Coastguard Worker if (SwizzleRemap.find(Idx) != SwizzleRemap.end())
1937*9880d681SAndroid Build Coastguard Worker Swz[i] = DAG.getConstant(SwizzleRemap[Idx], DL, MVT::i32);
1938*9880d681SAndroid Build Coastguard Worker }
1939*9880d681SAndroid Build Coastguard Worker
1940*9880d681SAndroid Build Coastguard Worker return BuildVector;
1941*9880d681SAndroid Build Coastguard Worker }
1942*9880d681SAndroid Build Coastguard Worker
1943*9880d681SAndroid Build Coastguard Worker
1944*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1945*9880d681SAndroid Build Coastguard Worker // Custom DAG Optimizations
1946*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1947*9880d681SAndroid Build Coastguard Worker
PerformDAGCombine(SDNode * N,DAGCombinerInfo & DCI) const1948*9880d681SAndroid Build Coastguard Worker SDValue R600TargetLowering::PerformDAGCombine(SDNode *N,
1949*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
1950*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
1951*9880d681SAndroid Build Coastguard Worker
1952*9880d681SAndroid Build Coastguard Worker switch (N->getOpcode()) {
1953*9880d681SAndroid Build Coastguard Worker default: return AMDGPUTargetLowering::PerformDAGCombine(N, DCI);
1954*9880d681SAndroid Build Coastguard Worker // (f32 fp_round (f64 uint_to_fp a)) -> (f32 uint_to_fp a)
1955*9880d681SAndroid Build Coastguard Worker case ISD::FP_ROUND: {
1956*9880d681SAndroid Build Coastguard Worker SDValue Arg = N->getOperand(0);
1957*9880d681SAndroid Build Coastguard Worker if (Arg.getOpcode() == ISD::UINT_TO_FP && Arg.getValueType() == MVT::f64) {
1958*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::UINT_TO_FP, SDLoc(N), N->getValueType(0),
1959*9880d681SAndroid Build Coastguard Worker Arg.getOperand(0));
1960*9880d681SAndroid Build Coastguard Worker }
1961*9880d681SAndroid Build Coastguard Worker break;
1962*9880d681SAndroid Build Coastguard Worker }
1963*9880d681SAndroid Build Coastguard Worker
1964*9880d681SAndroid Build Coastguard Worker // (i32 fp_to_sint (fneg (select_cc f32, f32, 1.0, 0.0 cc))) ->
1965*9880d681SAndroid Build Coastguard Worker // (i32 select_cc f32, f32, -1, 0 cc)
1966*9880d681SAndroid Build Coastguard Worker //
1967*9880d681SAndroid Build Coastguard Worker // Mesa's GLSL frontend generates the above pattern a lot and we can lower
1968*9880d681SAndroid Build Coastguard Worker // this to one of the SET*_DX10 instructions.
1969*9880d681SAndroid Build Coastguard Worker case ISD::FP_TO_SINT: {
1970*9880d681SAndroid Build Coastguard Worker SDValue FNeg = N->getOperand(0);
1971*9880d681SAndroid Build Coastguard Worker if (FNeg.getOpcode() != ISD::FNEG) {
1972*9880d681SAndroid Build Coastguard Worker return SDValue();
1973*9880d681SAndroid Build Coastguard Worker }
1974*9880d681SAndroid Build Coastguard Worker SDValue SelectCC = FNeg.getOperand(0);
1975*9880d681SAndroid Build Coastguard Worker if (SelectCC.getOpcode() != ISD::SELECT_CC ||
1976*9880d681SAndroid Build Coastguard Worker SelectCC.getOperand(0).getValueType() != MVT::f32 || // LHS
1977*9880d681SAndroid Build Coastguard Worker SelectCC.getOperand(2).getValueType() != MVT::f32 || // True
1978*9880d681SAndroid Build Coastguard Worker !isHWTrueValue(SelectCC.getOperand(2)) ||
1979*9880d681SAndroid Build Coastguard Worker !isHWFalseValue(SelectCC.getOperand(3))) {
1980*9880d681SAndroid Build Coastguard Worker return SDValue();
1981*9880d681SAndroid Build Coastguard Worker }
1982*9880d681SAndroid Build Coastguard Worker
1983*9880d681SAndroid Build Coastguard Worker SDLoc dl(N);
1984*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::SELECT_CC, dl, N->getValueType(0),
1985*9880d681SAndroid Build Coastguard Worker SelectCC.getOperand(0), // LHS
1986*9880d681SAndroid Build Coastguard Worker SelectCC.getOperand(1), // RHS
1987*9880d681SAndroid Build Coastguard Worker DAG.getConstant(-1, dl, MVT::i32), // True
1988*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, dl, MVT::i32), // False
1989*9880d681SAndroid Build Coastguard Worker SelectCC.getOperand(4)); // CC
1990*9880d681SAndroid Build Coastguard Worker
1991*9880d681SAndroid Build Coastguard Worker break;
1992*9880d681SAndroid Build Coastguard Worker }
1993*9880d681SAndroid Build Coastguard Worker
1994*9880d681SAndroid Build Coastguard Worker // insert_vector_elt (build_vector elt0, ... , eltN), NewEltIdx, idx
1995*9880d681SAndroid Build Coastguard Worker // => build_vector elt0, ... , NewEltIdx, ... , eltN
1996*9880d681SAndroid Build Coastguard Worker case ISD::INSERT_VECTOR_ELT: {
1997*9880d681SAndroid Build Coastguard Worker SDValue InVec = N->getOperand(0);
1998*9880d681SAndroid Build Coastguard Worker SDValue InVal = N->getOperand(1);
1999*9880d681SAndroid Build Coastguard Worker SDValue EltNo = N->getOperand(2);
2000*9880d681SAndroid Build Coastguard Worker SDLoc dl(N);
2001*9880d681SAndroid Build Coastguard Worker
2002*9880d681SAndroid Build Coastguard Worker // If the inserted element is an UNDEF, just use the input vector.
2003*9880d681SAndroid Build Coastguard Worker if (InVal.isUndef())
2004*9880d681SAndroid Build Coastguard Worker return InVec;
2005*9880d681SAndroid Build Coastguard Worker
2006*9880d681SAndroid Build Coastguard Worker EVT VT = InVec.getValueType();
2007*9880d681SAndroid Build Coastguard Worker
2008*9880d681SAndroid Build Coastguard Worker // If we can't generate a legal BUILD_VECTOR, exit
2009*9880d681SAndroid Build Coastguard Worker if (!isOperationLegal(ISD::BUILD_VECTOR, VT))
2010*9880d681SAndroid Build Coastguard Worker return SDValue();
2011*9880d681SAndroid Build Coastguard Worker
2012*9880d681SAndroid Build Coastguard Worker // Check that we know which element is being inserted
2013*9880d681SAndroid Build Coastguard Worker if (!isa<ConstantSDNode>(EltNo))
2014*9880d681SAndroid Build Coastguard Worker return SDValue();
2015*9880d681SAndroid Build Coastguard Worker unsigned Elt = cast<ConstantSDNode>(EltNo)->getZExtValue();
2016*9880d681SAndroid Build Coastguard Worker
2017*9880d681SAndroid Build Coastguard Worker // Check that the operand is a BUILD_VECTOR (or UNDEF, which can essentially
2018*9880d681SAndroid Build Coastguard Worker // be converted to a BUILD_VECTOR). Fill in the Ops vector with the
2019*9880d681SAndroid Build Coastguard Worker // vector elements.
2020*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> Ops;
2021*9880d681SAndroid Build Coastguard Worker if (InVec.getOpcode() == ISD::BUILD_VECTOR) {
2022*9880d681SAndroid Build Coastguard Worker Ops.append(InVec.getNode()->op_begin(),
2023*9880d681SAndroid Build Coastguard Worker InVec.getNode()->op_end());
2024*9880d681SAndroid Build Coastguard Worker } else if (InVec.isUndef()) {
2025*9880d681SAndroid Build Coastguard Worker unsigned NElts = VT.getVectorNumElements();
2026*9880d681SAndroid Build Coastguard Worker Ops.append(NElts, DAG.getUNDEF(InVal.getValueType()));
2027*9880d681SAndroid Build Coastguard Worker } else {
2028*9880d681SAndroid Build Coastguard Worker return SDValue();
2029*9880d681SAndroid Build Coastguard Worker }
2030*9880d681SAndroid Build Coastguard Worker
2031*9880d681SAndroid Build Coastguard Worker // Insert the element
2032*9880d681SAndroid Build Coastguard Worker if (Elt < Ops.size()) {
2033*9880d681SAndroid Build Coastguard Worker // All the operands of BUILD_VECTOR must have the same type;
2034*9880d681SAndroid Build Coastguard Worker // we enforce that here.
2035*9880d681SAndroid Build Coastguard Worker EVT OpVT = Ops[0].getValueType();
2036*9880d681SAndroid Build Coastguard Worker if (InVal.getValueType() != OpVT)
2037*9880d681SAndroid Build Coastguard Worker InVal = OpVT.bitsGT(InVal.getValueType()) ?
2038*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::ANY_EXTEND, dl, OpVT, InVal) :
2039*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::TRUNCATE, dl, OpVT, InVal);
2040*9880d681SAndroid Build Coastguard Worker Ops[Elt] = InVal;
2041*9880d681SAndroid Build Coastguard Worker }
2042*9880d681SAndroid Build Coastguard Worker
2043*9880d681SAndroid Build Coastguard Worker // Return the new vector
2044*9880d681SAndroid Build Coastguard Worker return DAG.getBuildVector(VT, dl, Ops);
2045*9880d681SAndroid Build Coastguard Worker }
2046*9880d681SAndroid Build Coastguard Worker
2047*9880d681SAndroid Build Coastguard Worker // Extract_vec (Build_vector) generated by custom lowering
2048*9880d681SAndroid Build Coastguard Worker // also needs to be customly combined
2049*9880d681SAndroid Build Coastguard Worker case ISD::EXTRACT_VECTOR_ELT: {
2050*9880d681SAndroid Build Coastguard Worker SDValue Arg = N->getOperand(0);
2051*9880d681SAndroid Build Coastguard Worker if (Arg.getOpcode() == ISD::BUILD_VECTOR) {
2052*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
2053*9880d681SAndroid Build Coastguard Worker unsigned Element = Const->getZExtValue();
2054*9880d681SAndroid Build Coastguard Worker return Arg->getOperand(Element);
2055*9880d681SAndroid Build Coastguard Worker }
2056*9880d681SAndroid Build Coastguard Worker }
2057*9880d681SAndroid Build Coastguard Worker if (Arg.getOpcode() == ISD::BITCAST &&
2058*9880d681SAndroid Build Coastguard Worker Arg.getOperand(0).getOpcode() == ISD::BUILD_VECTOR) {
2059*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
2060*9880d681SAndroid Build Coastguard Worker unsigned Element = Const->getZExtValue();
2061*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getVTList(),
2062*9880d681SAndroid Build Coastguard Worker Arg->getOperand(0).getOperand(Element));
2063*9880d681SAndroid Build Coastguard Worker }
2064*9880d681SAndroid Build Coastguard Worker }
2065*9880d681SAndroid Build Coastguard Worker break;
2066*9880d681SAndroid Build Coastguard Worker }
2067*9880d681SAndroid Build Coastguard Worker
2068*9880d681SAndroid Build Coastguard Worker case ISD::SELECT_CC: {
2069*9880d681SAndroid Build Coastguard Worker // Try common optimizations
2070*9880d681SAndroid Build Coastguard Worker if (SDValue Ret = AMDGPUTargetLowering::PerformDAGCombine(N, DCI))
2071*9880d681SAndroid Build Coastguard Worker return Ret;
2072*9880d681SAndroid Build Coastguard Worker
2073*9880d681SAndroid Build Coastguard Worker // fold selectcc (selectcc x, y, a, b, cc), b, a, b, seteq ->
2074*9880d681SAndroid Build Coastguard Worker // selectcc x, y, a, b, inv(cc)
2075*9880d681SAndroid Build Coastguard Worker //
2076*9880d681SAndroid Build Coastguard Worker // fold selectcc (selectcc x, y, a, b, cc), b, a, b, setne ->
2077*9880d681SAndroid Build Coastguard Worker // selectcc x, y, a, b, cc
2078*9880d681SAndroid Build Coastguard Worker SDValue LHS = N->getOperand(0);
2079*9880d681SAndroid Build Coastguard Worker if (LHS.getOpcode() != ISD::SELECT_CC) {
2080*9880d681SAndroid Build Coastguard Worker return SDValue();
2081*9880d681SAndroid Build Coastguard Worker }
2082*9880d681SAndroid Build Coastguard Worker
2083*9880d681SAndroid Build Coastguard Worker SDValue RHS = N->getOperand(1);
2084*9880d681SAndroid Build Coastguard Worker SDValue True = N->getOperand(2);
2085*9880d681SAndroid Build Coastguard Worker SDValue False = N->getOperand(3);
2086*9880d681SAndroid Build Coastguard Worker ISD::CondCode NCC = cast<CondCodeSDNode>(N->getOperand(4))->get();
2087*9880d681SAndroid Build Coastguard Worker
2088*9880d681SAndroid Build Coastguard Worker if (LHS.getOperand(2).getNode() != True.getNode() ||
2089*9880d681SAndroid Build Coastguard Worker LHS.getOperand(3).getNode() != False.getNode() ||
2090*9880d681SAndroid Build Coastguard Worker RHS.getNode() != False.getNode()) {
2091*9880d681SAndroid Build Coastguard Worker return SDValue();
2092*9880d681SAndroid Build Coastguard Worker }
2093*9880d681SAndroid Build Coastguard Worker
2094*9880d681SAndroid Build Coastguard Worker switch (NCC) {
2095*9880d681SAndroid Build Coastguard Worker default: return SDValue();
2096*9880d681SAndroid Build Coastguard Worker case ISD::SETNE: return LHS;
2097*9880d681SAndroid Build Coastguard Worker case ISD::SETEQ: {
2098*9880d681SAndroid Build Coastguard Worker ISD::CondCode LHSCC = cast<CondCodeSDNode>(LHS.getOperand(4))->get();
2099*9880d681SAndroid Build Coastguard Worker LHSCC = ISD::getSetCCInverse(LHSCC,
2100*9880d681SAndroid Build Coastguard Worker LHS.getOperand(0).getValueType().isInteger());
2101*9880d681SAndroid Build Coastguard Worker if (DCI.isBeforeLegalizeOps() ||
2102*9880d681SAndroid Build Coastguard Worker isCondCodeLegal(LHSCC, LHS.getOperand(0).getSimpleValueType()))
2103*9880d681SAndroid Build Coastguard Worker return DAG.getSelectCC(SDLoc(N),
2104*9880d681SAndroid Build Coastguard Worker LHS.getOperand(0),
2105*9880d681SAndroid Build Coastguard Worker LHS.getOperand(1),
2106*9880d681SAndroid Build Coastguard Worker LHS.getOperand(2),
2107*9880d681SAndroid Build Coastguard Worker LHS.getOperand(3),
2108*9880d681SAndroid Build Coastguard Worker LHSCC);
2109*9880d681SAndroid Build Coastguard Worker break;
2110*9880d681SAndroid Build Coastguard Worker }
2111*9880d681SAndroid Build Coastguard Worker }
2112*9880d681SAndroid Build Coastguard Worker return SDValue();
2113*9880d681SAndroid Build Coastguard Worker }
2114*9880d681SAndroid Build Coastguard Worker
2115*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::EXPORT: {
2116*9880d681SAndroid Build Coastguard Worker SDValue Arg = N->getOperand(1);
2117*9880d681SAndroid Build Coastguard Worker if (Arg.getOpcode() != ISD::BUILD_VECTOR)
2118*9880d681SAndroid Build Coastguard Worker break;
2119*9880d681SAndroid Build Coastguard Worker
2120*9880d681SAndroid Build Coastguard Worker SDValue NewArgs[8] = {
2121*9880d681SAndroid Build Coastguard Worker N->getOperand(0), // Chain
2122*9880d681SAndroid Build Coastguard Worker SDValue(),
2123*9880d681SAndroid Build Coastguard Worker N->getOperand(2), // ArrayBase
2124*9880d681SAndroid Build Coastguard Worker N->getOperand(3), // Type
2125*9880d681SAndroid Build Coastguard Worker N->getOperand(4), // SWZ_X
2126*9880d681SAndroid Build Coastguard Worker N->getOperand(5), // SWZ_Y
2127*9880d681SAndroid Build Coastguard Worker N->getOperand(6), // SWZ_Z
2128*9880d681SAndroid Build Coastguard Worker N->getOperand(7) // SWZ_W
2129*9880d681SAndroid Build Coastguard Worker };
2130*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
2131*9880d681SAndroid Build Coastguard Worker NewArgs[1] = OptimizeSwizzle(N->getOperand(1), &NewArgs[4], DAG, DL);
2132*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::EXPORT, DL, N->getVTList(), NewArgs);
2133*9880d681SAndroid Build Coastguard Worker }
2134*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::TEXTURE_FETCH: {
2135*9880d681SAndroid Build Coastguard Worker SDValue Arg = N->getOperand(1);
2136*9880d681SAndroid Build Coastguard Worker if (Arg.getOpcode() != ISD::BUILD_VECTOR)
2137*9880d681SAndroid Build Coastguard Worker break;
2138*9880d681SAndroid Build Coastguard Worker
2139*9880d681SAndroid Build Coastguard Worker SDValue NewArgs[19] = {
2140*9880d681SAndroid Build Coastguard Worker N->getOperand(0),
2141*9880d681SAndroid Build Coastguard Worker N->getOperand(1),
2142*9880d681SAndroid Build Coastguard Worker N->getOperand(2),
2143*9880d681SAndroid Build Coastguard Worker N->getOperand(3),
2144*9880d681SAndroid Build Coastguard Worker N->getOperand(4),
2145*9880d681SAndroid Build Coastguard Worker N->getOperand(5),
2146*9880d681SAndroid Build Coastguard Worker N->getOperand(6),
2147*9880d681SAndroid Build Coastguard Worker N->getOperand(7),
2148*9880d681SAndroid Build Coastguard Worker N->getOperand(8),
2149*9880d681SAndroid Build Coastguard Worker N->getOperand(9),
2150*9880d681SAndroid Build Coastguard Worker N->getOperand(10),
2151*9880d681SAndroid Build Coastguard Worker N->getOperand(11),
2152*9880d681SAndroid Build Coastguard Worker N->getOperand(12),
2153*9880d681SAndroid Build Coastguard Worker N->getOperand(13),
2154*9880d681SAndroid Build Coastguard Worker N->getOperand(14),
2155*9880d681SAndroid Build Coastguard Worker N->getOperand(15),
2156*9880d681SAndroid Build Coastguard Worker N->getOperand(16),
2157*9880d681SAndroid Build Coastguard Worker N->getOperand(17),
2158*9880d681SAndroid Build Coastguard Worker N->getOperand(18),
2159*9880d681SAndroid Build Coastguard Worker };
2160*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
2161*9880d681SAndroid Build Coastguard Worker NewArgs[1] = OptimizeSwizzle(N->getOperand(1), &NewArgs[2], DAG, DL);
2162*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::TEXTURE_FETCH, DL, N->getVTList(), NewArgs);
2163*9880d681SAndroid Build Coastguard Worker }
2164*9880d681SAndroid Build Coastguard Worker }
2165*9880d681SAndroid Build Coastguard Worker
2166*9880d681SAndroid Build Coastguard Worker return AMDGPUTargetLowering::PerformDAGCombine(N, DCI);
2167*9880d681SAndroid Build Coastguard Worker }
2168*9880d681SAndroid Build Coastguard Worker
FoldOperand(SDNode * ParentNode,unsigned SrcIdx,SDValue & Src,SDValue & Neg,SDValue & Abs,SDValue & Sel,SDValue & Imm,SelectionDAG & DAG) const2169*9880d681SAndroid Build Coastguard Worker bool R600TargetLowering::FoldOperand(SDNode *ParentNode, unsigned SrcIdx,
2170*9880d681SAndroid Build Coastguard Worker SDValue &Src, SDValue &Neg, SDValue &Abs,
2171*9880d681SAndroid Build Coastguard Worker SDValue &Sel, SDValue &Imm,
2172*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2173*9880d681SAndroid Build Coastguard Worker const R600InstrInfo *TII = getSubtarget()->getInstrInfo();
2174*9880d681SAndroid Build Coastguard Worker if (!Src.isMachineOpcode())
2175*9880d681SAndroid Build Coastguard Worker return false;
2176*9880d681SAndroid Build Coastguard Worker
2177*9880d681SAndroid Build Coastguard Worker switch (Src.getMachineOpcode()) {
2178*9880d681SAndroid Build Coastguard Worker case AMDGPU::FNEG_R600:
2179*9880d681SAndroid Build Coastguard Worker if (!Neg.getNode())
2180*9880d681SAndroid Build Coastguard Worker return false;
2181*9880d681SAndroid Build Coastguard Worker Src = Src.getOperand(0);
2182*9880d681SAndroid Build Coastguard Worker Neg = DAG.getTargetConstant(1, SDLoc(ParentNode), MVT::i32);
2183*9880d681SAndroid Build Coastguard Worker return true;
2184*9880d681SAndroid Build Coastguard Worker case AMDGPU::FABS_R600:
2185*9880d681SAndroid Build Coastguard Worker if (!Abs.getNode())
2186*9880d681SAndroid Build Coastguard Worker return false;
2187*9880d681SAndroid Build Coastguard Worker Src = Src.getOperand(0);
2188*9880d681SAndroid Build Coastguard Worker Abs = DAG.getTargetConstant(1, SDLoc(ParentNode), MVT::i32);
2189*9880d681SAndroid Build Coastguard Worker return true;
2190*9880d681SAndroid Build Coastguard Worker case AMDGPU::CONST_COPY: {
2191*9880d681SAndroid Build Coastguard Worker unsigned Opcode = ParentNode->getMachineOpcode();
2192*9880d681SAndroid Build Coastguard Worker bool HasDst = TII->getOperandIdx(Opcode, AMDGPU::OpName::dst) > -1;
2193*9880d681SAndroid Build Coastguard Worker
2194*9880d681SAndroid Build Coastguard Worker if (!Sel.getNode())
2195*9880d681SAndroid Build Coastguard Worker return false;
2196*9880d681SAndroid Build Coastguard Worker
2197*9880d681SAndroid Build Coastguard Worker SDValue CstOffset = Src.getOperand(0);
2198*9880d681SAndroid Build Coastguard Worker if (ParentNode->getValueType(0).isVector())
2199*9880d681SAndroid Build Coastguard Worker return false;
2200*9880d681SAndroid Build Coastguard Worker
2201*9880d681SAndroid Build Coastguard Worker // Gather constants values
2202*9880d681SAndroid Build Coastguard Worker int SrcIndices[] = {
2203*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0),
2204*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1),
2205*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src2),
2206*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_X),
2207*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_Y),
2208*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_Z),
2209*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_W),
2210*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_X),
2211*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_Y),
2212*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_Z),
2213*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_W)
2214*9880d681SAndroid Build Coastguard Worker };
2215*9880d681SAndroid Build Coastguard Worker std::vector<unsigned> Consts;
2216*9880d681SAndroid Build Coastguard Worker for (int OtherSrcIdx : SrcIndices) {
2217*9880d681SAndroid Build Coastguard Worker int OtherSelIdx = TII->getSelIdx(Opcode, OtherSrcIdx);
2218*9880d681SAndroid Build Coastguard Worker if (OtherSrcIdx < 0 || OtherSelIdx < 0)
2219*9880d681SAndroid Build Coastguard Worker continue;
2220*9880d681SAndroid Build Coastguard Worker if (HasDst) {
2221*9880d681SAndroid Build Coastguard Worker OtherSrcIdx--;
2222*9880d681SAndroid Build Coastguard Worker OtherSelIdx--;
2223*9880d681SAndroid Build Coastguard Worker }
2224*9880d681SAndroid Build Coastguard Worker if (RegisterSDNode *Reg =
2225*9880d681SAndroid Build Coastguard Worker dyn_cast<RegisterSDNode>(ParentNode->getOperand(OtherSrcIdx))) {
2226*9880d681SAndroid Build Coastguard Worker if (Reg->getReg() == AMDGPU::ALU_CONST) {
2227*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Cst
2228*9880d681SAndroid Build Coastguard Worker = cast<ConstantSDNode>(ParentNode->getOperand(OtherSelIdx));
2229*9880d681SAndroid Build Coastguard Worker Consts.push_back(Cst->getZExtValue());
2230*9880d681SAndroid Build Coastguard Worker }
2231*9880d681SAndroid Build Coastguard Worker }
2232*9880d681SAndroid Build Coastguard Worker }
2233*9880d681SAndroid Build Coastguard Worker
2234*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Cst = cast<ConstantSDNode>(CstOffset);
2235*9880d681SAndroid Build Coastguard Worker Consts.push_back(Cst->getZExtValue());
2236*9880d681SAndroid Build Coastguard Worker if (!TII->fitsConstReadLimitations(Consts)) {
2237*9880d681SAndroid Build Coastguard Worker return false;
2238*9880d681SAndroid Build Coastguard Worker }
2239*9880d681SAndroid Build Coastguard Worker
2240*9880d681SAndroid Build Coastguard Worker Sel = CstOffset;
2241*9880d681SAndroid Build Coastguard Worker Src = DAG.getRegister(AMDGPU::ALU_CONST, MVT::f32);
2242*9880d681SAndroid Build Coastguard Worker return true;
2243*9880d681SAndroid Build Coastguard Worker }
2244*9880d681SAndroid Build Coastguard Worker case AMDGPU::MOV_IMM_GLOBAL_ADDR:
2245*9880d681SAndroid Build Coastguard Worker // Check if the Imm slot is used. Taken from below.
2246*9880d681SAndroid Build Coastguard Worker if (cast<ConstantSDNode>(Imm)->getZExtValue())
2247*9880d681SAndroid Build Coastguard Worker return false;
2248*9880d681SAndroid Build Coastguard Worker Imm = Src.getOperand(0);
2249*9880d681SAndroid Build Coastguard Worker Src = DAG.getRegister(AMDGPU::ALU_LITERAL_X, MVT::i32);
2250*9880d681SAndroid Build Coastguard Worker return true;
2251*9880d681SAndroid Build Coastguard Worker case AMDGPU::MOV_IMM_I32:
2252*9880d681SAndroid Build Coastguard Worker case AMDGPU::MOV_IMM_F32: {
2253*9880d681SAndroid Build Coastguard Worker unsigned ImmReg = AMDGPU::ALU_LITERAL_X;
2254*9880d681SAndroid Build Coastguard Worker uint64_t ImmValue = 0;
2255*9880d681SAndroid Build Coastguard Worker
2256*9880d681SAndroid Build Coastguard Worker
2257*9880d681SAndroid Build Coastguard Worker if (Src.getMachineOpcode() == AMDGPU::MOV_IMM_F32) {
2258*9880d681SAndroid Build Coastguard Worker ConstantFPSDNode *FPC = dyn_cast<ConstantFPSDNode>(Src.getOperand(0));
2259*9880d681SAndroid Build Coastguard Worker float FloatValue = FPC->getValueAPF().convertToFloat();
2260*9880d681SAndroid Build Coastguard Worker if (FloatValue == 0.0) {
2261*9880d681SAndroid Build Coastguard Worker ImmReg = AMDGPU::ZERO;
2262*9880d681SAndroid Build Coastguard Worker } else if (FloatValue == 0.5) {
2263*9880d681SAndroid Build Coastguard Worker ImmReg = AMDGPU::HALF;
2264*9880d681SAndroid Build Coastguard Worker } else if (FloatValue == 1.0) {
2265*9880d681SAndroid Build Coastguard Worker ImmReg = AMDGPU::ONE;
2266*9880d681SAndroid Build Coastguard Worker } else {
2267*9880d681SAndroid Build Coastguard Worker ImmValue = FPC->getValueAPF().bitcastToAPInt().getZExtValue();
2268*9880d681SAndroid Build Coastguard Worker }
2269*9880d681SAndroid Build Coastguard Worker } else {
2270*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C = dyn_cast<ConstantSDNode>(Src.getOperand(0));
2271*9880d681SAndroid Build Coastguard Worker uint64_t Value = C->getZExtValue();
2272*9880d681SAndroid Build Coastguard Worker if (Value == 0) {
2273*9880d681SAndroid Build Coastguard Worker ImmReg = AMDGPU::ZERO;
2274*9880d681SAndroid Build Coastguard Worker } else if (Value == 1) {
2275*9880d681SAndroid Build Coastguard Worker ImmReg = AMDGPU::ONE_INT;
2276*9880d681SAndroid Build Coastguard Worker } else {
2277*9880d681SAndroid Build Coastguard Worker ImmValue = Value;
2278*9880d681SAndroid Build Coastguard Worker }
2279*9880d681SAndroid Build Coastguard Worker }
2280*9880d681SAndroid Build Coastguard Worker
2281*9880d681SAndroid Build Coastguard Worker // Check that we aren't already using an immediate.
2282*9880d681SAndroid Build Coastguard Worker // XXX: It's possible for an instruction to have more than one
2283*9880d681SAndroid Build Coastguard Worker // immediate operand, but this is not supported yet.
2284*9880d681SAndroid Build Coastguard Worker if (ImmReg == AMDGPU::ALU_LITERAL_X) {
2285*9880d681SAndroid Build Coastguard Worker if (!Imm.getNode())
2286*9880d681SAndroid Build Coastguard Worker return false;
2287*9880d681SAndroid Build Coastguard Worker ConstantSDNode *C = dyn_cast<ConstantSDNode>(Imm);
2288*9880d681SAndroid Build Coastguard Worker assert(C);
2289*9880d681SAndroid Build Coastguard Worker if (C->getZExtValue())
2290*9880d681SAndroid Build Coastguard Worker return false;
2291*9880d681SAndroid Build Coastguard Worker Imm = DAG.getTargetConstant(ImmValue, SDLoc(ParentNode), MVT::i32);
2292*9880d681SAndroid Build Coastguard Worker }
2293*9880d681SAndroid Build Coastguard Worker Src = DAG.getRegister(ImmReg, MVT::i32);
2294*9880d681SAndroid Build Coastguard Worker return true;
2295*9880d681SAndroid Build Coastguard Worker }
2296*9880d681SAndroid Build Coastguard Worker default:
2297*9880d681SAndroid Build Coastguard Worker return false;
2298*9880d681SAndroid Build Coastguard Worker }
2299*9880d681SAndroid Build Coastguard Worker }
2300*9880d681SAndroid Build Coastguard Worker
2301*9880d681SAndroid Build Coastguard Worker /// \brief Fold the instructions after selecting them
PostISelFolding(MachineSDNode * Node,SelectionDAG & DAG) const2302*9880d681SAndroid Build Coastguard Worker SDNode *R600TargetLowering::PostISelFolding(MachineSDNode *Node,
2303*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2304*9880d681SAndroid Build Coastguard Worker const R600InstrInfo *TII = getSubtarget()->getInstrInfo();
2305*9880d681SAndroid Build Coastguard Worker if (!Node->isMachineOpcode())
2306*9880d681SAndroid Build Coastguard Worker return Node;
2307*9880d681SAndroid Build Coastguard Worker
2308*9880d681SAndroid Build Coastguard Worker unsigned Opcode = Node->getMachineOpcode();
2309*9880d681SAndroid Build Coastguard Worker SDValue FakeOp;
2310*9880d681SAndroid Build Coastguard Worker
2311*9880d681SAndroid Build Coastguard Worker std::vector<SDValue> Ops(Node->op_begin(), Node->op_end());
2312*9880d681SAndroid Build Coastguard Worker
2313*9880d681SAndroid Build Coastguard Worker if (Opcode == AMDGPU::DOT_4) {
2314*9880d681SAndroid Build Coastguard Worker int OperandIdx[] = {
2315*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_X),
2316*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_Y),
2317*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_Z),
2318*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_W),
2319*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_X),
2320*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_Y),
2321*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_Z),
2322*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_W)
2323*9880d681SAndroid Build Coastguard Worker };
2324*9880d681SAndroid Build Coastguard Worker int NegIdx[] = {
2325*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_neg_X),
2326*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_neg_Y),
2327*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_neg_Z),
2328*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_neg_W),
2329*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_neg_X),
2330*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_neg_Y),
2331*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_neg_Z),
2332*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_neg_W)
2333*9880d681SAndroid Build Coastguard Worker };
2334*9880d681SAndroid Build Coastguard Worker int AbsIdx[] = {
2335*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_abs_X),
2336*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_abs_Y),
2337*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_abs_Z),
2338*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_abs_W),
2339*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_abs_X),
2340*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_abs_Y),
2341*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_abs_Z),
2342*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_abs_W)
2343*9880d681SAndroid Build Coastguard Worker };
2344*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 8; i++) {
2345*9880d681SAndroid Build Coastguard Worker if (OperandIdx[i] < 0)
2346*9880d681SAndroid Build Coastguard Worker return Node;
2347*9880d681SAndroid Build Coastguard Worker SDValue &Src = Ops[OperandIdx[i] - 1];
2348*9880d681SAndroid Build Coastguard Worker SDValue &Neg = Ops[NegIdx[i] - 1];
2349*9880d681SAndroid Build Coastguard Worker SDValue &Abs = Ops[AbsIdx[i] - 1];
2350*9880d681SAndroid Build Coastguard Worker bool HasDst = TII->getOperandIdx(Opcode, AMDGPU::OpName::dst) > -1;
2351*9880d681SAndroid Build Coastguard Worker int SelIdx = TII->getSelIdx(Opcode, OperandIdx[i]);
2352*9880d681SAndroid Build Coastguard Worker if (HasDst)
2353*9880d681SAndroid Build Coastguard Worker SelIdx--;
2354*9880d681SAndroid Build Coastguard Worker SDValue &Sel = (SelIdx > -1) ? Ops[SelIdx] : FakeOp;
2355*9880d681SAndroid Build Coastguard Worker if (FoldOperand(Node, i, Src, Neg, Abs, Sel, FakeOp, DAG))
2356*9880d681SAndroid Build Coastguard Worker return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
2357*9880d681SAndroid Build Coastguard Worker }
2358*9880d681SAndroid Build Coastguard Worker } else if (Opcode == AMDGPU::REG_SEQUENCE) {
2359*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, e = Node->getNumOperands(); i < e; i += 2) {
2360*9880d681SAndroid Build Coastguard Worker SDValue &Src = Ops[i];
2361*9880d681SAndroid Build Coastguard Worker if (FoldOperand(Node, i, Src, FakeOp, FakeOp, FakeOp, FakeOp, DAG))
2362*9880d681SAndroid Build Coastguard Worker return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
2363*9880d681SAndroid Build Coastguard Worker }
2364*9880d681SAndroid Build Coastguard Worker } else if (Opcode == AMDGPU::CLAMP_R600) {
2365*9880d681SAndroid Build Coastguard Worker SDValue Src = Node->getOperand(0);
2366*9880d681SAndroid Build Coastguard Worker if (!Src.isMachineOpcode() ||
2367*9880d681SAndroid Build Coastguard Worker !TII->hasInstrModifiers(Src.getMachineOpcode()))
2368*9880d681SAndroid Build Coastguard Worker return Node;
2369*9880d681SAndroid Build Coastguard Worker int ClampIdx = TII->getOperandIdx(Src.getMachineOpcode(),
2370*9880d681SAndroid Build Coastguard Worker AMDGPU::OpName::clamp);
2371*9880d681SAndroid Build Coastguard Worker if (ClampIdx < 0)
2372*9880d681SAndroid Build Coastguard Worker return Node;
2373*9880d681SAndroid Build Coastguard Worker SDLoc DL(Node);
2374*9880d681SAndroid Build Coastguard Worker std::vector<SDValue> Ops(Src->op_begin(), Src->op_end());
2375*9880d681SAndroid Build Coastguard Worker Ops[ClampIdx - 1] = DAG.getTargetConstant(1, DL, MVT::i32);
2376*9880d681SAndroid Build Coastguard Worker return DAG.getMachineNode(Src.getMachineOpcode(), DL,
2377*9880d681SAndroid Build Coastguard Worker Node->getVTList(), Ops);
2378*9880d681SAndroid Build Coastguard Worker } else {
2379*9880d681SAndroid Build Coastguard Worker if (!TII->hasInstrModifiers(Opcode))
2380*9880d681SAndroid Build Coastguard Worker return Node;
2381*9880d681SAndroid Build Coastguard Worker int OperandIdx[] = {
2382*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0),
2383*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1),
2384*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src2)
2385*9880d681SAndroid Build Coastguard Worker };
2386*9880d681SAndroid Build Coastguard Worker int NegIdx[] = {
2387*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_neg),
2388*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_neg),
2389*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src2_neg)
2390*9880d681SAndroid Build Coastguard Worker };
2391*9880d681SAndroid Build Coastguard Worker int AbsIdx[] = {
2392*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src0_abs),
2393*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(Opcode, AMDGPU::OpName::src1_abs),
2394*9880d681SAndroid Build Coastguard Worker -1
2395*9880d681SAndroid Build Coastguard Worker };
2396*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < 3; i++) {
2397*9880d681SAndroid Build Coastguard Worker if (OperandIdx[i] < 0)
2398*9880d681SAndroid Build Coastguard Worker return Node;
2399*9880d681SAndroid Build Coastguard Worker SDValue &Src = Ops[OperandIdx[i] - 1];
2400*9880d681SAndroid Build Coastguard Worker SDValue &Neg = Ops[NegIdx[i] - 1];
2401*9880d681SAndroid Build Coastguard Worker SDValue FakeAbs;
2402*9880d681SAndroid Build Coastguard Worker SDValue &Abs = (AbsIdx[i] > -1) ? Ops[AbsIdx[i] - 1] : FakeAbs;
2403*9880d681SAndroid Build Coastguard Worker bool HasDst = TII->getOperandIdx(Opcode, AMDGPU::OpName::dst) > -1;
2404*9880d681SAndroid Build Coastguard Worker int SelIdx = TII->getSelIdx(Opcode, OperandIdx[i]);
2405*9880d681SAndroid Build Coastguard Worker int ImmIdx = TII->getOperandIdx(Opcode, AMDGPU::OpName::literal);
2406*9880d681SAndroid Build Coastguard Worker if (HasDst) {
2407*9880d681SAndroid Build Coastguard Worker SelIdx--;
2408*9880d681SAndroid Build Coastguard Worker ImmIdx--;
2409*9880d681SAndroid Build Coastguard Worker }
2410*9880d681SAndroid Build Coastguard Worker SDValue &Sel = (SelIdx > -1) ? Ops[SelIdx] : FakeOp;
2411*9880d681SAndroid Build Coastguard Worker SDValue &Imm = Ops[ImmIdx];
2412*9880d681SAndroid Build Coastguard Worker if (FoldOperand(Node, i, Src, Neg, Abs, Sel, Imm, DAG))
2413*9880d681SAndroid Build Coastguard Worker return DAG.getMachineNode(Opcode, SDLoc(Node), Node->getVTList(), Ops);
2414*9880d681SAndroid Build Coastguard Worker }
2415*9880d681SAndroid Build Coastguard Worker }
2416*9880d681SAndroid Build Coastguard Worker
2417*9880d681SAndroid Build Coastguard Worker return Node;
2418*9880d681SAndroid Build Coastguard Worker }
2419