xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/R600ISelLowering.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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