1*9880d681SAndroid Build Coastguard Worker //===-- AMDGPUISelLowering.cpp - AMDGPU Common DAG lowering functions -----===//
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 This is the parent TargetLowering class for hardware code gen
12*9880d681SAndroid Build Coastguard Worker /// targets.
13*9880d681SAndroid Build Coastguard Worker //
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "AMDGPUISelLowering.h"
17*9880d681SAndroid Build Coastguard Worker #include "AMDGPU.h"
18*9880d681SAndroid Build Coastguard Worker #include "AMDGPUFrameLowering.h"
19*9880d681SAndroid Build Coastguard Worker #include "AMDGPUIntrinsicInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "AMDGPURegisterInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "AMDGPUSubtarget.h"
22*9880d681SAndroid Build Coastguard Worker #include "R600MachineFunctionInfo.h"
23*9880d681SAndroid Build Coastguard Worker #include "SIMachineFunctionInfo.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/CallingConvLower.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunction.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/CodeGen/TargetLoweringObjectFileImpl.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DataLayout.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/DiagnosticInfo.h"
31*9880d681SAndroid Build Coastguard Worker #include "SIInstrInfo.h"
32*9880d681SAndroid Build Coastguard Worker using namespace llvm;
33*9880d681SAndroid Build Coastguard Worker
allocateKernArg(unsigned ValNo,MVT ValVT,MVT LocVT,CCValAssign::LocInfo LocInfo,ISD::ArgFlagsTy ArgFlags,CCState & State)34*9880d681SAndroid Build Coastguard Worker static bool allocateKernArg(unsigned ValNo, MVT ValVT, MVT LocVT,
35*9880d681SAndroid Build Coastguard Worker CCValAssign::LocInfo LocInfo,
36*9880d681SAndroid Build Coastguard Worker ISD::ArgFlagsTy ArgFlags, CCState &State) {
37*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = State.getMachineFunction();
38*9880d681SAndroid Build Coastguard Worker AMDGPUMachineFunction *MFI = MF.getInfo<AMDGPUMachineFunction>();
39*9880d681SAndroid Build Coastguard Worker
40*9880d681SAndroid Build Coastguard Worker uint64_t Offset = MFI->allocateKernArg(ValVT.getStoreSize(),
41*9880d681SAndroid Build Coastguard Worker ArgFlags.getOrigAlign());
42*9880d681SAndroid Build Coastguard Worker State.addLoc(CCValAssign::getCustomMem(ValNo, ValVT, Offset, LocVT, LocInfo));
43*9880d681SAndroid Build Coastguard Worker return true;
44*9880d681SAndroid Build Coastguard Worker }
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker #include "AMDGPUGenCallingConv.inc"
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker // Find a larger type to do a load / store of a vector with.
getEquivalentMemType(LLVMContext & Ctx,EVT VT)49*9880d681SAndroid Build Coastguard Worker EVT AMDGPUTargetLowering::getEquivalentMemType(LLVMContext &Ctx, EVT VT) {
50*9880d681SAndroid Build Coastguard Worker unsigned StoreSize = VT.getStoreSizeInBits();
51*9880d681SAndroid Build Coastguard Worker if (StoreSize <= 32)
52*9880d681SAndroid Build Coastguard Worker return EVT::getIntegerVT(Ctx, StoreSize);
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker assert(StoreSize % 32 == 0 && "Store size not a multiple of 32");
55*9880d681SAndroid Build Coastguard Worker return EVT::getVectorVT(Ctx, MVT::i32, StoreSize / 32);
56*9880d681SAndroid Build Coastguard Worker }
57*9880d681SAndroid Build Coastguard Worker
getEquivalentBitType(LLVMContext & Ctx,EVT VT)58*9880d681SAndroid Build Coastguard Worker EVT AMDGPUTargetLowering::getEquivalentBitType(LLVMContext &Ctx, EVT VT) {
59*9880d681SAndroid Build Coastguard Worker unsigned StoreSize = VT.getStoreSizeInBits();
60*9880d681SAndroid Build Coastguard Worker if (StoreSize <= 32)
61*9880d681SAndroid Build Coastguard Worker return EVT::getIntegerVT(Ctx, StoreSize);
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Worker return EVT::getVectorVT(Ctx, MVT::i32, StoreSize / 32);
64*9880d681SAndroid Build Coastguard Worker }
65*9880d681SAndroid Build Coastguard Worker
AMDGPUTargetLowering(const TargetMachine & TM,const AMDGPUSubtarget & STI)66*9880d681SAndroid Build Coastguard Worker AMDGPUTargetLowering::AMDGPUTargetLowering(const TargetMachine &TM,
67*9880d681SAndroid Build Coastguard Worker const AMDGPUSubtarget &STI)
68*9880d681SAndroid Build Coastguard Worker : TargetLowering(TM), Subtarget(&STI) {
69*9880d681SAndroid Build Coastguard Worker // Lower floating point store/load to integer store/load to reduce the number
70*9880d681SAndroid Build Coastguard Worker // of patterns in tablegen.
71*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::f32, Promote);
72*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::f32, MVT::i32);
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::v2f32, Promote);
75*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::v2f32, MVT::v2i32);
76*9880d681SAndroid Build Coastguard Worker
77*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::v4f32, Promote);
78*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::v4f32, MVT::v4i32);
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::v8f32, Promote);
81*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::v8f32, MVT::v8i32);
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::v16f32, Promote);
84*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::v16f32, MVT::v16i32);
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::i64, Promote);
87*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::i64, MVT::v2i32);
88*9880d681SAndroid Build Coastguard Worker
89*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::v2i64, Promote);
90*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::v2i64, MVT::v4i32);
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::f64, Promote);
93*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::f64, MVT::v2i32);
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::LOAD, MVT::v2f64, Promote);
96*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::LOAD, MVT::v2f64, MVT::v4i32);
97*9880d681SAndroid Build Coastguard Worker
98*9880d681SAndroid Build Coastguard Worker // There are no 64-bit extloads. These should be done as a 32-bit extload and
99*9880d681SAndroid Build Coastguard Worker // an extension to 64-bit.
100*9880d681SAndroid Build Coastguard Worker for (MVT VT : MVT::integer_valuetypes()) {
101*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::i64, VT, Expand);
102*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, MVT::i64, VT, Expand);
103*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, MVT::i64, VT, Expand);
104*9880d681SAndroid Build Coastguard Worker }
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker for (MVT VT : MVT::integer_valuetypes()) {
107*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i64)
108*9880d681SAndroid Build Coastguard Worker continue;
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
111*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Legal);
112*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i16, Legal);
113*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i32, Expand);
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
116*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i8, Legal);
117*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i16, Legal);
118*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i32, Expand);
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
121*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::i8, Legal);
122*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::i16, Legal);
123*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::i32, Expand);
124*9880d681SAndroid Build Coastguard Worker }
125*9880d681SAndroid Build Coastguard Worker
126*9880d681SAndroid Build Coastguard Worker for (MVT VT : MVT::integer_vector_valuetypes()) {
127*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::v2i8, Expand);
128*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v2i8, Expand);
129*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v2i8, Expand);
130*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::v4i8, Expand);
131*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v4i8, Expand);
132*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v4i8, Expand);
133*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::v2i16, Expand);
134*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v2i16, Expand);
135*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v2i16, Expand);
136*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, VT, MVT::v4i16, Expand);
137*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::SEXTLOAD, VT, MVT::v4i16, Expand);
138*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::v4i16, Expand);
139*9880d681SAndroid Build Coastguard Worker }
140*9880d681SAndroid Build Coastguard Worker
141*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
142*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v2f32, MVT::v2f16, Expand);
143*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v4f32, MVT::v4f16, Expand);
144*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v8f32, MVT::v8f16, Expand);
145*9880d681SAndroid Build Coastguard Worker
146*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
147*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2f32, Expand);
148*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v4f64, MVT::v4f32, Expand);
149*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v8f64, MVT::v8f32, Expand);
150*9880d681SAndroid Build Coastguard Worker
151*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
152*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2f16, Expand);
153*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v4f64, MVT::v4f16, Expand);
154*9880d681SAndroid Build Coastguard Worker setLoadExtAction(ISD::EXTLOAD, MVT::v8f64, MVT::v8f16, Expand);
155*9880d681SAndroid Build Coastguard Worker
156*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::f32, Promote);
157*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::f32, MVT::i32);
158*9880d681SAndroid Build Coastguard Worker
159*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::v2f32, Promote);
160*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::v2f32, MVT::v2i32);
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::v4f32, Promote);
163*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::v4f32, MVT::v4i32);
164*9880d681SAndroid Build Coastguard Worker
165*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::v8f32, Promote);
166*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::v8f32, MVT::v8i32);
167*9880d681SAndroid Build Coastguard Worker
168*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::v16f32, Promote);
169*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::v16f32, MVT::v16i32);
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::i64, Promote);
172*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::i64, MVT::v2i32);
173*9880d681SAndroid Build Coastguard Worker
174*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::v2i64, Promote);
175*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::v2i64, MVT::v4i32);
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::f64, Promote);
178*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::f64, MVT::v2i32);
179*9880d681SAndroid Build Coastguard Worker
180*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::STORE, MVT::v2f64, Promote);
181*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::STORE, MVT::v2f64, MVT::v4i32);
182*9880d681SAndroid Build Coastguard Worker
183*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2i32, MVT::v2i8, Custom);
184*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2i32, MVT::v2i16, Custom);
185*9880d681SAndroid Build Coastguard Worker
186*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v4i32, MVT::v4i8, Custom);
187*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v4i32, MVT::v4i16, Expand);
188*9880d681SAndroid Build Coastguard Worker
189*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v8i32, MVT::v8i16, Expand);
190*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v16i32, MVT::v16i8, Expand);
191*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v16i32, MVT::v16i16, Expand);
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::i64, MVT::i1, Expand);
194*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::i64, MVT::i8, Expand);
195*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::i64, MVT::i16, Expand);
196*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::i64, MVT::i32, Expand);
197*9880d681SAndroid Build Coastguard Worker
198*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2i64, MVT::v2i1, Expand);
199*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2i64, MVT::v2i8, Expand);
200*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2i64, MVT::v2i16, Expand);
201*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2i64, MVT::v2i32, Expand);
202*9880d681SAndroid Build Coastguard Worker
203*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::f32, MVT::f16, Expand);
204*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2f32, MVT::v2f16, Expand);
205*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v4f32, MVT::v4f16, Expand);
206*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v8f32, MVT::v8f16, Expand);
207*9880d681SAndroid Build Coastguard Worker
208*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::f64, MVT::f16, Expand);
209*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::f64, MVT::f32, Expand);
210*9880d681SAndroid Build Coastguard Worker
211*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2f64, MVT::v2f32, Expand);
212*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v2f64, MVT::v2f16, Expand);
213*9880d681SAndroid Build Coastguard Worker
214*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v4f64, MVT::v4f32, Expand);
215*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v4f64, MVT::v4f16, Expand);
216*9880d681SAndroid Build Coastguard Worker
217*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v8f64, MVT::v8f32, Expand);
218*9880d681SAndroid Build Coastguard Worker setTruncStoreAction(MVT::v8f64, MVT::v8f16, Expand);
219*9880d681SAndroid Build Coastguard Worker
220*9880d681SAndroid Build Coastguard Worker
221*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::Constant, MVT::i32, Legal);
222*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::Constant, MVT::i64, Legal);
223*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
224*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ConstantFP, MVT::f64, Legal);
225*9880d681SAndroid Build Coastguard Worker
226*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BR_JT, MVT::Other, Expand);
227*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BRIND, MVT::Other, Expand);
228*9880d681SAndroid Build Coastguard Worker
229*9880d681SAndroid Build Coastguard Worker // This is totally unsupported, just custom lower to produce an error.
230*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Custom);
231*9880d681SAndroid Build Coastguard Worker
232*9880d681SAndroid Build Coastguard Worker // We need to custom lower some of the intrinsics
233*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
234*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
235*9880d681SAndroid Build Coastguard Worker
236*9880d681SAndroid Build Coastguard Worker // Library functions. These default to Expand, but we have instructions
237*9880d681SAndroid Build Coastguard Worker // for them.
238*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCEIL, MVT::f32, Legal);
239*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FEXP2, MVT::f32, Legal);
240*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FPOW, MVT::f32, Legal);
241*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FLOG2, MVT::f32, Legal);
242*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FABS, MVT::f32, Legal);
243*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FFLOOR, MVT::f32, Legal);
244*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FRINT, MVT::f32, Legal);
245*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FTRUNC, MVT::f32, Legal);
246*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMINNUM, MVT::f32, Legal);
247*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMAXNUM, MVT::f32, Legal);
248*9880d681SAndroid Build Coastguard Worker
249*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FROUND, MVT::f32, Custom);
250*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FROUND, MVT::f64, Custom);
251*9880d681SAndroid Build Coastguard Worker
252*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FNEARBYINT, MVT::f32, Custom);
253*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FNEARBYINT, MVT::f64, Custom);
254*9880d681SAndroid Build Coastguard Worker
255*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FREM, MVT::f32, Custom);
256*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FREM, MVT::f64, Custom);
257*9880d681SAndroid Build Coastguard Worker
258*9880d681SAndroid Build Coastguard Worker // v_mad_f32 does not support denormals according to some sources.
259*9880d681SAndroid Build Coastguard Worker if (!Subtarget->hasFP32Denormals())
260*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMAD, MVT::f32, Legal);
261*9880d681SAndroid Build Coastguard Worker
262*9880d681SAndroid Build Coastguard Worker // Expand to fneg + fadd.
263*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSUB, MVT::f64, Expand);
264*9880d681SAndroid Build Coastguard Worker
265*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CONCAT_VECTORS, MVT::v4i32, Custom);
266*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CONCAT_VECTORS, MVT::v4f32, Custom);
267*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CONCAT_VECTORS, MVT::v8i32, Custom);
268*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CONCAT_VECTORS, MVT::v8f32, Custom);
269*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v2f32, Custom);
270*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v2i32, Custom);
271*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v4f32, Custom);
272*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v4i32, Custom);
273*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v8f32, Custom);
274*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::EXTRACT_SUBVECTOR, MVT::v8i32, Custom);
275*9880d681SAndroid Build Coastguard Worker
276*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() < AMDGPUSubtarget::SEA_ISLANDS) {
277*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCEIL, MVT::f64, Custom);
278*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FTRUNC, MVT::f64, Custom);
279*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FRINT, MVT::f64, Custom);
280*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FFLOOR, MVT::f64, Custom);
281*9880d681SAndroid Build Coastguard Worker }
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker if (!Subtarget->hasBFI()) {
284*9880d681SAndroid Build Coastguard Worker // fcopysign can be done in a single instruction with BFI.
285*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
286*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
287*9880d681SAndroid Build Coastguard Worker }
288*9880d681SAndroid Build Coastguard Worker
289*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand);
290*9880d681SAndroid Build Coastguard Worker
291*9880d681SAndroid Build Coastguard Worker const MVT ScalarIntVTs[] = { MVT::i32, MVT::i64 };
292*9880d681SAndroid Build Coastguard Worker for (MVT VT : ScalarIntVTs) {
293*9880d681SAndroid Build Coastguard Worker // These should use [SU]DIVREM, so set them to expand
294*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SDIV, VT, Expand);
295*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UDIV, VT, Expand);
296*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SREM, VT, Expand);
297*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UREM, VT, Expand);
298*9880d681SAndroid Build Coastguard Worker
299*9880d681SAndroid Build Coastguard Worker // GPU does not have divrem function for signed or unsigned.
300*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SDIVREM, VT, Custom);
301*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UDIVREM, VT, Custom);
302*9880d681SAndroid Build Coastguard Worker
303*9880d681SAndroid Build Coastguard Worker // GPU does not have [S|U]MUL_LOHI functions as a single instruction.
304*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SMUL_LOHI, VT, Expand);
305*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UMUL_LOHI, VT, Expand);
306*9880d681SAndroid Build Coastguard Worker
307*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BSWAP, VT, Expand);
308*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTTZ, VT, Expand);
309*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTLZ, VT, Expand);
310*9880d681SAndroid Build Coastguard Worker }
311*9880d681SAndroid Build Coastguard Worker
312*9880d681SAndroid Build Coastguard Worker if (!Subtarget->hasBCNT(32))
313*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTPOP, MVT::i32, Expand);
314*9880d681SAndroid Build Coastguard Worker
315*9880d681SAndroid Build Coastguard Worker if (!Subtarget->hasBCNT(64))
316*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTPOP, MVT::i64, Expand);
317*9880d681SAndroid Build Coastguard Worker
318*9880d681SAndroid Build Coastguard Worker // The hardware supports 32-bit ROTR, but not ROTL.
319*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTL, MVT::i32, Expand);
320*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTL, MVT::i64, Expand);
321*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTR, MVT::i64, Expand);
322*9880d681SAndroid Build Coastguard Worker
323*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::MUL, MVT::i64, Expand);
324*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::MULHU, MVT::i64, Expand);
325*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::MULHS, MVT::i64, Expand);
326*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UDIV, MVT::i32, Expand);
327*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UREM, MVT::i32, Expand);
328*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UINT_TO_FP, MVT::i64, Custom);
329*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
330*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
331*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_UINT, MVT::i64, Custom);
332*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
333*9880d681SAndroid Build Coastguard Worker
334*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SMIN, MVT::i32, Legal);
335*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UMIN, MVT::i32, Legal);
336*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SMAX, MVT::i32, Legal);
337*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UMAX, MVT::i32, Legal);
338*9880d681SAndroid Build Coastguard Worker
339*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasFFBH())
340*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Custom);
341*9880d681SAndroid Build Coastguard Worker
342*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasFFBL())
343*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Legal);
344*9880d681SAndroid Build Coastguard Worker
345*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTLZ, MVT::i64, Custom);
346*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Custom);
347*9880d681SAndroid Build Coastguard Worker
348*9880d681SAndroid Build Coastguard Worker // We only really have 32-bit BFE instructions (and 16-bit on VI).
349*9880d681SAndroid Build Coastguard Worker //
350*9880d681SAndroid Build Coastguard Worker // On SI+ there are 64-bit BFEs, but they are scalar only and there isn't any
351*9880d681SAndroid Build Coastguard Worker // effort to match them now. We want this to be false for i64 cases when the
352*9880d681SAndroid Build Coastguard Worker // extraction isn't restricted to the upper or lower half. Ideally we would
353*9880d681SAndroid Build Coastguard Worker // have some pass reduce 64-bit extracts to 32-bit if possible. Extracts that
354*9880d681SAndroid Build Coastguard Worker // span the midpoint are probably relatively rare, so don't worry about them
355*9880d681SAndroid Build Coastguard Worker // for now.
356*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasBFE())
357*9880d681SAndroid Build Coastguard Worker setHasExtractBitsInsn(true);
358*9880d681SAndroid Build Coastguard Worker
359*9880d681SAndroid Build Coastguard Worker static const MVT::SimpleValueType VectorIntTypes[] = {
360*9880d681SAndroid Build Coastguard Worker MVT::v2i32, MVT::v4i32
361*9880d681SAndroid Build Coastguard Worker };
362*9880d681SAndroid Build Coastguard Worker
363*9880d681SAndroid Build Coastguard Worker for (MVT VT : VectorIntTypes) {
364*9880d681SAndroid Build Coastguard Worker // Expand the following operations for the current type by default.
365*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ADD, VT, Expand);
366*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::AND, VT, Expand);
367*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_SINT, VT, Expand);
368*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FP_TO_UINT, VT, Expand);
369*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::MUL, VT, Expand);
370*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::OR, VT, Expand);
371*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SHL, VT, Expand);
372*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SRA, VT, Expand);
373*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SRL, VT, Expand);
374*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTL, VT, Expand);
375*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ROTR, VT, Expand);
376*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SUB, VT, Expand);
377*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SINT_TO_FP, VT, Expand);
378*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UINT_TO_FP, VT, Expand);
379*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SDIV, VT, Expand);
380*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UDIV, VT, Expand);
381*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SREM, VT, Expand);
382*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UREM, VT, Expand);
383*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SMUL_LOHI, VT, Expand);
384*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UMUL_LOHI, VT, Expand);
385*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SDIVREM, VT, Custom);
386*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::UDIVREM, VT, Expand);
387*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ADDC, VT, Expand);
388*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SUBC, VT, Expand);
389*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::ADDE, VT, Expand);
390*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SUBE, VT, Expand);
391*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, VT, Expand);
392*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::VSELECT, VT, Expand);
393*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, VT, Expand);
394*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::XOR, VT, Expand);
395*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::BSWAP, VT, Expand);
396*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTPOP, VT, Expand);
397*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTTZ, VT, Expand);
398*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::CTLZ, VT, Expand);
399*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::VECTOR_SHUFFLE, VT, Expand);
400*9880d681SAndroid Build Coastguard Worker }
401*9880d681SAndroid Build Coastguard Worker
402*9880d681SAndroid Build Coastguard Worker static const MVT::SimpleValueType FloatVectorTypes[] = {
403*9880d681SAndroid Build Coastguard Worker MVT::v2f32, MVT::v4f32
404*9880d681SAndroid Build Coastguard Worker };
405*9880d681SAndroid Build Coastguard Worker
406*9880d681SAndroid Build Coastguard Worker for (MVT VT : FloatVectorTypes) {
407*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FABS, VT, Expand);
408*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMINNUM, VT, Expand);
409*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMAXNUM, VT, Expand);
410*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FADD, VT, Expand);
411*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCEIL, VT, Expand);
412*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOS, VT, Expand);
413*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FDIV, VT, Expand);
414*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FEXP2, VT, Expand);
415*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FLOG2, VT, Expand);
416*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FREM, VT, Expand);
417*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FPOW, VT, Expand);
418*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FFLOOR, VT, Expand);
419*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FTRUNC, VT, Expand);
420*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMUL, VT, Expand);
421*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FMA, VT, Expand);
422*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FRINT, VT, Expand);
423*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FNEARBYINT, VT, Expand);
424*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSQRT, VT, Expand);
425*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSIN, VT, Expand);
426*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FSUB, VT, Expand);
427*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FNEG, VT, Expand);
428*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::VSELECT, VT, Expand);
429*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT_CC, VT, Expand);
430*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::FCOPYSIGN, VT, Expand);
431*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::VECTOR_SHUFFLE, VT, Expand);
432*9880d681SAndroid Build Coastguard Worker }
433*9880d681SAndroid Build Coastguard Worker
434*9880d681SAndroid Build Coastguard Worker // This causes using an unrolled select operation rather than expansion with
435*9880d681SAndroid Build Coastguard Worker // bit operations. This is in general better, but the alternative using BFI
436*9880d681SAndroid Build Coastguard Worker // instructions may be better if the select sources are SGPRs.
437*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::v2f32, Promote);
438*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::SELECT, MVT::v2f32, MVT::v2i32);
439*9880d681SAndroid Build Coastguard Worker
440*9880d681SAndroid Build Coastguard Worker setOperationAction(ISD::SELECT, MVT::v4f32, Promote);
441*9880d681SAndroid Build Coastguard Worker AddPromotedToType(ISD::SELECT, MVT::v4f32, MVT::v4i32);
442*9880d681SAndroid Build Coastguard Worker
443*9880d681SAndroid Build Coastguard Worker setBooleanContents(ZeroOrNegativeOneBooleanContent);
444*9880d681SAndroid Build Coastguard Worker setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
445*9880d681SAndroid Build Coastguard Worker
446*9880d681SAndroid Build Coastguard Worker setSchedulingPreference(Sched::RegPressure);
447*9880d681SAndroid Build Coastguard Worker setJumpIsExpensive(true);
448*9880d681SAndroid Build Coastguard Worker
449*9880d681SAndroid Build Coastguard Worker // SI at least has hardware support for floating point exceptions, but no way
450*9880d681SAndroid Build Coastguard Worker // of using or handling them is implemented. They are also optional in OpenCL
451*9880d681SAndroid Build Coastguard Worker // (Section 7.3)
452*9880d681SAndroid Build Coastguard Worker setHasFloatingPointExceptions(Subtarget->hasFPExceptions());
453*9880d681SAndroid Build Coastguard Worker
454*9880d681SAndroid Build Coastguard Worker setSelectIsExpensive(false);
455*9880d681SAndroid Build Coastguard Worker PredictableSelectIsExpensive = false;
456*9880d681SAndroid Build Coastguard Worker
457*9880d681SAndroid Build Coastguard Worker setFsqrtIsCheap(true);
458*9880d681SAndroid Build Coastguard Worker
459*9880d681SAndroid Build Coastguard Worker // We want to find all load dependencies for long chains of stores to enable
460*9880d681SAndroid Build Coastguard Worker // merging into very wide vectors. The problem is with vectors with > 4
461*9880d681SAndroid Build Coastguard Worker // elements. MergeConsecutiveStores will attempt to merge these because x8/x16
462*9880d681SAndroid Build Coastguard Worker // vectors are a legal type, even though we have to split the loads
463*9880d681SAndroid Build Coastguard Worker // usually. When we can more precisely specify load legality per address
464*9880d681SAndroid Build Coastguard Worker // space, we should be able to make FindBetterChain/MergeConsecutiveStores
465*9880d681SAndroid Build Coastguard Worker // smarter so that they can figure out what to do in 2 iterations without all
466*9880d681SAndroid Build Coastguard Worker // N > 4 stores on the same chain.
467*9880d681SAndroid Build Coastguard Worker GatherAllAliasesMaxDepth = 16;
468*9880d681SAndroid Build Coastguard Worker
469*9880d681SAndroid Build Coastguard Worker // FIXME: Need to really handle these.
470*9880d681SAndroid Build Coastguard Worker MaxStoresPerMemcpy = 4096;
471*9880d681SAndroid Build Coastguard Worker MaxStoresPerMemmove = 4096;
472*9880d681SAndroid Build Coastguard Worker MaxStoresPerMemset = 4096;
473*9880d681SAndroid Build Coastguard Worker
474*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::BITCAST);
475*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::AND);
476*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::SHL);
477*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::SRA);
478*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::SRL);
479*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::MUL);
480*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::SELECT);
481*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::SELECT_CC);
482*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::STORE);
483*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::FADD);
484*9880d681SAndroid Build Coastguard Worker setTargetDAGCombine(ISD::FSUB);
485*9880d681SAndroid Build Coastguard Worker }
486*9880d681SAndroid Build Coastguard Worker
487*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
488*9880d681SAndroid Build Coastguard Worker // Target Information
489*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
490*9880d681SAndroid Build Coastguard Worker
getVectorIdxTy(const DataLayout &) const491*9880d681SAndroid Build Coastguard Worker MVT AMDGPUTargetLowering::getVectorIdxTy(const DataLayout &) const {
492*9880d681SAndroid Build Coastguard Worker return MVT::i32;
493*9880d681SAndroid Build Coastguard Worker }
494*9880d681SAndroid Build Coastguard Worker
isSelectSupported(SelectSupportKind SelType) const495*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isSelectSupported(SelectSupportKind SelType) const {
496*9880d681SAndroid Build Coastguard Worker return true;
497*9880d681SAndroid Build Coastguard Worker }
498*9880d681SAndroid Build Coastguard Worker
499*9880d681SAndroid Build Coastguard Worker // The backend supports 32 and 64 bit floating point immediates.
500*9880d681SAndroid Build Coastguard Worker // FIXME: Why are we reporting vectors of FP immediates as legal?
isFPImmLegal(const APFloat & Imm,EVT VT) const501*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
502*9880d681SAndroid Build Coastguard Worker EVT ScalarVT = VT.getScalarType();
503*9880d681SAndroid Build Coastguard Worker return (ScalarVT == MVT::f32 || ScalarVT == MVT::f64);
504*9880d681SAndroid Build Coastguard Worker }
505*9880d681SAndroid Build Coastguard Worker
506*9880d681SAndroid Build Coastguard Worker // We don't want to shrink f64 / f32 constants.
ShouldShrinkFPConstant(EVT VT) const507*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::ShouldShrinkFPConstant(EVT VT) const {
508*9880d681SAndroid Build Coastguard Worker EVT ScalarVT = VT.getScalarType();
509*9880d681SAndroid Build Coastguard Worker return (ScalarVT != MVT::f32 && ScalarVT != MVT::f64);
510*9880d681SAndroid Build Coastguard Worker }
511*9880d681SAndroid Build Coastguard Worker
shouldReduceLoadWidth(SDNode * N,ISD::LoadExtType,EVT NewVT) const512*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::shouldReduceLoadWidth(SDNode *N,
513*9880d681SAndroid Build Coastguard Worker ISD::LoadExtType,
514*9880d681SAndroid Build Coastguard Worker EVT NewVT) const {
515*9880d681SAndroid Build Coastguard Worker
516*9880d681SAndroid Build Coastguard Worker unsigned NewSize = NewVT.getStoreSizeInBits();
517*9880d681SAndroid Build Coastguard Worker
518*9880d681SAndroid Build Coastguard Worker // If we are reducing to a 32-bit load, this is always better.
519*9880d681SAndroid Build Coastguard Worker if (NewSize == 32)
520*9880d681SAndroid Build Coastguard Worker return true;
521*9880d681SAndroid Build Coastguard Worker
522*9880d681SAndroid Build Coastguard Worker EVT OldVT = N->getValueType(0);
523*9880d681SAndroid Build Coastguard Worker unsigned OldSize = OldVT.getStoreSizeInBits();
524*9880d681SAndroid Build Coastguard Worker
525*9880d681SAndroid Build Coastguard Worker // Don't produce extloads from sub 32-bit types. SI doesn't have scalar
526*9880d681SAndroid Build Coastguard Worker // extloads, so doing one requires using a buffer_load. In cases where we
527*9880d681SAndroid Build Coastguard Worker // still couldn't use a scalar load, using the wider load shouldn't really
528*9880d681SAndroid Build Coastguard Worker // hurt anything.
529*9880d681SAndroid Build Coastguard Worker
530*9880d681SAndroid Build Coastguard Worker // If the old size already had to be an extload, there's no harm in continuing
531*9880d681SAndroid Build Coastguard Worker // to reduce the width.
532*9880d681SAndroid Build Coastguard Worker return (OldSize < 32);
533*9880d681SAndroid Build Coastguard Worker }
534*9880d681SAndroid Build Coastguard Worker
isLoadBitCastBeneficial(EVT LoadTy,EVT CastTy) const535*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isLoadBitCastBeneficial(EVT LoadTy,
536*9880d681SAndroid Build Coastguard Worker EVT CastTy) const {
537*9880d681SAndroid Build Coastguard Worker
538*9880d681SAndroid Build Coastguard Worker assert(LoadTy.getSizeInBits() == CastTy.getSizeInBits());
539*9880d681SAndroid Build Coastguard Worker
540*9880d681SAndroid Build Coastguard Worker if (LoadTy.getScalarType() == MVT::i32)
541*9880d681SAndroid Build Coastguard Worker return false;
542*9880d681SAndroid Build Coastguard Worker
543*9880d681SAndroid Build Coastguard Worker unsigned LScalarSize = LoadTy.getScalarSizeInBits();
544*9880d681SAndroid Build Coastguard Worker unsigned CastScalarSize = CastTy.getScalarSizeInBits();
545*9880d681SAndroid Build Coastguard Worker
546*9880d681SAndroid Build Coastguard Worker return (LScalarSize < CastScalarSize) ||
547*9880d681SAndroid Build Coastguard Worker (CastScalarSize >= 32);
548*9880d681SAndroid Build Coastguard Worker }
549*9880d681SAndroid Build Coastguard Worker
550*9880d681SAndroid Build Coastguard Worker // SI+ has instructions for cttz / ctlz for 32-bit values. This is probably also
551*9880d681SAndroid Build Coastguard Worker // profitable with the expansion for 64-bit since it's generally good to
552*9880d681SAndroid Build Coastguard Worker // speculate things.
553*9880d681SAndroid Build Coastguard Worker // FIXME: These should really have the size as a parameter.
isCheapToSpeculateCttz() const554*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isCheapToSpeculateCttz() const {
555*9880d681SAndroid Build Coastguard Worker return true;
556*9880d681SAndroid Build Coastguard Worker }
557*9880d681SAndroid Build Coastguard Worker
isCheapToSpeculateCtlz() const558*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isCheapToSpeculateCtlz() const {
559*9880d681SAndroid Build Coastguard Worker return true;
560*9880d681SAndroid Build Coastguard Worker }
561*9880d681SAndroid Build Coastguard Worker
562*9880d681SAndroid Build Coastguard Worker //===---------------------------------------------------------------------===//
563*9880d681SAndroid Build Coastguard Worker // Target Properties
564*9880d681SAndroid Build Coastguard Worker //===---------------------------------------------------------------------===//
565*9880d681SAndroid Build Coastguard Worker
isFAbsFree(EVT VT) const566*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isFAbsFree(EVT VT) const {
567*9880d681SAndroid Build Coastguard Worker assert(VT.isFloatingPoint());
568*9880d681SAndroid Build Coastguard Worker return VT == MVT::f32 || VT == MVT::f64;
569*9880d681SAndroid Build Coastguard Worker }
570*9880d681SAndroid Build Coastguard Worker
isFNegFree(EVT VT) const571*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isFNegFree(EVT VT) const {
572*9880d681SAndroid Build Coastguard Worker assert(VT.isFloatingPoint());
573*9880d681SAndroid Build Coastguard Worker return VT == MVT::f32 || VT == MVT::f64;
574*9880d681SAndroid Build Coastguard Worker }
575*9880d681SAndroid Build Coastguard Worker
storeOfVectorConstantIsCheap(EVT MemVT,unsigned NumElem,unsigned AS) const576*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering:: storeOfVectorConstantIsCheap(EVT MemVT,
577*9880d681SAndroid Build Coastguard Worker unsigned NumElem,
578*9880d681SAndroid Build Coastguard Worker unsigned AS) const {
579*9880d681SAndroid Build Coastguard Worker return true;
580*9880d681SAndroid Build Coastguard Worker }
581*9880d681SAndroid Build Coastguard Worker
aggressivelyPreferBuildVectorSources(EVT VecVT) const582*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::aggressivelyPreferBuildVectorSources(EVT VecVT) const {
583*9880d681SAndroid Build Coastguard Worker // There are few operations which truly have vector input operands. Any vector
584*9880d681SAndroid Build Coastguard Worker // operation is going to involve operations on each component, and a
585*9880d681SAndroid Build Coastguard Worker // build_vector will be a copy per element, so it always makes sense to use a
586*9880d681SAndroid Build Coastguard Worker // build_vector input in place of the extracted element to avoid a copy into a
587*9880d681SAndroid Build Coastguard Worker // super register.
588*9880d681SAndroid Build Coastguard Worker //
589*9880d681SAndroid Build Coastguard Worker // We should probably only do this if all users are extracts only, but this
590*9880d681SAndroid Build Coastguard Worker // should be the common case.
591*9880d681SAndroid Build Coastguard Worker return true;
592*9880d681SAndroid Build Coastguard Worker }
593*9880d681SAndroid Build Coastguard Worker
isTruncateFree(EVT Source,EVT Dest) const594*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isTruncateFree(EVT Source, EVT Dest) const {
595*9880d681SAndroid Build Coastguard Worker // Truncate is just accessing a subregister.
596*9880d681SAndroid Build Coastguard Worker return Dest.bitsLT(Source) && (Dest.getSizeInBits() % 32 == 0);
597*9880d681SAndroid Build Coastguard Worker }
598*9880d681SAndroid Build Coastguard Worker
isTruncateFree(Type * Source,Type * Dest) const599*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isTruncateFree(Type *Source, Type *Dest) const {
600*9880d681SAndroid Build Coastguard Worker // Truncate is just accessing a subregister.
601*9880d681SAndroid Build Coastguard Worker return Dest->getPrimitiveSizeInBits() < Source->getPrimitiveSizeInBits() &&
602*9880d681SAndroid Build Coastguard Worker (Dest->getPrimitiveSizeInBits() % 32 == 0);
603*9880d681SAndroid Build Coastguard Worker }
604*9880d681SAndroid Build Coastguard Worker
isZExtFree(Type * Src,Type * Dest) const605*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isZExtFree(Type *Src, Type *Dest) const {
606*9880d681SAndroid Build Coastguard Worker unsigned SrcSize = Src->getScalarSizeInBits();
607*9880d681SAndroid Build Coastguard Worker unsigned DestSize = Dest->getScalarSizeInBits();
608*9880d681SAndroid Build Coastguard Worker
609*9880d681SAndroid Build Coastguard Worker return SrcSize == 32 && DestSize == 64;
610*9880d681SAndroid Build Coastguard Worker }
611*9880d681SAndroid Build Coastguard Worker
isZExtFree(EVT Src,EVT Dest) const612*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isZExtFree(EVT Src, EVT Dest) const {
613*9880d681SAndroid Build Coastguard Worker // Any register load of a 64-bit value really requires 2 32-bit moves. For all
614*9880d681SAndroid Build Coastguard Worker // practical purposes, the extra mov 0 to load a 64-bit is free. As used,
615*9880d681SAndroid Build Coastguard Worker // this will enable reducing 64-bit operations the 32-bit, which is always
616*9880d681SAndroid Build Coastguard Worker // good.
617*9880d681SAndroid Build Coastguard Worker return Src == MVT::i32 && Dest == MVT::i64;
618*9880d681SAndroid Build Coastguard Worker }
619*9880d681SAndroid Build Coastguard Worker
isZExtFree(SDValue Val,EVT VT2) const620*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isZExtFree(SDValue Val, EVT VT2) const {
621*9880d681SAndroid Build Coastguard Worker return isZExtFree(Val.getValueType(), VT2);
622*9880d681SAndroid Build Coastguard Worker }
623*9880d681SAndroid Build Coastguard Worker
isNarrowingProfitable(EVT SrcVT,EVT DestVT) const624*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::isNarrowingProfitable(EVT SrcVT, EVT DestVT) const {
625*9880d681SAndroid Build Coastguard Worker // There aren't really 64-bit registers, but pairs of 32-bit ones and only a
626*9880d681SAndroid Build Coastguard Worker // limited number of native 64-bit operations. Shrinking an operation to fit
627*9880d681SAndroid Build Coastguard Worker // in a single 32-bit register should always be helpful. As currently used,
628*9880d681SAndroid Build Coastguard Worker // this is much less general than the name suggests, and is only used in
629*9880d681SAndroid Build Coastguard Worker // places trying to reduce the sizes of loads. Shrinking loads to < 32-bits is
630*9880d681SAndroid Build Coastguard Worker // not profitable, and may actually be harmful.
631*9880d681SAndroid Build Coastguard Worker return SrcVT.getSizeInBits() > 32 && DestVT.getSizeInBits() == 32;
632*9880d681SAndroid Build Coastguard Worker }
633*9880d681SAndroid Build Coastguard Worker
634*9880d681SAndroid Build Coastguard Worker //===---------------------------------------------------------------------===//
635*9880d681SAndroid Build Coastguard Worker // TargetLowering Callbacks
636*9880d681SAndroid Build Coastguard Worker //===---------------------------------------------------------------------===//
637*9880d681SAndroid Build Coastguard Worker
AnalyzeFormalArguments(CCState & State,const SmallVectorImpl<ISD::InputArg> & Ins) const638*9880d681SAndroid Build Coastguard Worker void AMDGPUTargetLowering::AnalyzeFormalArguments(CCState &State,
639*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::InputArg> &Ins) const {
640*9880d681SAndroid Build Coastguard Worker
641*9880d681SAndroid Build Coastguard Worker State.AnalyzeFormalArguments(Ins, CC_AMDGPU);
642*9880d681SAndroid Build Coastguard Worker }
643*9880d681SAndroid Build Coastguard Worker
AnalyzeReturn(CCState & State,const SmallVectorImpl<ISD::OutputArg> & Outs) const644*9880d681SAndroid Build Coastguard Worker void AMDGPUTargetLowering::AnalyzeReturn(CCState &State,
645*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::OutputArg> &Outs) const {
646*9880d681SAndroid Build Coastguard Worker
647*9880d681SAndroid Build Coastguard Worker State.AnalyzeReturn(Outs, RetCC_SI);
648*9880d681SAndroid Build Coastguard Worker }
649*9880d681SAndroid Build Coastguard Worker
650*9880d681SAndroid Build Coastguard Worker SDValue
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool isVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const651*9880d681SAndroid Build Coastguard Worker AMDGPUTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
652*9880d681SAndroid Build Coastguard Worker bool isVarArg,
653*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::OutputArg> &Outs,
654*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<SDValue> &OutVals,
655*9880d681SAndroid Build Coastguard Worker const SDLoc &DL, SelectionDAG &DAG) const {
656*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::ENDPGM, DL, MVT::Other, Chain);
657*9880d681SAndroid Build Coastguard Worker }
658*9880d681SAndroid Build Coastguard Worker
659*9880d681SAndroid Build Coastguard Worker //===---------------------------------------------------------------------===//
660*9880d681SAndroid Build Coastguard Worker // Target specific lowering
661*9880d681SAndroid Build Coastguard Worker //===---------------------------------------------------------------------===//
662*9880d681SAndroid Build Coastguard Worker
LowerCall(CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const663*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerCall(CallLoweringInfo &CLI,
664*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &InVals) const {
665*9880d681SAndroid Build Coastguard Worker SDValue Callee = CLI.Callee;
666*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = CLI.DAG;
667*9880d681SAndroid Build Coastguard Worker
668*9880d681SAndroid Build Coastguard Worker const Function &Fn = *DAG.getMachineFunction().getFunction();
669*9880d681SAndroid Build Coastguard Worker
670*9880d681SAndroid Build Coastguard Worker StringRef FuncName("<unknown>");
671*9880d681SAndroid Build Coastguard Worker
672*9880d681SAndroid Build Coastguard Worker if (const ExternalSymbolSDNode *G = dyn_cast<ExternalSymbolSDNode>(Callee))
673*9880d681SAndroid Build Coastguard Worker FuncName = G->getSymbol();
674*9880d681SAndroid Build Coastguard Worker else if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
675*9880d681SAndroid Build Coastguard Worker FuncName = G->getGlobal()->getName();
676*9880d681SAndroid Build Coastguard Worker
677*9880d681SAndroid Build Coastguard Worker DiagnosticInfoUnsupported NoCalls(
678*9880d681SAndroid Build Coastguard Worker Fn, "unsupported call to function " + FuncName, CLI.DL.getDebugLoc());
679*9880d681SAndroid Build Coastguard Worker DAG.getContext()->diagnose(NoCalls);
680*9880d681SAndroid Build Coastguard Worker
681*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0, E = CLI.Ins.size(); I != E; ++I)
682*9880d681SAndroid Build Coastguard Worker InVals.push_back(DAG.getUNDEF(CLI.Ins[I].VT));
683*9880d681SAndroid Build Coastguard Worker
684*9880d681SAndroid Build Coastguard Worker return DAG.getEntryNode();
685*9880d681SAndroid Build Coastguard Worker }
686*9880d681SAndroid Build Coastguard Worker
LowerDYNAMIC_STACKALLOC(SDValue Op,SelectionDAG & DAG) const687*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
688*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
689*9880d681SAndroid Build Coastguard Worker const Function &Fn = *DAG.getMachineFunction().getFunction();
690*9880d681SAndroid Build Coastguard Worker
691*9880d681SAndroid Build Coastguard Worker DiagnosticInfoUnsupported NoDynamicAlloca(Fn, "unsupported dynamic alloca",
692*9880d681SAndroid Build Coastguard Worker SDLoc(Op).getDebugLoc());
693*9880d681SAndroid Build Coastguard Worker DAG.getContext()->diagnose(NoDynamicAlloca);
694*9880d681SAndroid Build Coastguard Worker auto Ops = {DAG.getConstant(0, SDLoc(), Op.getValueType()), Op.getOperand(0)};
695*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, SDLoc());
696*9880d681SAndroid Build Coastguard Worker }
697*9880d681SAndroid Build Coastguard Worker
LowerOperation(SDValue Op,SelectionDAG & DAG) const698*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerOperation(SDValue Op,
699*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
700*9880d681SAndroid Build Coastguard Worker switch (Op.getOpcode()) {
701*9880d681SAndroid Build Coastguard Worker default:
702*9880d681SAndroid Build Coastguard Worker Op->dump(&DAG);
703*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Custom lowering code for this"
704*9880d681SAndroid Build Coastguard Worker "instruction is not implemented yet!");
705*9880d681SAndroid Build Coastguard Worker break;
706*9880d681SAndroid Build Coastguard Worker case ISD::SIGN_EXTEND_INREG: return LowerSIGN_EXTEND_INREG(Op, DAG);
707*9880d681SAndroid Build Coastguard Worker case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
708*9880d681SAndroid Build Coastguard Worker case ISD::EXTRACT_SUBVECTOR: return LowerEXTRACT_SUBVECTOR(Op, DAG);
709*9880d681SAndroid Build Coastguard Worker case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
710*9880d681SAndroid Build Coastguard Worker case ISD::UDIVREM: return LowerUDIVREM(Op, DAG);
711*9880d681SAndroid Build Coastguard Worker case ISD::SDIVREM: return LowerSDIVREM(Op, DAG);
712*9880d681SAndroid Build Coastguard Worker case ISD::FREM: return LowerFREM(Op, DAG);
713*9880d681SAndroid Build Coastguard Worker case ISD::FCEIL: return LowerFCEIL(Op, DAG);
714*9880d681SAndroid Build Coastguard Worker case ISD::FTRUNC: return LowerFTRUNC(Op, DAG);
715*9880d681SAndroid Build Coastguard Worker case ISD::FRINT: return LowerFRINT(Op, DAG);
716*9880d681SAndroid Build Coastguard Worker case ISD::FNEARBYINT: return LowerFNEARBYINT(Op, DAG);
717*9880d681SAndroid Build Coastguard Worker case ISD::FROUND: return LowerFROUND(Op, DAG);
718*9880d681SAndroid Build Coastguard Worker case ISD::FFLOOR: return LowerFFLOOR(Op, DAG);
719*9880d681SAndroid Build Coastguard Worker case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
720*9880d681SAndroid Build Coastguard Worker case ISD::UINT_TO_FP: return LowerUINT_TO_FP(Op, DAG);
721*9880d681SAndroid Build Coastguard Worker case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
722*9880d681SAndroid Build Coastguard Worker case ISD::FP_TO_UINT: return LowerFP_TO_UINT(Op, DAG);
723*9880d681SAndroid Build Coastguard Worker case ISD::CTLZ:
724*9880d681SAndroid Build Coastguard Worker case ISD::CTLZ_ZERO_UNDEF:
725*9880d681SAndroid Build Coastguard Worker return LowerCTLZ(Op, DAG);
726*9880d681SAndroid Build Coastguard Worker case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
727*9880d681SAndroid Build Coastguard Worker }
728*9880d681SAndroid Build Coastguard Worker return Op;
729*9880d681SAndroid Build Coastguard Worker }
730*9880d681SAndroid Build Coastguard Worker
ReplaceNodeResults(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const731*9880d681SAndroid Build Coastguard Worker void AMDGPUTargetLowering::ReplaceNodeResults(SDNode *N,
732*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &Results,
733*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
734*9880d681SAndroid Build Coastguard Worker switch (N->getOpcode()) {
735*9880d681SAndroid Build Coastguard Worker case ISD::SIGN_EXTEND_INREG:
736*9880d681SAndroid Build Coastguard Worker // Different parts of legalization seem to interpret which type of
737*9880d681SAndroid Build Coastguard Worker // sign_extend_inreg is the one to check for custom lowering. The extended
738*9880d681SAndroid Build Coastguard Worker // from type is what really matters, but some places check for custom
739*9880d681SAndroid Build Coastguard Worker // lowering of the result type. This results in trying to use
740*9880d681SAndroid Build Coastguard Worker // ReplaceNodeResults to sext_in_reg to an illegal type, so we'll just do
741*9880d681SAndroid Build Coastguard Worker // nothing here and let the illegal result integer be handled normally.
742*9880d681SAndroid Build Coastguard Worker return;
743*9880d681SAndroid Build Coastguard Worker default:
744*9880d681SAndroid Build Coastguard Worker return;
745*9880d681SAndroid Build Coastguard Worker }
746*9880d681SAndroid Build Coastguard Worker }
747*9880d681SAndroid Build Coastguard Worker
748*9880d681SAndroid Build Coastguard Worker // FIXME: This implements accesses to initialized globals in the constant
749*9880d681SAndroid Build Coastguard Worker // address space by copying them to private and accessing that. It does not
750*9880d681SAndroid Build Coastguard Worker // properly handle illegal types or vectors. The private vector loads are not
751*9880d681SAndroid Build Coastguard Worker // scalarized, and the illegal scalars hit an assertion. This technique will not
752*9880d681SAndroid Build Coastguard Worker // work well with large initializers, and this should eventually be
753*9880d681SAndroid Build Coastguard Worker // removed. Initialized globals should be placed into a data section that the
754*9880d681SAndroid Build Coastguard Worker // runtime will load into a buffer before the kernel is executed. Uses of the
755*9880d681SAndroid Build Coastguard Worker // global need to be replaced with a pointer loaded from an implicit kernel
756*9880d681SAndroid Build Coastguard Worker // argument into this buffer holding the copy of the data, which will remove the
757*9880d681SAndroid Build Coastguard Worker // need for any of this.
LowerConstantInitializer(const Constant * Init,const GlobalValue * GV,const SDValue & InitPtr,SDValue Chain,SelectionDAG & DAG) const758*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerConstantInitializer(const Constant* Init,
759*9880d681SAndroid Build Coastguard Worker const GlobalValue *GV,
760*9880d681SAndroid Build Coastguard Worker const SDValue &InitPtr,
761*9880d681SAndroid Build Coastguard Worker SDValue Chain,
762*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
763*9880d681SAndroid Build Coastguard Worker const DataLayout &TD = DAG.getDataLayout();
764*9880d681SAndroid Build Coastguard Worker SDLoc DL(InitPtr);
765*9880d681SAndroid Build Coastguard Worker Type *InitTy = Init->getType();
766*9880d681SAndroid Build Coastguard Worker
767*9880d681SAndroid Build Coastguard Worker if (const ConstantInt *CI = dyn_cast<ConstantInt>(Init)) {
768*9880d681SAndroid Build Coastguard Worker EVT VT = EVT::getEVT(InitTy);
769*9880d681SAndroid Build Coastguard Worker PointerType *PtrTy = PointerType::get(InitTy, AMDGPUAS::PRIVATE_ADDRESS);
770*9880d681SAndroid Build Coastguard Worker return DAG.getStore(Chain, DL, DAG.getConstant(*CI, DL, VT), InitPtr,
771*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(UndefValue::get(PtrTy)), false,
772*9880d681SAndroid Build Coastguard Worker false, TD.getPrefTypeAlignment(InitTy));
773*9880d681SAndroid Build Coastguard Worker }
774*9880d681SAndroid Build Coastguard Worker
775*9880d681SAndroid Build Coastguard Worker if (const ConstantFP *CFP = dyn_cast<ConstantFP>(Init)) {
776*9880d681SAndroid Build Coastguard Worker EVT VT = EVT::getEVT(CFP->getType());
777*9880d681SAndroid Build Coastguard Worker PointerType *PtrTy = PointerType::get(CFP->getType(), 0);
778*9880d681SAndroid Build Coastguard Worker return DAG.getStore(Chain, DL, DAG.getConstantFP(*CFP, DL, VT), InitPtr,
779*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(UndefValue::get(PtrTy)), false,
780*9880d681SAndroid Build Coastguard Worker false, TD.getPrefTypeAlignment(CFP->getType()));
781*9880d681SAndroid Build Coastguard Worker }
782*9880d681SAndroid Build Coastguard Worker
783*9880d681SAndroid Build Coastguard Worker if (StructType *ST = dyn_cast<StructType>(InitTy)) {
784*9880d681SAndroid Build Coastguard Worker const StructLayout *SL = TD.getStructLayout(ST);
785*9880d681SAndroid Build Coastguard Worker
786*9880d681SAndroid Build Coastguard Worker EVT PtrVT = InitPtr.getValueType();
787*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> Chains;
788*9880d681SAndroid Build Coastguard Worker
789*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0, N = ST->getNumElements(); I != N; ++I) {
790*9880d681SAndroid Build Coastguard Worker SDValue Offset = DAG.getConstant(SL->getElementOffset(I), DL, PtrVT);
791*9880d681SAndroid Build Coastguard Worker SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, InitPtr, Offset);
792*9880d681SAndroid Build Coastguard Worker
793*9880d681SAndroid Build Coastguard Worker Constant *Elt = Init->getAggregateElement(I);
794*9880d681SAndroid Build Coastguard Worker Chains.push_back(LowerConstantInitializer(Elt, GV, Ptr, Chain, DAG));
795*9880d681SAndroid Build Coastguard Worker }
796*9880d681SAndroid Build Coastguard Worker
797*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
798*9880d681SAndroid Build Coastguard Worker }
799*9880d681SAndroid Build Coastguard Worker
800*9880d681SAndroid Build Coastguard Worker if (SequentialType *SeqTy = dyn_cast<SequentialType>(InitTy)) {
801*9880d681SAndroid Build Coastguard Worker EVT PtrVT = InitPtr.getValueType();
802*9880d681SAndroid Build Coastguard Worker
803*9880d681SAndroid Build Coastguard Worker unsigned NumElements;
804*9880d681SAndroid Build Coastguard Worker if (ArrayType *AT = dyn_cast<ArrayType>(SeqTy))
805*9880d681SAndroid Build Coastguard Worker NumElements = AT->getNumElements();
806*9880d681SAndroid Build Coastguard Worker else if (VectorType *VT = dyn_cast<VectorType>(SeqTy))
807*9880d681SAndroid Build Coastguard Worker NumElements = VT->getNumElements();
808*9880d681SAndroid Build Coastguard Worker else
809*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unexpected type");
810*9880d681SAndroid Build Coastguard Worker
811*9880d681SAndroid Build Coastguard Worker unsigned EltSize = TD.getTypeAllocSize(SeqTy->getElementType());
812*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> Chains;
813*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < NumElements; ++i) {
814*9880d681SAndroid Build Coastguard Worker SDValue Offset = DAG.getConstant(i * EltSize, DL, PtrVT);
815*9880d681SAndroid Build Coastguard Worker SDValue Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, InitPtr, Offset);
816*9880d681SAndroid Build Coastguard Worker
817*9880d681SAndroid Build Coastguard Worker Constant *Elt = Init->getAggregateElement(i);
818*9880d681SAndroid Build Coastguard Worker Chains.push_back(LowerConstantInitializer(Elt, GV, Ptr, Chain, DAG));
819*9880d681SAndroid Build Coastguard Worker }
820*9880d681SAndroid Build Coastguard Worker
821*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
822*9880d681SAndroid Build Coastguard Worker }
823*9880d681SAndroid Build Coastguard Worker
824*9880d681SAndroid Build Coastguard Worker if (isa<UndefValue>(Init)) {
825*9880d681SAndroid Build Coastguard Worker EVT VT = EVT::getEVT(InitTy);
826*9880d681SAndroid Build Coastguard Worker PointerType *PtrTy = PointerType::get(InitTy, AMDGPUAS::PRIVATE_ADDRESS);
827*9880d681SAndroid Build Coastguard Worker return DAG.getStore(Chain, DL, DAG.getUNDEF(VT), InitPtr,
828*9880d681SAndroid Build Coastguard Worker MachinePointerInfo(UndefValue::get(PtrTy)), false,
829*9880d681SAndroid Build Coastguard Worker false, TD.getPrefTypeAlignment(InitTy));
830*9880d681SAndroid Build Coastguard Worker }
831*9880d681SAndroid Build Coastguard Worker
832*9880d681SAndroid Build Coastguard Worker Init->dump();
833*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unhandled constant initializer");
834*9880d681SAndroid Build Coastguard Worker }
835*9880d681SAndroid Build Coastguard Worker
hasDefinedInitializer(const GlobalValue * GV)836*9880d681SAndroid Build Coastguard Worker static bool hasDefinedInitializer(const GlobalValue *GV) {
837*9880d681SAndroid Build Coastguard Worker const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
838*9880d681SAndroid Build Coastguard Worker if (!GVar || !GVar->hasInitializer())
839*9880d681SAndroid Build Coastguard Worker return false;
840*9880d681SAndroid Build Coastguard Worker
841*9880d681SAndroid Build Coastguard Worker return !isa<UndefValue>(GVar->getInitializer());
842*9880d681SAndroid Build Coastguard Worker }
843*9880d681SAndroid Build Coastguard Worker
LowerGlobalAddress(AMDGPUMachineFunction * MFI,SDValue Op,SelectionDAG & DAG) const844*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerGlobalAddress(AMDGPUMachineFunction* MFI,
845*9880d681SAndroid Build Coastguard Worker SDValue Op,
846*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
847*9880d681SAndroid Build Coastguard Worker
848*9880d681SAndroid Build Coastguard Worker const DataLayout &DL = DAG.getDataLayout();
849*9880d681SAndroid Build Coastguard Worker GlobalAddressSDNode *G = cast<GlobalAddressSDNode>(Op);
850*9880d681SAndroid Build Coastguard Worker const GlobalValue *GV = G->getGlobal();
851*9880d681SAndroid Build Coastguard Worker
852*9880d681SAndroid Build Coastguard Worker switch (G->getAddressSpace()) {
853*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::CONSTANT_ADDRESS: {
854*9880d681SAndroid Build Coastguard Worker MVT ConstPtrVT = getPointerTy(DL, AMDGPUAS::CONSTANT_ADDRESS);
855*9880d681SAndroid Build Coastguard Worker SDValue GA = DAG.getTargetGlobalAddress(GV, SDLoc(G), ConstPtrVT);
856*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::CONST_DATA_PTR, SDLoc(G), ConstPtrVT, GA);
857*9880d681SAndroid Build Coastguard Worker }
858*9880d681SAndroid Build Coastguard Worker case AMDGPUAS::LOCAL_ADDRESS: {
859*9880d681SAndroid Build Coastguard Worker // XXX: What does the value of G->getOffset() mean?
860*9880d681SAndroid Build Coastguard Worker assert(G->getOffset() == 0 &&
861*9880d681SAndroid Build Coastguard Worker "Do not know what to do with an non-zero offset");
862*9880d681SAndroid Build Coastguard Worker
863*9880d681SAndroid Build Coastguard Worker // TODO: We could emit code to handle the initialization somewhere.
864*9880d681SAndroid Build Coastguard Worker if (hasDefinedInitializer(GV))
865*9880d681SAndroid Build Coastguard Worker break;
866*9880d681SAndroid Build Coastguard Worker
867*9880d681SAndroid Build Coastguard Worker unsigned Offset;
868*9880d681SAndroid Build Coastguard Worker if (MFI->LocalMemoryObjects.count(GV) == 0) {
869*9880d681SAndroid Build Coastguard Worker unsigned Align = GV->getAlignment();
870*9880d681SAndroid Build Coastguard Worker if (Align == 0)
871*9880d681SAndroid Build Coastguard Worker Align = DL.getABITypeAlignment(GV->getValueType());
872*9880d681SAndroid Build Coastguard Worker
873*9880d681SAndroid Build Coastguard Worker /// TODO: We should sort these to minimize wasted space due to alignment
874*9880d681SAndroid Build Coastguard Worker /// padding. Currently the padding is decided by the first encountered use
875*9880d681SAndroid Build Coastguard Worker /// during lowering.
876*9880d681SAndroid Build Coastguard Worker Offset = MFI->LDSSize = alignTo(MFI->LDSSize, Align);
877*9880d681SAndroid Build Coastguard Worker MFI->LocalMemoryObjects[GV] = Offset;
878*9880d681SAndroid Build Coastguard Worker MFI->LDSSize += DL.getTypeAllocSize(GV->getValueType());
879*9880d681SAndroid Build Coastguard Worker } else {
880*9880d681SAndroid Build Coastguard Worker Offset = MFI->LocalMemoryObjects[GV];
881*9880d681SAndroid Build Coastguard Worker }
882*9880d681SAndroid Build Coastguard Worker
883*9880d681SAndroid Build Coastguard Worker return DAG.getConstant(Offset, SDLoc(Op),
884*9880d681SAndroid Build Coastguard Worker getPointerTy(DL, AMDGPUAS::LOCAL_ADDRESS));
885*9880d681SAndroid Build Coastguard Worker }
886*9880d681SAndroid Build Coastguard Worker }
887*9880d681SAndroid Build Coastguard Worker
888*9880d681SAndroid Build Coastguard Worker const Function &Fn = *DAG.getMachineFunction().getFunction();
889*9880d681SAndroid Build Coastguard Worker DiagnosticInfoUnsupported BadInit(
890*9880d681SAndroid Build Coastguard Worker Fn, "unsupported initializer for address space", SDLoc(Op).getDebugLoc());
891*9880d681SAndroid Build Coastguard Worker DAG.getContext()->diagnose(BadInit);
892*9880d681SAndroid Build Coastguard Worker return SDValue();
893*9880d681SAndroid Build Coastguard Worker }
894*9880d681SAndroid Build Coastguard Worker
LowerCONCAT_VECTORS(SDValue Op,SelectionDAG & DAG) const895*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerCONCAT_VECTORS(SDValue Op,
896*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
897*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> Args;
898*9880d681SAndroid Build Coastguard Worker
899*9880d681SAndroid Build Coastguard Worker for (const SDUse &U : Op->ops())
900*9880d681SAndroid Build Coastguard Worker DAG.ExtractVectorElements(U.get(), Args);
901*9880d681SAndroid Build Coastguard Worker
902*9880d681SAndroid Build Coastguard Worker return DAG.getBuildVector(Op.getValueType(), SDLoc(Op), Args);
903*9880d681SAndroid Build Coastguard Worker }
904*9880d681SAndroid Build Coastguard Worker
LowerEXTRACT_SUBVECTOR(SDValue Op,SelectionDAG & DAG) const905*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerEXTRACT_SUBVECTOR(SDValue Op,
906*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
907*9880d681SAndroid Build Coastguard Worker
908*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> Args;
909*9880d681SAndroid Build Coastguard Worker unsigned Start = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
910*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
911*9880d681SAndroid Build Coastguard Worker DAG.ExtractVectorElements(Op.getOperand(0), Args, Start,
912*9880d681SAndroid Build Coastguard Worker VT.getVectorNumElements());
913*9880d681SAndroid Build Coastguard Worker
914*9880d681SAndroid Build Coastguard Worker return DAG.getBuildVector(Op.getValueType(), SDLoc(Op), Args);
915*9880d681SAndroid Build Coastguard Worker }
916*9880d681SAndroid Build Coastguard Worker
LowerINTRINSIC_WO_CHAIN(SDValue Op,SelectionDAG & DAG) const917*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
918*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
919*9880d681SAndroid Build Coastguard Worker unsigned IntrinsicID = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
920*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
921*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
922*9880d681SAndroid Build Coastguard Worker
923*9880d681SAndroid Build Coastguard Worker switch (IntrinsicID) {
924*9880d681SAndroid Build Coastguard Worker default: return Op;
925*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::AMDGPU_clamp: // Legacy name.
926*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::CLAMP, DL, VT,
927*9880d681SAndroid Build Coastguard Worker Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
928*9880d681SAndroid Build Coastguard Worker
929*9880d681SAndroid Build Coastguard Worker case Intrinsic::AMDGPU_ldexp: // Legacy name
930*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::LDEXP, DL, VT, Op.getOperand(1),
931*9880d681SAndroid Build Coastguard Worker Op.getOperand(2));
932*9880d681SAndroid Build Coastguard Worker
933*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::AMDGPU_bfe_i32:
934*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::BFE_I32, DL, VT,
935*9880d681SAndroid Build Coastguard Worker Op.getOperand(1),
936*9880d681SAndroid Build Coastguard Worker Op.getOperand(2),
937*9880d681SAndroid Build Coastguard Worker Op.getOperand(3));
938*9880d681SAndroid Build Coastguard Worker
939*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::AMDGPU_bfe_u32:
940*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::BFE_U32, DL, VT,
941*9880d681SAndroid Build Coastguard Worker Op.getOperand(1),
942*9880d681SAndroid Build Coastguard Worker Op.getOperand(2),
943*9880d681SAndroid Build Coastguard Worker Op.getOperand(3));
944*9880d681SAndroid Build Coastguard Worker
945*9880d681SAndroid Build Coastguard Worker case AMDGPUIntrinsic::AMDGPU_brev: // Legacy name
946*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITREVERSE, DL, VT, Op.getOperand(1));
947*9880d681SAndroid Build Coastguard Worker }
948*9880d681SAndroid Build Coastguard Worker }
949*9880d681SAndroid Build Coastguard Worker
950*9880d681SAndroid Build Coastguard Worker /// \brief Generate Min/Max node
CombineFMinMaxLegacy(const SDLoc & DL,EVT VT,SDValue LHS,SDValue RHS,SDValue True,SDValue False,SDValue CC,DAGCombinerInfo & DCI) const951*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::CombineFMinMaxLegacy(const SDLoc &DL, EVT VT,
952*9880d681SAndroid Build Coastguard Worker SDValue LHS, SDValue RHS,
953*9880d681SAndroid Build Coastguard Worker SDValue True, SDValue False,
954*9880d681SAndroid Build Coastguard Worker SDValue CC,
955*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
956*9880d681SAndroid Build Coastguard Worker if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
957*9880d681SAndroid Build Coastguard Worker return SDValue();
958*9880d681SAndroid Build Coastguard Worker
959*9880d681SAndroid Build Coastguard Worker if (!(LHS == True && RHS == False) && !(LHS == False && RHS == True))
960*9880d681SAndroid Build Coastguard Worker return SDValue();
961*9880d681SAndroid Build Coastguard Worker
962*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
963*9880d681SAndroid Build Coastguard Worker ISD::CondCode CCOpcode = cast<CondCodeSDNode>(CC)->get();
964*9880d681SAndroid Build Coastguard Worker switch (CCOpcode) {
965*9880d681SAndroid Build Coastguard Worker case ISD::SETOEQ:
966*9880d681SAndroid Build Coastguard Worker case ISD::SETONE:
967*9880d681SAndroid Build Coastguard Worker case ISD::SETUNE:
968*9880d681SAndroid Build Coastguard Worker case ISD::SETNE:
969*9880d681SAndroid Build Coastguard Worker case ISD::SETUEQ:
970*9880d681SAndroid Build Coastguard Worker case ISD::SETEQ:
971*9880d681SAndroid Build Coastguard Worker case ISD::SETFALSE:
972*9880d681SAndroid Build Coastguard Worker case ISD::SETFALSE2:
973*9880d681SAndroid Build Coastguard Worker case ISD::SETTRUE:
974*9880d681SAndroid Build Coastguard Worker case ISD::SETTRUE2:
975*9880d681SAndroid Build Coastguard Worker case ISD::SETUO:
976*9880d681SAndroid Build Coastguard Worker case ISD::SETO:
977*9880d681SAndroid Build Coastguard Worker break;
978*9880d681SAndroid Build Coastguard Worker case ISD::SETULE:
979*9880d681SAndroid Build Coastguard Worker case ISD::SETULT: {
980*9880d681SAndroid Build Coastguard Worker if (LHS == True)
981*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, RHS, LHS);
982*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, LHS, RHS);
983*9880d681SAndroid Build Coastguard Worker }
984*9880d681SAndroid Build Coastguard Worker case ISD::SETOLE:
985*9880d681SAndroid Build Coastguard Worker case ISD::SETOLT:
986*9880d681SAndroid Build Coastguard Worker case ISD::SETLE:
987*9880d681SAndroid Build Coastguard Worker case ISD::SETLT: {
988*9880d681SAndroid Build Coastguard Worker // Ordered. Assume ordered for undefined.
989*9880d681SAndroid Build Coastguard Worker
990*9880d681SAndroid Build Coastguard Worker // Only do this after legalization to avoid interfering with other combines
991*9880d681SAndroid Build Coastguard Worker // which might occur.
992*9880d681SAndroid Build Coastguard Worker if (DCI.getDAGCombineLevel() < AfterLegalizeDAG &&
993*9880d681SAndroid Build Coastguard Worker !DCI.isCalledByLegalizer())
994*9880d681SAndroid Build Coastguard Worker return SDValue();
995*9880d681SAndroid Build Coastguard Worker
996*9880d681SAndroid Build Coastguard Worker // We need to permute the operands to get the correct NaN behavior. The
997*9880d681SAndroid Build Coastguard Worker // selected operand is the second one based on the failing compare with NaN,
998*9880d681SAndroid Build Coastguard Worker // so permute it based on the compare type the hardware uses.
999*9880d681SAndroid Build Coastguard Worker if (LHS == True)
1000*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, LHS, RHS);
1001*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, RHS, LHS);
1002*9880d681SAndroid Build Coastguard Worker }
1003*9880d681SAndroid Build Coastguard Worker case ISD::SETUGE:
1004*9880d681SAndroid Build Coastguard Worker case ISD::SETUGT: {
1005*9880d681SAndroid Build Coastguard Worker if (LHS == True)
1006*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, RHS, LHS);
1007*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, LHS, RHS);
1008*9880d681SAndroid Build Coastguard Worker }
1009*9880d681SAndroid Build Coastguard Worker case ISD::SETGT:
1010*9880d681SAndroid Build Coastguard Worker case ISD::SETGE:
1011*9880d681SAndroid Build Coastguard Worker case ISD::SETOGE:
1012*9880d681SAndroid Build Coastguard Worker case ISD::SETOGT: {
1013*9880d681SAndroid Build Coastguard Worker if (DCI.getDAGCombineLevel() < AfterLegalizeDAG &&
1014*9880d681SAndroid Build Coastguard Worker !DCI.isCalledByLegalizer())
1015*9880d681SAndroid Build Coastguard Worker return SDValue();
1016*9880d681SAndroid Build Coastguard Worker
1017*9880d681SAndroid Build Coastguard Worker if (LHS == True)
1018*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FMAX_LEGACY, DL, VT, LHS, RHS);
1019*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FMIN_LEGACY, DL, VT, RHS, LHS);
1020*9880d681SAndroid Build Coastguard Worker }
1021*9880d681SAndroid Build Coastguard Worker case ISD::SETCC_INVALID:
1022*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Invalid setcc condcode!");
1023*9880d681SAndroid Build Coastguard Worker }
1024*9880d681SAndroid Build Coastguard Worker return SDValue();
1025*9880d681SAndroid Build Coastguard Worker }
1026*9880d681SAndroid Build Coastguard Worker
1027*9880d681SAndroid Build Coastguard Worker std::pair<SDValue, SDValue>
split64BitValue(SDValue Op,SelectionDAG & DAG) const1028*9880d681SAndroid Build Coastguard Worker AMDGPUTargetLowering::split64BitValue(SDValue Op, SelectionDAG &DAG) const {
1029*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1030*9880d681SAndroid Build Coastguard Worker
1031*9880d681SAndroid Build Coastguard Worker SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1032*9880d681SAndroid Build Coastguard Worker
1033*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1034*9880d681SAndroid Build Coastguard Worker const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1035*9880d681SAndroid Build Coastguard Worker
1036*9880d681SAndroid Build Coastguard Worker SDValue Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);
1037*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);
1038*9880d681SAndroid Build Coastguard Worker
1039*9880d681SAndroid Build Coastguard Worker return std::make_pair(Lo, Hi);
1040*9880d681SAndroid Build Coastguard Worker }
1041*9880d681SAndroid Build Coastguard Worker
getLoHalf64(SDValue Op,SelectionDAG & DAG) const1042*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::getLoHalf64(SDValue Op, SelectionDAG &DAG) const {
1043*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1044*9880d681SAndroid Build Coastguard Worker
1045*9880d681SAndroid Build Coastguard Worker SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1046*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1047*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);
1048*9880d681SAndroid Build Coastguard Worker }
1049*9880d681SAndroid Build Coastguard Worker
getHiHalf64(SDValue Op,SelectionDAG & DAG) const1050*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::getHiHalf64(SDValue Op, SelectionDAG &DAG) const {
1051*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1052*9880d681SAndroid Build Coastguard Worker
1053*9880d681SAndroid Build Coastguard Worker SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Op);
1054*9880d681SAndroid Build Coastguard Worker const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1055*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);
1056*9880d681SAndroid Build Coastguard Worker }
1057*9880d681SAndroid Build Coastguard Worker
SplitVectorLoad(const SDValue Op,SelectionDAG & DAG) const1058*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::SplitVectorLoad(const SDValue Op,
1059*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1060*9880d681SAndroid Build Coastguard Worker LoadSDNode *Load = cast<LoadSDNode>(Op);
1061*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1062*9880d681SAndroid Build Coastguard Worker
1063*9880d681SAndroid Build Coastguard Worker
1064*9880d681SAndroid Build Coastguard Worker // If this is a 2 element vector, we really want to scalarize and not create
1065*9880d681SAndroid Build Coastguard Worker // weird 1 element vectors.
1066*9880d681SAndroid Build Coastguard Worker if (VT.getVectorNumElements() == 2)
1067*9880d681SAndroid Build Coastguard Worker return scalarizeVectorLoad(Load, DAG);
1068*9880d681SAndroid Build Coastguard Worker
1069*9880d681SAndroid Build Coastguard Worker SDValue BasePtr = Load->getBasePtr();
1070*9880d681SAndroid Build Coastguard Worker EVT PtrVT = BasePtr.getValueType();
1071*9880d681SAndroid Build Coastguard Worker EVT MemVT = Load->getMemoryVT();
1072*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1073*9880d681SAndroid Build Coastguard Worker
1074*9880d681SAndroid Build Coastguard Worker const MachinePointerInfo &SrcValue = Load->getMemOperand()->getPointerInfo();
1075*9880d681SAndroid Build Coastguard Worker
1076*9880d681SAndroid Build Coastguard Worker EVT LoVT, HiVT;
1077*9880d681SAndroid Build Coastguard Worker EVT LoMemVT, HiMemVT;
1078*9880d681SAndroid Build Coastguard Worker SDValue Lo, Hi;
1079*9880d681SAndroid Build Coastguard Worker
1080*9880d681SAndroid Build Coastguard Worker std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT);
1081*9880d681SAndroid Build Coastguard Worker std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemVT);
1082*9880d681SAndroid Build Coastguard Worker std::tie(Lo, Hi) = DAG.SplitVector(Op, SL, LoVT, HiVT);
1083*9880d681SAndroid Build Coastguard Worker
1084*9880d681SAndroid Build Coastguard Worker unsigned Size = LoMemVT.getStoreSize();
1085*9880d681SAndroid Build Coastguard Worker unsigned BaseAlign = Load->getAlignment();
1086*9880d681SAndroid Build Coastguard Worker unsigned HiAlign = MinAlign(BaseAlign, Size);
1087*9880d681SAndroid Build Coastguard Worker
1088*9880d681SAndroid Build Coastguard Worker SDValue LoLoad
1089*9880d681SAndroid Build Coastguard Worker = DAG.getExtLoad(Load->getExtensionType(), SL, LoVT,
1090*9880d681SAndroid Build Coastguard Worker Load->getChain(), BasePtr,
1091*9880d681SAndroid Build Coastguard Worker SrcValue,
1092*9880d681SAndroid Build Coastguard Worker LoMemVT, Load->isVolatile(), Load->isNonTemporal(),
1093*9880d681SAndroid Build Coastguard Worker Load->isInvariant(), BaseAlign);
1094*9880d681SAndroid Build Coastguard Worker
1095*9880d681SAndroid Build Coastguard Worker SDValue HiPtr = DAG.getNode(ISD::ADD, SL, PtrVT, BasePtr,
1096*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Size, SL, PtrVT));
1097*9880d681SAndroid Build Coastguard Worker
1098*9880d681SAndroid Build Coastguard Worker SDValue HiLoad
1099*9880d681SAndroid Build Coastguard Worker = DAG.getExtLoad(Load->getExtensionType(), SL, HiVT,
1100*9880d681SAndroid Build Coastguard Worker Load->getChain(), HiPtr,
1101*9880d681SAndroid Build Coastguard Worker SrcValue.getWithOffset(LoMemVT.getStoreSize()),
1102*9880d681SAndroid Build Coastguard Worker HiMemVT, Load->isVolatile(), Load->isNonTemporal(),
1103*9880d681SAndroid Build Coastguard Worker Load->isInvariant(), HiAlign);
1104*9880d681SAndroid Build Coastguard Worker
1105*9880d681SAndroid Build Coastguard Worker SDValue Ops[] = {
1106*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::CONCAT_VECTORS, SL, VT, LoLoad, HiLoad),
1107*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::TokenFactor, SL, MVT::Other,
1108*9880d681SAndroid Build Coastguard Worker LoLoad.getValue(1), HiLoad.getValue(1))
1109*9880d681SAndroid Build Coastguard Worker };
1110*9880d681SAndroid Build Coastguard Worker
1111*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, SL);
1112*9880d681SAndroid Build Coastguard Worker }
1113*9880d681SAndroid Build Coastguard Worker
1114*9880d681SAndroid Build Coastguard Worker // FIXME: This isn't doing anything for SI. This should be used in a target
1115*9880d681SAndroid Build Coastguard Worker // combine during type legalization.
MergeVectorStore(const SDValue & Op,SelectionDAG & DAG) const1116*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::MergeVectorStore(const SDValue &Op,
1117*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1118*9880d681SAndroid Build Coastguard Worker StoreSDNode *Store = cast<StoreSDNode>(Op);
1119*9880d681SAndroid Build Coastguard Worker EVT MemVT = Store->getMemoryVT();
1120*9880d681SAndroid Build Coastguard Worker unsigned MemBits = MemVT.getSizeInBits();
1121*9880d681SAndroid Build Coastguard Worker
1122*9880d681SAndroid Build Coastguard Worker // Byte stores are really expensive, so if possible, try to pack 32-bit vector
1123*9880d681SAndroid Build Coastguard Worker // truncating store into an i32 store.
1124*9880d681SAndroid Build Coastguard Worker // XXX: We could also handle optimize other vector bitwidths.
1125*9880d681SAndroid Build Coastguard Worker if (!MemVT.isVector() || MemBits > 32) {
1126*9880d681SAndroid Build Coastguard Worker return SDValue();
1127*9880d681SAndroid Build Coastguard Worker }
1128*9880d681SAndroid Build Coastguard Worker
1129*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1130*9880d681SAndroid Build Coastguard Worker SDValue Value = Store->getValue();
1131*9880d681SAndroid Build Coastguard Worker EVT VT = Value.getValueType();
1132*9880d681SAndroid Build Coastguard Worker EVT ElemVT = VT.getVectorElementType();
1133*9880d681SAndroid Build Coastguard Worker SDValue Ptr = Store->getBasePtr();
1134*9880d681SAndroid Build Coastguard Worker EVT MemEltVT = MemVT.getVectorElementType();
1135*9880d681SAndroid Build Coastguard Worker unsigned MemEltBits = MemEltVT.getSizeInBits();
1136*9880d681SAndroid Build Coastguard Worker unsigned MemNumElements = MemVT.getVectorNumElements();
1137*9880d681SAndroid Build Coastguard Worker unsigned PackedSize = MemVT.getStoreSizeInBits();
1138*9880d681SAndroid Build Coastguard Worker SDValue Mask = DAG.getConstant((1 << MemEltBits) - 1, DL, MVT::i32);
1139*9880d681SAndroid Build Coastguard Worker
1140*9880d681SAndroid Build Coastguard Worker assert(Value.getValueType().getScalarSizeInBits() >= 32);
1141*9880d681SAndroid Build Coastguard Worker
1142*9880d681SAndroid Build Coastguard Worker SDValue PackedValue;
1143*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < MemNumElements; ++i) {
1144*9880d681SAndroid Build Coastguard Worker SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, ElemVT, Value,
1145*9880d681SAndroid Build Coastguard Worker DAG.getConstant(i, DL, MVT::i32));
1146*9880d681SAndroid Build Coastguard Worker Elt = DAG.getZExtOrTrunc(Elt, DL, MVT::i32);
1147*9880d681SAndroid Build Coastguard Worker Elt = DAG.getNode(ISD::AND, DL, MVT::i32, Elt, Mask); // getZeroExtendInReg
1148*9880d681SAndroid Build Coastguard Worker
1149*9880d681SAndroid Build Coastguard Worker SDValue Shift = DAG.getConstant(MemEltBits * i, DL, MVT::i32);
1150*9880d681SAndroid Build Coastguard Worker Elt = DAG.getNode(ISD::SHL, DL, MVT::i32, Elt, Shift);
1151*9880d681SAndroid Build Coastguard Worker
1152*9880d681SAndroid Build Coastguard Worker if (i == 0) {
1153*9880d681SAndroid Build Coastguard Worker PackedValue = Elt;
1154*9880d681SAndroid Build Coastguard Worker } else {
1155*9880d681SAndroid Build Coastguard Worker PackedValue = DAG.getNode(ISD::OR, DL, MVT::i32, PackedValue, Elt);
1156*9880d681SAndroid Build Coastguard Worker }
1157*9880d681SAndroid Build Coastguard Worker }
1158*9880d681SAndroid Build Coastguard Worker
1159*9880d681SAndroid Build Coastguard Worker if (PackedSize < 32) {
1160*9880d681SAndroid Build Coastguard Worker EVT PackedVT = EVT::getIntegerVT(*DAG.getContext(), PackedSize);
1161*9880d681SAndroid Build Coastguard Worker return DAG.getTruncStore(Store->getChain(), DL, PackedValue, Ptr,
1162*9880d681SAndroid Build Coastguard Worker Store->getMemOperand()->getPointerInfo(),
1163*9880d681SAndroid Build Coastguard Worker PackedVT,
1164*9880d681SAndroid Build Coastguard Worker Store->isNonTemporal(), Store->isVolatile(),
1165*9880d681SAndroid Build Coastguard Worker Store->getAlignment());
1166*9880d681SAndroid Build Coastguard Worker }
1167*9880d681SAndroid Build Coastguard Worker
1168*9880d681SAndroid Build Coastguard Worker return DAG.getStore(Store->getChain(), DL, PackedValue, Ptr,
1169*9880d681SAndroid Build Coastguard Worker Store->getMemOperand()->getPointerInfo(),
1170*9880d681SAndroid Build Coastguard Worker Store->isVolatile(), Store->isNonTemporal(),
1171*9880d681SAndroid Build Coastguard Worker Store->getAlignment());
1172*9880d681SAndroid Build Coastguard Worker }
1173*9880d681SAndroid Build Coastguard Worker
SplitVectorStore(SDValue Op,SelectionDAG & DAG) const1174*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::SplitVectorStore(SDValue Op,
1175*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1176*9880d681SAndroid Build Coastguard Worker StoreSDNode *Store = cast<StoreSDNode>(Op);
1177*9880d681SAndroid Build Coastguard Worker SDValue Val = Store->getValue();
1178*9880d681SAndroid Build Coastguard Worker EVT VT = Val.getValueType();
1179*9880d681SAndroid Build Coastguard Worker
1180*9880d681SAndroid Build Coastguard Worker // If this is a 2 element vector, we really want to scalarize and not create
1181*9880d681SAndroid Build Coastguard Worker // weird 1 element vectors.
1182*9880d681SAndroid Build Coastguard Worker if (VT.getVectorNumElements() == 2)
1183*9880d681SAndroid Build Coastguard Worker return scalarizeVectorStore(Store, DAG);
1184*9880d681SAndroid Build Coastguard Worker
1185*9880d681SAndroid Build Coastguard Worker EVT MemVT = Store->getMemoryVT();
1186*9880d681SAndroid Build Coastguard Worker SDValue Chain = Store->getChain();
1187*9880d681SAndroid Build Coastguard Worker SDValue BasePtr = Store->getBasePtr();
1188*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1189*9880d681SAndroid Build Coastguard Worker
1190*9880d681SAndroid Build Coastguard Worker EVT LoVT, HiVT;
1191*9880d681SAndroid Build Coastguard Worker EVT LoMemVT, HiMemVT;
1192*9880d681SAndroid Build Coastguard Worker SDValue Lo, Hi;
1193*9880d681SAndroid Build Coastguard Worker
1194*9880d681SAndroid Build Coastguard Worker std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT);
1195*9880d681SAndroid Build Coastguard Worker std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemVT);
1196*9880d681SAndroid Build Coastguard Worker std::tie(Lo, Hi) = DAG.SplitVector(Val, SL, LoVT, HiVT);
1197*9880d681SAndroid Build Coastguard Worker
1198*9880d681SAndroid Build Coastguard Worker EVT PtrVT = BasePtr.getValueType();
1199*9880d681SAndroid Build Coastguard Worker SDValue HiPtr = DAG.getNode(ISD::ADD, SL, PtrVT, BasePtr,
1200*9880d681SAndroid Build Coastguard Worker DAG.getConstant(LoMemVT.getStoreSize(), SL,
1201*9880d681SAndroid Build Coastguard Worker PtrVT));
1202*9880d681SAndroid Build Coastguard Worker
1203*9880d681SAndroid Build Coastguard Worker const MachinePointerInfo &SrcValue = Store->getMemOperand()->getPointerInfo();
1204*9880d681SAndroid Build Coastguard Worker unsigned BaseAlign = Store->getAlignment();
1205*9880d681SAndroid Build Coastguard Worker unsigned Size = LoMemVT.getStoreSize();
1206*9880d681SAndroid Build Coastguard Worker unsigned HiAlign = MinAlign(BaseAlign, Size);
1207*9880d681SAndroid Build Coastguard Worker
1208*9880d681SAndroid Build Coastguard Worker SDValue LoStore
1209*9880d681SAndroid Build Coastguard Worker = DAG.getTruncStore(Chain, SL, Lo,
1210*9880d681SAndroid Build Coastguard Worker BasePtr,
1211*9880d681SAndroid Build Coastguard Worker SrcValue,
1212*9880d681SAndroid Build Coastguard Worker LoMemVT,
1213*9880d681SAndroid Build Coastguard Worker Store->isNonTemporal(),
1214*9880d681SAndroid Build Coastguard Worker Store->isVolatile(),
1215*9880d681SAndroid Build Coastguard Worker BaseAlign);
1216*9880d681SAndroid Build Coastguard Worker SDValue HiStore
1217*9880d681SAndroid Build Coastguard Worker = DAG.getTruncStore(Chain, SL, Hi,
1218*9880d681SAndroid Build Coastguard Worker HiPtr,
1219*9880d681SAndroid Build Coastguard Worker SrcValue.getWithOffset(Size),
1220*9880d681SAndroid Build Coastguard Worker HiMemVT,
1221*9880d681SAndroid Build Coastguard Worker Store->isNonTemporal(),
1222*9880d681SAndroid Build Coastguard Worker Store->isVolatile(),
1223*9880d681SAndroid Build Coastguard Worker HiAlign);
1224*9880d681SAndroid Build Coastguard Worker
1225*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::TokenFactor, SL, MVT::Other, LoStore, HiStore);
1226*9880d681SAndroid Build Coastguard Worker }
1227*9880d681SAndroid Build Coastguard Worker
1228*9880d681SAndroid Build Coastguard Worker // This is a shortcut for integer division because we have fast i32<->f32
1229*9880d681SAndroid Build Coastguard Worker // conversions, and fast f32 reciprocal instructions. The fractional part of a
1230*9880d681SAndroid Build Coastguard Worker // float is enough to accurately represent up to a 24-bit signed integer.
LowerDIVREM24(SDValue Op,SelectionDAG & DAG,bool Sign) const1231*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerDIVREM24(SDValue Op, SelectionDAG &DAG,
1232*9880d681SAndroid Build Coastguard Worker bool Sign) const {
1233*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1234*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1235*9880d681SAndroid Build Coastguard Worker SDValue LHS = Op.getOperand(0);
1236*9880d681SAndroid Build Coastguard Worker SDValue RHS = Op.getOperand(1);
1237*9880d681SAndroid Build Coastguard Worker MVT IntVT = MVT::i32;
1238*9880d681SAndroid Build Coastguard Worker MVT FltVT = MVT::f32;
1239*9880d681SAndroid Build Coastguard Worker
1240*9880d681SAndroid Build Coastguard Worker unsigned LHSSignBits = DAG.ComputeNumSignBits(LHS);
1241*9880d681SAndroid Build Coastguard Worker if (LHSSignBits < 9)
1242*9880d681SAndroid Build Coastguard Worker return SDValue();
1243*9880d681SAndroid Build Coastguard Worker
1244*9880d681SAndroid Build Coastguard Worker unsigned RHSSignBits = DAG.ComputeNumSignBits(RHS);
1245*9880d681SAndroid Build Coastguard Worker if (RHSSignBits < 9)
1246*9880d681SAndroid Build Coastguard Worker return SDValue();
1247*9880d681SAndroid Build Coastguard Worker
1248*9880d681SAndroid Build Coastguard Worker unsigned BitSize = VT.getSizeInBits();
1249*9880d681SAndroid Build Coastguard Worker unsigned SignBits = std::min(LHSSignBits, RHSSignBits);
1250*9880d681SAndroid Build Coastguard Worker unsigned DivBits = BitSize - SignBits;
1251*9880d681SAndroid Build Coastguard Worker if (Sign)
1252*9880d681SAndroid Build Coastguard Worker ++DivBits;
1253*9880d681SAndroid Build Coastguard Worker
1254*9880d681SAndroid Build Coastguard Worker ISD::NodeType ToFp = Sign ? ISD::SINT_TO_FP : ISD::UINT_TO_FP;
1255*9880d681SAndroid Build Coastguard Worker ISD::NodeType ToInt = Sign ? ISD::FP_TO_SINT : ISD::FP_TO_UINT;
1256*9880d681SAndroid Build Coastguard Worker
1257*9880d681SAndroid Build Coastguard Worker SDValue jq = DAG.getConstant(1, DL, IntVT);
1258*9880d681SAndroid Build Coastguard Worker
1259*9880d681SAndroid Build Coastguard Worker if (Sign) {
1260*9880d681SAndroid Build Coastguard Worker // char|short jq = ia ^ ib;
1261*9880d681SAndroid Build Coastguard Worker jq = DAG.getNode(ISD::XOR, DL, VT, LHS, RHS);
1262*9880d681SAndroid Build Coastguard Worker
1263*9880d681SAndroid Build Coastguard Worker // jq = jq >> (bitsize - 2)
1264*9880d681SAndroid Build Coastguard Worker jq = DAG.getNode(ISD::SRA, DL, VT, jq,
1265*9880d681SAndroid Build Coastguard Worker DAG.getConstant(BitSize - 2, DL, VT));
1266*9880d681SAndroid Build Coastguard Worker
1267*9880d681SAndroid Build Coastguard Worker // jq = jq | 0x1
1268*9880d681SAndroid Build Coastguard Worker jq = DAG.getNode(ISD::OR, DL, VT, jq, DAG.getConstant(1, DL, VT));
1269*9880d681SAndroid Build Coastguard Worker }
1270*9880d681SAndroid Build Coastguard Worker
1271*9880d681SAndroid Build Coastguard Worker // int ia = (int)LHS;
1272*9880d681SAndroid Build Coastguard Worker SDValue ia = LHS;
1273*9880d681SAndroid Build Coastguard Worker
1274*9880d681SAndroid Build Coastguard Worker // int ib, (int)RHS;
1275*9880d681SAndroid Build Coastguard Worker SDValue ib = RHS;
1276*9880d681SAndroid Build Coastguard Worker
1277*9880d681SAndroid Build Coastguard Worker // float fa = (float)ia;
1278*9880d681SAndroid Build Coastguard Worker SDValue fa = DAG.getNode(ToFp, DL, FltVT, ia);
1279*9880d681SAndroid Build Coastguard Worker
1280*9880d681SAndroid Build Coastguard Worker // float fb = (float)ib;
1281*9880d681SAndroid Build Coastguard Worker SDValue fb = DAG.getNode(ToFp, DL, FltVT, ib);
1282*9880d681SAndroid Build Coastguard Worker
1283*9880d681SAndroid Build Coastguard Worker SDValue fq = DAG.getNode(ISD::FMUL, DL, FltVT,
1284*9880d681SAndroid Build Coastguard Worker fa, DAG.getNode(AMDGPUISD::RCP, DL, FltVT, fb));
1285*9880d681SAndroid Build Coastguard Worker
1286*9880d681SAndroid Build Coastguard Worker // fq = trunc(fq);
1287*9880d681SAndroid Build Coastguard Worker fq = DAG.getNode(ISD::FTRUNC, DL, FltVT, fq);
1288*9880d681SAndroid Build Coastguard Worker
1289*9880d681SAndroid Build Coastguard Worker // float fqneg = -fq;
1290*9880d681SAndroid Build Coastguard Worker SDValue fqneg = DAG.getNode(ISD::FNEG, DL, FltVT, fq);
1291*9880d681SAndroid Build Coastguard Worker
1292*9880d681SAndroid Build Coastguard Worker // float fr = mad(fqneg, fb, fa);
1293*9880d681SAndroid Build Coastguard Worker SDValue fr = DAG.getNode(ISD::FMAD, DL, FltVT, fqneg, fb, fa);
1294*9880d681SAndroid Build Coastguard Worker
1295*9880d681SAndroid Build Coastguard Worker // int iq = (int)fq;
1296*9880d681SAndroid Build Coastguard Worker SDValue iq = DAG.getNode(ToInt, DL, IntVT, fq);
1297*9880d681SAndroid Build Coastguard Worker
1298*9880d681SAndroid Build Coastguard Worker // fr = fabs(fr);
1299*9880d681SAndroid Build Coastguard Worker fr = DAG.getNode(ISD::FABS, DL, FltVT, fr);
1300*9880d681SAndroid Build Coastguard Worker
1301*9880d681SAndroid Build Coastguard Worker // fb = fabs(fb);
1302*9880d681SAndroid Build Coastguard Worker fb = DAG.getNode(ISD::FABS, DL, FltVT, fb);
1303*9880d681SAndroid Build Coastguard Worker
1304*9880d681SAndroid Build Coastguard Worker EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
1305*9880d681SAndroid Build Coastguard Worker
1306*9880d681SAndroid Build Coastguard Worker // int cv = fr >= fb;
1307*9880d681SAndroid Build Coastguard Worker SDValue cv = DAG.getSetCC(DL, SetCCVT, fr, fb, ISD::SETOGE);
1308*9880d681SAndroid Build Coastguard Worker
1309*9880d681SAndroid Build Coastguard Worker // jq = (cv ? jq : 0);
1310*9880d681SAndroid Build Coastguard Worker jq = DAG.getNode(ISD::SELECT, DL, VT, cv, jq, DAG.getConstant(0, DL, VT));
1311*9880d681SAndroid Build Coastguard Worker
1312*9880d681SAndroid Build Coastguard Worker // dst = iq + jq;
1313*9880d681SAndroid Build Coastguard Worker SDValue Div = DAG.getNode(ISD::ADD, DL, VT, iq, jq);
1314*9880d681SAndroid Build Coastguard Worker
1315*9880d681SAndroid Build Coastguard Worker // Rem needs compensation, it's easier to recompute it
1316*9880d681SAndroid Build Coastguard Worker SDValue Rem = DAG.getNode(ISD::MUL, DL, VT, Div, RHS);
1317*9880d681SAndroid Build Coastguard Worker Rem = DAG.getNode(ISD::SUB, DL, VT, LHS, Rem);
1318*9880d681SAndroid Build Coastguard Worker
1319*9880d681SAndroid Build Coastguard Worker // Truncate to number of bits this divide really is.
1320*9880d681SAndroid Build Coastguard Worker if (Sign) {
1321*9880d681SAndroid Build Coastguard Worker SDValue InRegSize
1322*9880d681SAndroid Build Coastguard Worker = DAG.getValueType(EVT::getIntegerVT(*DAG.getContext(), DivBits));
1323*9880d681SAndroid Build Coastguard Worker Div = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Div, InRegSize);
1324*9880d681SAndroid Build Coastguard Worker Rem = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, VT, Rem, InRegSize);
1325*9880d681SAndroid Build Coastguard Worker } else {
1326*9880d681SAndroid Build Coastguard Worker SDValue TruncMask = DAG.getConstant((UINT64_C(1) << DivBits) - 1, DL, VT);
1327*9880d681SAndroid Build Coastguard Worker Div = DAG.getNode(ISD::AND, DL, VT, Div, TruncMask);
1328*9880d681SAndroid Build Coastguard Worker Rem = DAG.getNode(ISD::AND, DL, VT, Rem, TruncMask);
1329*9880d681SAndroid Build Coastguard Worker }
1330*9880d681SAndroid Build Coastguard Worker
1331*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues({ Div, Rem }, DL);
1332*9880d681SAndroid Build Coastguard Worker }
1333*9880d681SAndroid Build Coastguard Worker
LowerUDIVREM64(SDValue Op,SelectionDAG & DAG,SmallVectorImpl<SDValue> & Results) const1334*9880d681SAndroid Build Coastguard Worker void AMDGPUTargetLowering::LowerUDIVREM64(SDValue Op,
1335*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
1336*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<SDValue> &Results) const {
1337*9880d681SAndroid Build Coastguard Worker assert(Op.getValueType() == MVT::i64);
1338*9880d681SAndroid Build Coastguard Worker
1339*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1340*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1341*9880d681SAndroid Build Coastguard Worker EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
1342*9880d681SAndroid Build Coastguard Worker
1343*9880d681SAndroid Build Coastguard Worker SDValue one = DAG.getConstant(1, DL, HalfVT);
1344*9880d681SAndroid Build Coastguard Worker SDValue zero = DAG.getConstant(0, DL, HalfVT);
1345*9880d681SAndroid Build Coastguard Worker
1346*9880d681SAndroid Build Coastguard Worker //HiLo split
1347*9880d681SAndroid Build Coastguard Worker SDValue LHS = Op.getOperand(0);
1348*9880d681SAndroid Build Coastguard Worker SDValue LHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, zero);
1349*9880d681SAndroid Build Coastguard Worker SDValue LHS_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, one);
1350*9880d681SAndroid Build Coastguard Worker
1351*9880d681SAndroid Build Coastguard Worker SDValue RHS = Op.getOperand(1);
1352*9880d681SAndroid Build Coastguard Worker SDValue RHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, zero);
1353*9880d681SAndroid Build Coastguard Worker SDValue RHS_Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, one);
1354*9880d681SAndroid Build Coastguard Worker
1355*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i64 &&
1356*9880d681SAndroid Build Coastguard Worker DAG.MaskedValueIsZero(RHS, APInt::getHighBitsSet(64, 32)) &&
1357*9880d681SAndroid Build Coastguard Worker DAG.MaskedValueIsZero(LHS, APInt::getHighBitsSet(64, 32))) {
1358*9880d681SAndroid Build Coastguard Worker
1359*9880d681SAndroid Build Coastguard Worker SDValue Res = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(HalfVT, HalfVT),
1360*9880d681SAndroid Build Coastguard Worker LHS_Lo, RHS_Lo);
1361*9880d681SAndroid Build Coastguard Worker
1362*9880d681SAndroid Build Coastguard Worker SDValue DIV = DAG.getBuildVector(MVT::v2i32, DL, {Res.getValue(0), zero});
1363*9880d681SAndroid Build Coastguard Worker SDValue REM = DAG.getBuildVector(MVT::v2i32, DL, {Res.getValue(1), zero});
1364*9880d681SAndroid Build Coastguard Worker
1365*9880d681SAndroid Build Coastguard Worker Results.push_back(DAG.getNode(ISD::BITCAST, DL, MVT::i64, DIV));
1366*9880d681SAndroid Build Coastguard Worker Results.push_back(DAG.getNode(ISD::BITCAST, DL, MVT::i64, REM));
1367*9880d681SAndroid Build Coastguard Worker return;
1368*9880d681SAndroid Build Coastguard Worker }
1369*9880d681SAndroid Build Coastguard Worker
1370*9880d681SAndroid Build Coastguard Worker // Get Speculative values
1371*9880d681SAndroid Build Coastguard Worker SDValue DIV_Part = DAG.getNode(ISD::UDIV, DL, HalfVT, LHS_Hi, RHS_Lo);
1372*9880d681SAndroid Build Coastguard Worker SDValue REM_Part = DAG.getNode(ISD::UREM, DL, HalfVT, LHS_Hi, RHS_Lo);
1373*9880d681SAndroid Build Coastguard Worker
1374*9880d681SAndroid Build Coastguard Worker SDValue REM_Lo = DAG.getSelectCC(DL, RHS_Hi, zero, REM_Part, LHS_Hi, ISD::SETEQ);
1375*9880d681SAndroid Build Coastguard Worker SDValue REM = DAG.getBuildVector(MVT::v2i32, DL, {REM_Lo, zero});
1376*9880d681SAndroid Build Coastguard Worker REM = DAG.getNode(ISD::BITCAST, DL, MVT::i64, REM);
1377*9880d681SAndroid Build Coastguard Worker
1378*9880d681SAndroid Build Coastguard Worker SDValue DIV_Hi = DAG.getSelectCC(DL, RHS_Hi, zero, DIV_Part, zero, ISD::SETEQ);
1379*9880d681SAndroid Build Coastguard Worker SDValue DIV_Lo = zero;
1380*9880d681SAndroid Build Coastguard Worker
1381*9880d681SAndroid Build Coastguard Worker const unsigned halfBitWidth = HalfVT.getSizeInBits();
1382*9880d681SAndroid Build Coastguard Worker
1383*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < halfBitWidth; ++i) {
1384*9880d681SAndroid Build Coastguard Worker const unsigned bitPos = halfBitWidth - i - 1;
1385*9880d681SAndroid Build Coastguard Worker SDValue POS = DAG.getConstant(bitPos, DL, HalfVT);
1386*9880d681SAndroid Build Coastguard Worker // Get value of high bit
1387*9880d681SAndroid Build Coastguard Worker SDValue HBit = DAG.getNode(ISD::SRL, DL, HalfVT, LHS_Lo, POS);
1388*9880d681SAndroid Build Coastguard Worker HBit = DAG.getNode(ISD::AND, DL, HalfVT, HBit, one);
1389*9880d681SAndroid Build Coastguard Worker HBit = DAG.getNode(ISD::ZERO_EXTEND, DL, VT, HBit);
1390*9880d681SAndroid Build Coastguard Worker
1391*9880d681SAndroid Build Coastguard Worker // Shift
1392*9880d681SAndroid Build Coastguard Worker REM = DAG.getNode(ISD::SHL, DL, VT, REM, DAG.getConstant(1, DL, VT));
1393*9880d681SAndroid Build Coastguard Worker // Add LHS high bit
1394*9880d681SAndroid Build Coastguard Worker REM = DAG.getNode(ISD::OR, DL, VT, REM, HBit);
1395*9880d681SAndroid Build Coastguard Worker
1396*9880d681SAndroid Build Coastguard Worker SDValue BIT = DAG.getConstant(1ULL << bitPos, DL, HalfVT);
1397*9880d681SAndroid Build Coastguard Worker SDValue realBIT = DAG.getSelectCC(DL, REM, RHS, BIT, zero, ISD::SETUGE);
1398*9880d681SAndroid Build Coastguard Worker
1399*9880d681SAndroid Build Coastguard Worker DIV_Lo = DAG.getNode(ISD::OR, DL, HalfVT, DIV_Lo, realBIT);
1400*9880d681SAndroid Build Coastguard Worker
1401*9880d681SAndroid Build Coastguard Worker // Update REM
1402*9880d681SAndroid Build Coastguard Worker SDValue REM_sub = DAG.getNode(ISD::SUB, DL, VT, REM, RHS);
1403*9880d681SAndroid Build Coastguard Worker REM = DAG.getSelectCC(DL, REM, RHS, REM_sub, REM, ISD::SETUGE);
1404*9880d681SAndroid Build Coastguard Worker }
1405*9880d681SAndroid Build Coastguard Worker
1406*9880d681SAndroid Build Coastguard Worker SDValue DIV = DAG.getBuildVector(MVT::v2i32, DL, {DIV_Lo, DIV_Hi});
1407*9880d681SAndroid Build Coastguard Worker DIV = DAG.getNode(ISD::BITCAST, DL, MVT::i64, DIV);
1408*9880d681SAndroid Build Coastguard Worker Results.push_back(DIV);
1409*9880d681SAndroid Build Coastguard Worker Results.push_back(REM);
1410*9880d681SAndroid Build Coastguard Worker }
1411*9880d681SAndroid Build Coastguard Worker
LowerUDIVREM(SDValue Op,SelectionDAG & DAG) const1412*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerUDIVREM(SDValue Op,
1413*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1414*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1415*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1416*9880d681SAndroid Build Coastguard Worker
1417*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i64) {
1418*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 2> Results;
1419*9880d681SAndroid Build Coastguard Worker LowerUDIVREM64(Op, DAG, Results);
1420*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Results, DL);
1421*9880d681SAndroid Build Coastguard Worker }
1422*9880d681SAndroid Build Coastguard Worker
1423*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32) {
1424*9880d681SAndroid Build Coastguard Worker if (SDValue Res = LowerDIVREM24(Op, DAG, false))
1425*9880d681SAndroid Build Coastguard Worker return Res;
1426*9880d681SAndroid Build Coastguard Worker }
1427*9880d681SAndroid Build Coastguard Worker
1428*9880d681SAndroid Build Coastguard Worker SDValue Num = Op.getOperand(0);
1429*9880d681SAndroid Build Coastguard Worker SDValue Den = Op.getOperand(1);
1430*9880d681SAndroid Build Coastguard Worker
1431*9880d681SAndroid Build Coastguard Worker // RCP = URECIP(Den) = 2^32 / Den + e
1432*9880d681SAndroid Build Coastguard Worker // e is rounding error.
1433*9880d681SAndroid Build Coastguard Worker SDValue RCP = DAG.getNode(AMDGPUISD::URECIP, DL, VT, Den);
1434*9880d681SAndroid Build Coastguard Worker
1435*9880d681SAndroid Build Coastguard Worker // RCP_LO = mul(RCP, Den) */
1436*9880d681SAndroid Build Coastguard Worker SDValue RCP_LO = DAG.getNode(ISD::MUL, DL, VT, RCP, Den);
1437*9880d681SAndroid Build Coastguard Worker
1438*9880d681SAndroid Build Coastguard Worker // RCP_HI = mulhu (RCP, Den) */
1439*9880d681SAndroid Build Coastguard Worker SDValue RCP_HI = DAG.getNode(ISD::MULHU, DL, VT, RCP, Den);
1440*9880d681SAndroid Build Coastguard Worker
1441*9880d681SAndroid Build Coastguard Worker // NEG_RCP_LO = -RCP_LO
1442*9880d681SAndroid Build Coastguard Worker SDValue NEG_RCP_LO = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT),
1443*9880d681SAndroid Build Coastguard Worker RCP_LO);
1444*9880d681SAndroid Build Coastguard Worker
1445*9880d681SAndroid Build Coastguard Worker // ABS_RCP_LO = (RCP_HI == 0 ? NEG_RCP_LO : RCP_LO)
1446*9880d681SAndroid Build Coastguard Worker SDValue ABS_RCP_LO = DAG.getSelectCC(DL, RCP_HI, DAG.getConstant(0, DL, VT),
1447*9880d681SAndroid Build Coastguard Worker NEG_RCP_LO, RCP_LO,
1448*9880d681SAndroid Build Coastguard Worker ISD::SETEQ);
1449*9880d681SAndroid Build Coastguard Worker // Calculate the rounding error from the URECIP instruction
1450*9880d681SAndroid Build Coastguard Worker // E = mulhu(ABS_RCP_LO, RCP)
1451*9880d681SAndroid Build Coastguard Worker SDValue E = DAG.getNode(ISD::MULHU, DL, VT, ABS_RCP_LO, RCP);
1452*9880d681SAndroid Build Coastguard Worker
1453*9880d681SAndroid Build Coastguard Worker // RCP_A_E = RCP + E
1454*9880d681SAndroid Build Coastguard Worker SDValue RCP_A_E = DAG.getNode(ISD::ADD, DL, VT, RCP, E);
1455*9880d681SAndroid Build Coastguard Worker
1456*9880d681SAndroid Build Coastguard Worker // RCP_S_E = RCP - E
1457*9880d681SAndroid Build Coastguard Worker SDValue RCP_S_E = DAG.getNode(ISD::SUB, DL, VT, RCP, E);
1458*9880d681SAndroid Build Coastguard Worker
1459*9880d681SAndroid Build Coastguard Worker // Tmp0 = (RCP_HI == 0 ? RCP_A_E : RCP_SUB_E)
1460*9880d681SAndroid Build Coastguard Worker SDValue Tmp0 = DAG.getSelectCC(DL, RCP_HI, DAG.getConstant(0, DL, VT),
1461*9880d681SAndroid Build Coastguard Worker RCP_A_E, RCP_S_E,
1462*9880d681SAndroid Build Coastguard Worker ISD::SETEQ);
1463*9880d681SAndroid Build Coastguard Worker // Quotient = mulhu(Tmp0, Num)
1464*9880d681SAndroid Build Coastguard Worker SDValue Quotient = DAG.getNode(ISD::MULHU, DL, VT, Tmp0, Num);
1465*9880d681SAndroid Build Coastguard Worker
1466*9880d681SAndroid Build Coastguard Worker // Num_S_Remainder = Quotient * Den
1467*9880d681SAndroid Build Coastguard Worker SDValue Num_S_Remainder = DAG.getNode(ISD::MUL, DL, VT, Quotient, Den);
1468*9880d681SAndroid Build Coastguard Worker
1469*9880d681SAndroid Build Coastguard Worker // Remainder = Num - Num_S_Remainder
1470*9880d681SAndroid Build Coastguard Worker SDValue Remainder = DAG.getNode(ISD::SUB, DL, VT, Num, Num_S_Remainder);
1471*9880d681SAndroid Build Coastguard Worker
1472*9880d681SAndroid Build Coastguard Worker // Remainder_GE_Den = (Remainder >= Den ? -1 : 0)
1473*9880d681SAndroid Build Coastguard Worker SDValue Remainder_GE_Den = DAG.getSelectCC(DL, Remainder, Den,
1474*9880d681SAndroid Build Coastguard Worker DAG.getConstant(-1, DL, VT),
1475*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, VT),
1476*9880d681SAndroid Build Coastguard Worker ISD::SETUGE);
1477*9880d681SAndroid Build Coastguard Worker // Remainder_GE_Zero = (Num >= Num_S_Remainder ? -1 : 0)
1478*9880d681SAndroid Build Coastguard Worker SDValue Remainder_GE_Zero = DAG.getSelectCC(DL, Num,
1479*9880d681SAndroid Build Coastguard Worker Num_S_Remainder,
1480*9880d681SAndroid Build Coastguard Worker DAG.getConstant(-1, DL, VT),
1481*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, DL, VT),
1482*9880d681SAndroid Build Coastguard Worker ISD::SETUGE);
1483*9880d681SAndroid Build Coastguard Worker // Tmp1 = Remainder_GE_Den & Remainder_GE_Zero
1484*9880d681SAndroid Build Coastguard Worker SDValue Tmp1 = DAG.getNode(ISD::AND, DL, VT, Remainder_GE_Den,
1485*9880d681SAndroid Build Coastguard Worker Remainder_GE_Zero);
1486*9880d681SAndroid Build Coastguard Worker
1487*9880d681SAndroid Build Coastguard Worker // Calculate Division result:
1488*9880d681SAndroid Build Coastguard Worker
1489*9880d681SAndroid Build Coastguard Worker // Quotient_A_One = Quotient + 1
1490*9880d681SAndroid Build Coastguard Worker SDValue Quotient_A_One = DAG.getNode(ISD::ADD, DL, VT, Quotient,
1491*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, VT));
1492*9880d681SAndroid Build Coastguard Worker
1493*9880d681SAndroid Build Coastguard Worker // Quotient_S_One = Quotient - 1
1494*9880d681SAndroid Build Coastguard Worker SDValue Quotient_S_One = DAG.getNode(ISD::SUB, DL, VT, Quotient,
1495*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, DL, VT));
1496*9880d681SAndroid Build Coastguard Worker
1497*9880d681SAndroid Build Coastguard Worker // Div = (Tmp1 == 0 ? Quotient : Quotient_A_One)
1498*9880d681SAndroid Build Coastguard Worker SDValue Div = DAG.getSelectCC(DL, Tmp1, DAG.getConstant(0, DL, VT),
1499*9880d681SAndroid Build Coastguard Worker Quotient, Quotient_A_One, ISD::SETEQ);
1500*9880d681SAndroid Build Coastguard Worker
1501*9880d681SAndroid Build Coastguard Worker // Div = (Remainder_GE_Zero == 0 ? Quotient_S_One : Div)
1502*9880d681SAndroid Build Coastguard Worker Div = DAG.getSelectCC(DL, Remainder_GE_Zero, DAG.getConstant(0, DL, VT),
1503*9880d681SAndroid Build Coastguard Worker Quotient_S_One, Div, ISD::SETEQ);
1504*9880d681SAndroid Build Coastguard Worker
1505*9880d681SAndroid Build Coastguard Worker // Calculate Rem result:
1506*9880d681SAndroid Build Coastguard Worker
1507*9880d681SAndroid Build Coastguard Worker // Remainder_S_Den = Remainder - Den
1508*9880d681SAndroid Build Coastguard Worker SDValue Remainder_S_Den = DAG.getNode(ISD::SUB, DL, VT, Remainder, Den);
1509*9880d681SAndroid Build Coastguard Worker
1510*9880d681SAndroid Build Coastguard Worker // Remainder_A_Den = Remainder + Den
1511*9880d681SAndroid Build Coastguard Worker SDValue Remainder_A_Den = DAG.getNode(ISD::ADD, DL, VT, Remainder, Den);
1512*9880d681SAndroid Build Coastguard Worker
1513*9880d681SAndroid Build Coastguard Worker // Rem = (Tmp1 == 0 ? Remainder : Remainder_S_Den)
1514*9880d681SAndroid Build Coastguard Worker SDValue Rem = DAG.getSelectCC(DL, Tmp1, DAG.getConstant(0, DL, VT),
1515*9880d681SAndroid Build Coastguard Worker Remainder, Remainder_S_Den, ISD::SETEQ);
1516*9880d681SAndroid Build Coastguard Worker
1517*9880d681SAndroid Build Coastguard Worker // Rem = (Remainder_GE_Zero == 0 ? Remainder_A_Den : Rem)
1518*9880d681SAndroid Build Coastguard Worker Rem = DAG.getSelectCC(DL, Remainder_GE_Zero, DAG.getConstant(0, DL, VT),
1519*9880d681SAndroid Build Coastguard Worker Remainder_A_Den, Rem, ISD::SETEQ);
1520*9880d681SAndroid Build Coastguard Worker SDValue Ops[2] = {
1521*9880d681SAndroid Build Coastguard Worker Div,
1522*9880d681SAndroid Build Coastguard Worker Rem
1523*9880d681SAndroid Build Coastguard Worker };
1524*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, DL);
1525*9880d681SAndroid Build Coastguard Worker }
1526*9880d681SAndroid Build Coastguard Worker
LowerSDIVREM(SDValue Op,SelectionDAG & DAG) const1527*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerSDIVREM(SDValue Op,
1528*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
1529*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
1530*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1531*9880d681SAndroid Build Coastguard Worker
1532*9880d681SAndroid Build Coastguard Worker SDValue LHS = Op.getOperand(0);
1533*9880d681SAndroid Build Coastguard Worker SDValue RHS = Op.getOperand(1);
1534*9880d681SAndroid Build Coastguard Worker
1535*9880d681SAndroid Build Coastguard Worker SDValue Zero = DAG.getConstant(0, DL, VT);
1536*9880d681SAndroid Build Coastguard Worker SDValue NegOne = DAG.getConstant(-1, DL, VT);
1537*9880d681SAndroid Build Coastguard Worker
1538*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i32) {
1539*9880d681SAndroid Build Coastguard Worker if (SDValue Res = LowerDIVREM24(Op, DAG, true))
1540*9880d681SAndroid Build Coastguard Worker return Res;
1541*9880d681SAndroid Build Coastguard Worker }
1542*9880d681SAndroid Build Coastguard Worker
1543*9880d681SAndroid Build Coastguard Worker if (VT == MVT::i64 &&
1544*9880d681SAndroid Build Coastguard Worker DAG.ComputeNumSignBits(LHS) > 32 &&
1545*9880d681SAndroid Build Coastguard Worker DAG.ComputeNumSignBits(RHS) > 32) {
1546*9880d681SAndroid Build Coastguard Worker EVT HalfVT = VT.getHalfSizedIntegerVT(*DAG.getContext());
1547*9880d681SAndroid Build Coastguard Worker
1548*9880d681SAndroid Build Coastguard Worker //HiLo split
1549*9880d681SAndroid Build Coastguard Worker SDValue LHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, LHS, Zero);
1550*9880d681SAndroid Build Coastguard Worker SDValue RHS_Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, HalfVT, RHS, Zero);
1551*9880d681SAndroid Build Coastguard Worker SDValue DIVREM = DAG.getNode(ISD::SDIVREM, DL, DAG.getVTList(HalfVT, HalfVT),
1552*9880d681SAndroid Build Coastguard Worker LHS_Lo, RHS_Lo);
1553*9880d681SAndroid Build Coastguard Worker SDValue Res[2] = {
1554*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::SIGN_EXTEND, DL, VT, DIVREM.getValue(0)),
1555*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::SIGN_EXTEND, DL, VT, DIVREM.getValue(1))
1556*9880d681SAndroid Build Coastguard Worker };
1557*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Res, DL);
1558*9880d681SAndroid Build Coastguard Worker }
1559*9880d681SAndroid Build Coastguard Worker
1560*9880d681SAndroid Build Coastguard Worker SDValue LHSign = DAG.getSelectCC(DL, LHS, Zero, NegOne, Zero, ISD::SETLT);
1561*9880d681SAndroid Build Coastguard Worker SDValue RHSign = DAG.getSelectCC(DL, RHS, Zero, NegOne, Zero, ISD::SETLT);
1562*9880d681SAndroid Build Coastguard Worker SDValue DSign = DAG.getNode(ISD::XOR, DL, VT, LHSign, RHSign);
1563*9880d681SAndroid Build Coastguard Worker SDValue RSign = LHSign; // Remainder sign is the same as LHS
1564*9880d681SAndroid Build Coastguard Worker
1565*9880d681SAndroid Build Coastguard Worker LHS = DAG.getNode(ISD::ADD, DL, VT, LHS, LHSign);
1566*9880d681SAndroid Build Coastguard Worker RHS = DAG.getNode(ISD::ADD, DL, VT, RHS, RHSign);
1567*9880d681SAndroid Build Coastguard Worker
1568*9880d681SAndroid Build Coastguard Worker LHS = DAG.getNode(ISD::XOR, DL, VT, LHS, LHSign);
1569*9880d681SAndroid Build Coastguard Worker RHS = DAG.getNode(ISD::XOR, DL, VT, RHS, RHSign);
1570*9880d681SAndroid Build Coastguard Worker
1571*9880d681SAndroid Build Coastguard Worker SDValue Div = DAG.getNode(ISD::UDIVREM, DL, DAG.getVTList(VT, VT), LHS, RHS);
1572*9880d681SAndroid Build Coastguard Worker SDValue Rem = Div.getValue(1);
1573*9880d681SAndroid Build Coastguard Worker
1574*9880d681SAndroid Build Coastguard Worker Div = DAG.getNode(ISD::XOR, DL, VT, Div, DSign);
1575*9880d681SAndroid Build Coastguard Worker Rem = DAG.getNode(ISD::XOR, DL, VT, Rem, RSign);
1576*9880d681SAndroid Build Coastguard Worker
1577*9880d681SAndroid Build Coastguard Worker Div = DAG.getNode(ISD::SUB, DL, VT, Div, DSign);
1578*9880d681SAndroid Build Coastguard Worker Rem = DAG.getNode(ISD::SUB, DL, VT, Rem, RSign);
1579*9880d681SAndroid Build Coastguard Worker
1580*9880d681SAndroid Build Coastguard Worker SDValue Res[2] = {
1581*9880d681SAndroid Build Coastguard Worker Div,
1582*9880d681SAndroid Build Coastguard Worker Rem
1583*9880d681SAndroid Build Coastguard Worker };
1584*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Res, DL);
1585*9880d681SAndroid Build Coastguard Worker }
1586*9880d681SAndroid Build Coastguard Worker
1587*9880d681SAndroid Build Coastguard Worker // (frem x, y) -> (fsub x, (fmul (ftrunc (fdiv x, y)), y))
LowerFREM(SDValue Op,SelectionDAG & DAG) const1588*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFREM(SDValue Op, SelectionDAG &DAG) const {
1589*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1590*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1591*9880d681SAndroid Build Coastguard Worker SDValue X = Op.getOperand(0);
1592*9880d681SAndroid Build Coastguard Worker SDValue Y = Op.getOperand(1);
1593*9880d681SAndroid Build Coastguard Worker
1594*9880d681SAndroid Build Coastguard Worker // TODO: Should this propagate fast-math-flags?
1595*9880d681SAndroid Build Coastguard Worker
1596*9880d681SAndroid Build Coastguard Worker SDValue Div = DAG.getNode(ISD::FDIV, SL, VT, X, Y);
1597*9880d681SAndroid Build Coastguard Worker SDValue Floor = DAG.getNode(ISD::FTRUNC, SL, VT, Div);
1598*9880d681SAndroid Build Coastguard Worker SDValue Mul = DAG.getNode(ISD::FMUL, SL, VT, Floor, Y);
1599*9880d681SAndroid Build Coastguard Worker
1600*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::FSUB, SL, VT, X, Mul);
1601*9880d681SAndroid Build Coastguard Worker }
1602*9880d681SAndroid Build Coastguard Worker
LowerFCEIL(SDValue Op,SelectionDAG & DAG) const1603*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFCEIL(SDValue Op, SelectionDAG &DAG) const {
1604*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1605*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
1606*9880d681SAndroid Build Coastguard Worker
1607*9880d681SAndroid Build Coastguard Worker // result = trunc(src)
1608*9880d681SAndroid Build Coastguard Worker // if (src > 0.0 && src != result)
1609*9880d681SAndroid Build Coastguard Worker // result += 1.0
1610*9880d681SAndroid Build Coastguard Worker
1611*9880d681SAndroid Build Coastguard Worker SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);
1612*9880d681SAndroid Build Coastguard Worker
1613*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f64);
1614*9880d681SAndroid Build Coastguard Worker const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f64);
1615*9880d681SAndroid Build Coastguard Worker
1616*9880d681SAndroid Build Coastguard Worker EVT SetCCVT =
1617*9880d681SAndroid Build Coastguard Worker getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
1618*9880d681SAndroid Build Coastguard Worker
1619*9880d681SAndroid Build Coastguard Worker SDValue Lt0 = DAG.getSetCC(SL, SetCCVT, Src, Zero, ISD::SETOGT);
1620*9880d681SAndroid Build Coastguard Worker SDValue NeTrunc = DAG.getSetCC(SL, SetCCVT, Src, Trunc, ISD::SETONE);
1621*9880d681SAndroid Build Coastguard Worker SDValue And = DAG.getNode(ISD::AND, SL, SetCCVT, Lt0, NeTrunc);
1622*9880d681SAndroid Build Coastguard Worker
1623*9880d681SAndroid Build Coastguard Worker SDValue Add = DAG.getNode(ISD::SELECT, SL, MVT::f64, And, One, Zero);
1624*9880d681SAndroid Build Coastguard Worker // TODO: Should this propagate fast-math-flags?
1625*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::FADD, SL, MVT::f64, Trunc, Add);
1626*9880d681SAndroid Build Coastguard Worker }
1627*9880d681SAndroid Build Coastguard Worker
extractF64Exponent(SDValue Hi,const SDLoc & SL,SelectionDAG & DAG)1628*9880d681SAndroid Build Coastguard Worker static SDValue extractF64Exponent(SDValue Hi, const SDLoc &SL,
1629*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) {
1630*9880d681SAndroid Build Coastguard Worker const unsigned FractBits = 52;
1631*9880d681SAndroid Build Coastguard Worker const unsigned ExpBits = 11;
1632*9880d681SAndroid Build Coastguard Worker
1633*9880d681SAndroid Build Coastguard Worker SDValue ExpPart = DAG.getNode(AMDGPUISD::BFE_U32, SL, MVT::i32,
1634*9880d681SAndroid Build Coastguard Worker Hi,
1635*9880d681SAndroid Build Coastguard Worker DAG.getConstant(FractBits - 32, SL, MVT::i32),
1636*9880d681SAndroid Build Coastguard Worker DAG.getConstant(ExpBits, SL, MVT::i32));
1637*9880d681SAndroid Build Coastguard Worker SDValue Exp = DAG.getNode(ISD::SUB, SL, MVT::i32, ExpPart,
1638*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1023, SL, MVT::i32));
1639*9880d681SAndroid Build Coastguard Worker
1640*9880d681SAndroid Build Coastguard Worker return Exp;
1641*9880d681SAndroid Build Coastguard Worker }
1642*9880d681SAndroid Build Coastguard Worker
LowerFTRUNC(SDValue Op,SelectionDAG & DAG) const1643*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFTRUNC(SDValue Op, SelectionDAG &DAG) const {
1644*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1645*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
1646*9880d681SAndroid Build Coastguard Worker
1647*9880d681SAndroid Build Coastguard Worker assert(Op.getValueType() == MVT::f64);
1648*9880d681SAndroid Build Coastguard Worker
1649*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1650*9880d681SAndroid Build Coastguard Worker const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1651*9880d681SAndroid Build Coastguard Worker
1652*9880d681SAndroid Build Coastguard Worker SDValue VecSrc = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Src);
1653*9880d681SAndroid Build Coastguard Worker
1654*9880d681SAndroid Build Coastguard Worker // Extract the upper half, since this is where we will find the sign and
1655*9880d681SAndroid Build Coastguard Worker // exponent.
1656*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, VecSrc, One);
1657*9880d681SAndroid Build Coastguard Worker
1658*9880d681SAndroid Build Coastguard Worker SDValue Exp = extractF64Exponent(Hi, SL, DAG);
1659*9880d681SAndroid Build Coastguard Worker
1660*9880d681SAndroid Build Coastguard Worker const unsigned FractBits = 52;
1661*9880d681SAndroid Build Coastguard Worker
1662*9880d681SAndroid Build Coastguard Worker // Extract the sign bit.
1663*9880d681SAndroid Build Coastguard Worker const SDValue SignBitMask = DAG.getConstant(UINT32_C(1) << 31, SL, MVT::i32);
1664*9880d681SAndroid Build Coastguard Worker SDValue SignBit = DAG.getNode(ISD::AND, SL, MVT::i32, Hi, SignBitMask);
1665*9880d681SAndroid Build Coastguard Worker
1666*9880d681SAndroid Build Coastguard Worker // Extend back to to 64-bits.
1667*9880d681SAndroid Build Coastguard Worker SDValue SignBit64 = DAG.getBuildVector(MVT::v2i32, SL, {Zero, SignBit});
1668*9880d681SAndroid Build Coastguard Worker SignBit64 = DAG.getNode(ISD::BITCAST, SL, MVT::i64, SignBit64);
1669*9880d681SAndroid Build Coastguard Worker
1670*9880d681SAndroid Build Coastguard Worker SDValue BcInt = DAG.getNode(ISD::BITCAST, SL, MVT::i64, Src);
1671*9880d681SAndroid Build Coastguard Worker const SDValue FractMask
1672*9880d681SAndroid Build Coastguard Worker = DAG.getConstant((UINT64_C(1) << FractBits) - 1, SL, MVT::i64);
1673*9880d681SAndroid Build Coastguard Worker
1674*9880d681SAndroid Build Coastguard Worker SDValue Shr = DAG.getNode(ISD::SRA, SL, MVT::i64, FractMask, Exp);
1675*9880d681SAndroid Build Coastguard Worker SDValue Not = DAG.getNOT(SL, Shr, MVT::i64);
1676*9880d681SAndroid Build Coastguard Worker SDValue Tmp0 = DAG.getNode(ISD::AND, SL, MVT::i64, BcInt, Not);
1677*9880d681SAndroid Build Coastguard Worker
1678*9880d681SAndroid Build Coastguard Worker EVT SetCCVT =
1679*9880d681SAndroid Build Coastguard Worker getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i32);
1680*9880d681SAndroid Build Coastguard Worker
1681*9880d681SAndroid Build Coastguard Worker const SDValue FiftyOne = DAG.getConstant(FractBits - 1, SL, MVT::i32);
1682*9880d681SAndroid Build Coastguard Worker
1683*9880d681SAndroid Build Coastguard Worker SDValue ExpLt0 = DAG.getSetCC(SL, SetCCVT, Exp, Zero, ISD::SETLT);
1684*9880d681SAndroid Build Coastguard Worker SDValue ExpGt51 = DAG.getSetCC(SL, SetCCVT, Exp, FiftyOne, ISD::SETGT);
1685*9880d681SAndroid Build Coastguard Worker
1686*9880d681SAndroid Build Coastguard Worker SDValue Tmp1 = DAG.getNode(ISD::SELECT, SL, MVT::i64, ExpLt0, SignBit64, Tmp0);
1687*9880d681SAndroid Build Coastguard Worker SDValue Tmp2 = DAG.getNode(ISD::SELECT, SL, MVT::i64, ExpGt51, BcInt, Tmp1);
1688*9880d681SAndroid Build Coastguard Worker
1689*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SL, MVT::f64, Tmp2);
1690*9880d681SAndroid Build Coastguard Worker }
1691*9880d681SAndroid Build Coastguard Worker
LowerFRINT(SDValue Op,SelectionDAG & DAG) const1692*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFRINT(SDValue Op, SelectionDAG &DAG) const {
1693*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1694*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
1695*9880d681SAndroid Build Coastguard Worker
1696*9880d681SAndroid Build Coastguard Worker assert(Op.getValueType() == MVT::f64);
1697*9880d681SAndroid Build Coastguard Worker
1698*9880d681SAndroid Build Coastguard Worker APFloat C1Val(APFloat::IEEEdouble, "0x1.0p+52");
1699*9880d681SAndroid Build Coastguard Worker SDValue C1 = DAG.getConstantFP(C1Val, SL, MVT::f64);
1700*9880d681SAndroid Build Coastguard Worker SDValue CopySign = DAG.getNode(ISD::FCOPYSIGN, SL, MVT::f64, C1, Src);
1701*9880d681SAndroid Build Coastguard Worker
1702*9880d681SAndroid Build Coastguard Worker // TODO: Should this propagate fast-math-flags?
1703*9880d681SAndroid Build Coastguard Worker
1704*9880d681SAndroid Build Coastguard Worker SDValue Tmp1 = DAG.getNode(ISD::FADD, SL, MVT::f64, Src, CopySign);
1705*9880d681SAndroid Build Coastguard Worker SDValue Tmp2 = DAG.getNode(ISD::FSUB, SL, MVT::f64, Tmp1, CopySign);
1706*9880d681SAndroid Build Coastguard Worker
1707*9880d681SAndroid Build Coastguard Worker SDValue Fabs = DAG.getNode(ISD::FABS, SL, MVT::f64, Src);
1708*9880d681SAndroid Build Coastguard Worker
1709*9880d681SAndroid Build Coastguard Worker APFloat C2Val(APFloat::IEEEdouble, "0x1.fffffffffffffp+51");
1710*9880d681SAndroid Build Coastguard Worker SDValue C2 = DAG.getConstantFP(C2Val, SL, MVT::f64);
1711*9880d681SAndroid Build Coastguard Worker
1712*9880d681SAndroid Build Coastguard Worker EVT SetCCVT =
1713*9880d681SAndroid Build Coastguard Worker getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
1714*9880d681SAndroid Build Coastguard Worker SDValue Cond = DAG.getSetCC(SL, SetCCVT, Fabs, C2, ISD::SETOGT);
1715*9880d681SAndroid Build Coastguard Worker
1716*9880d681SAndroid Build Coastguard Worker return DAG.getSelect(SL, MVT::f64, Cond, Src, Tmp2);
1717*9880d681SAndroid Build Coastguard Worker }
1718*9880d681SAndroid Build Coastguard Worker
LowerFNEARBYINT(SDValue Op,SelectionDAG & DAG) const1719*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFNEARBYINT(SDValue Op, SelectionDAG &DAG) const {
1720*9880d681SAndroid Build Coastguard Worker // FNEARBYINT and FRINT are the same, except in their handling of FP
1721*9880d681SAndroid Build Coastguard Worker // exceptions. Those aren't really meaningful for us, and OpenCL only has
1722*9880d681SAndroid Build Coastguard Worker // rint, so just treat them as equivalent.
1723*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::FRINT, SDLoc(Op), Op.getValueType(), Op.getOperand(0));
1724*9880d681SAndroid Build Coastguard Worker }
1725*9880d681SAndroid Build Coastguard Worker
1726*9880d681SAndroid Build Coastguard Worker // XXX - May require not supporting f32 denormals?
LowerFROUND32(SDValue Op,SelectionDAG & DAG) const1727*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFROUND32(SDValue Op, SelectionDAG &DAG) const {
1728*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1729*9880d681SAndroid Build Coastguard Worker SDValue X = Op.getOperand(0);
1730*9880d681SAndroid Build Coastguard Worker
1731*9880d681SAndroid Build Coastguard Worker SDValue T = DAG.getNode(ISD::FTRUNC, SL, MVT::f32, X);
1732*9880d681SAndroid Build Coastguard Worker
1733*9880d681SAndroid Build Coastguard Worker // TODO: Should this propagate fast-math-flags?
1734*9880d681SAndroid Build Coastguard Worker
1735*9880d681SAndroid Build Coastguard Worker SDValue Diff = DAG.getNode(ISD::FSUB, SL, MVT::f32, X, T);
1736*9880d681SAndroid Build Coastguard Worker
1737*9880d681SAndroid Build Coastguard Worker SDValue AbsDiff = DAG.getNode(ISD::FABS, SL, MVT::f32, Diff);
1738*9880d681SAndroid Build Coastguard Worker
1739*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f32);
1740*9880d681SAndroid Build Coastguard Worker const SDValue One = DAG.getConstantFP(1.0, SL, MVT::f32);
1741*9880d681SAndroid Build Coastguard Worker const SDValue Half = DAG.getConstantFP(0.5, SL, MVT::f32);
1742*9880d681SAndroid Build Coastguard Worker
1743*9880d681SAndroid Build Coastguard Worker SDValue SignOne = DAG.getNode(ISD::FCOPYSIGN, SL, MVT::f32, One, X);
1744*9880d681SAndroid Build Coastguard Worker
1745*9880d681SAndroid Build Coastguard Worker EVT SetCCVT =
1746*9880d681SAndroid Build Coastguard Worker getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f32);
1747*9880d681SAndroid Build Coastguard Worker
1748*9880d681SAndroid Build Coastguard Worker SDValue Cmp = DAG.getSetCC(SL, SetCCVT, AbsDiff, Half, ISD::SETOGE);
1749*9880d681SAndroid Build Coastguard Worker
1750*9880d681SAndroid Build Coastguard Worker SDValue Sel = DAG.getNode(ISD::SELECT, SL, MVT::f32, Cmp, SignOne, Zero);
1751*9880d681SAndroid Build Coastguard Worker
1752*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::FADD, SL, MVT::f32, T, Sel);
1753*9880d681SAndroid Build Coastguard Worker }
1754*9880d681SAndroid Build Coastguard Worker
LowerFROUND64(SDValue Op,SelectionDAG & DAG) const1755*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFROUND64(SDValue Op, SelectionDAG &DAG) const {
1756*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1757*9880d681SAndroid Build Coastguard Worker SDValue X = Op.getOperand(0);
1758*9880d681SAndroid Build Coastguard Worker
1759*9880d681SAndroid Build Coastguard Worker SDValue L = DAG.getNode(ISD::BITCAST, SL, MVT::i64, X);
1760*9880d681SAndroid Build Coastguard Worker
1761*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1762*9880d681SAndroid Build Coastguard Worker const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1763*9880d681SAndroid Build Coastguard Worker const SDValue NegOne = DAG.getConstant(-1, SL, MVT::i32);
1764*9880d681SAndroid Build Coastguard Worker const SDValue FiftyOne = DAG.getConstant(51, SL, MVT::i32);
1765*9880d681SAndroid Build Coastguard Worker EVT SetCCVT =
1766*9880d681SAndroid Build Coastguard Worker getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::i32);
1767*9880d681SAndroid Build Coastguard Worker
1768*9880d681SAndroid Build Coastguard Worker SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, X);
1769*9880d681SAndroid Build Coastguard Worker
1770*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BC, One);
1771*9880d681SAndroid Build Coastguard Worker
1772*9880d681SAndroid Build Coastguard Worker SDValue Exp = extractF64Exponent(Hi, SL, DAG);
1773*9880d681SAndroid Build Coastguard Worker
1774*9880d681SAndroid Build Coastguard Worker const SDValue Mask = DAG.getConstant(INT64_C(0x000fffffffffffff), SL,
1775*9880d681SAndroid Build Coastguard Worker MVT::i64);
1776*9880d681SAndroid Build Coastguard Worker
1777*9880d681SAndroid Build Coastguard Worker SDValue M = DAG.getNode(ISD::SRA, SL, MVT::i64, Mask, Exp);
1778*9880d681SAndroid Build Coastguard Worker SDValue D = DAG.getNode(ISD::SRA, SL, MVT::i64,
1779*9880d681SAndroid Build Coastguard Worker DAG.getConstant(INT64_C(0x0008000000000000), SL,
1780*9880d681SAndroid Build Coastguard Worker MVT::i64),
1781*9880d681SAndroid Build Coastguard Worker Exp);
1782*9880d681SAndroid Build Coastguard Worker
1783*9880d681SAndroid Build Coastguard Worker SDValue Tmp0 = DAG.getNode(ISD::AND, SL, MVT::i64, L, M);
1784*9880d681SAndroid Build Coastguard Worker SDValue Tmp1 = DAG.getSetCC(SL, SetCCVT,
1785*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, SL, MVT::i64), Tmp0,
1786*9880d681SAndroid Build Coastguard Worker ISD::SETNE);
1787*9880d681SAndroid Build Coastguard Worker
1788*9880d681SAndroid Build Coastguard Worker SDValue Tmp2 = DAG.getNode(ISD::SELECT, SL, MVT::i64, Tmp1,
1789*9880d681SAndroid Build Coastguard Worker D, DAG.getConstant(0, SL, MVT::i64));
1790*9880d681SAndroid Build Coastguard Worker SDValue K = DAG.getNode(ISD::ADD, SL, MVT::i64, L, Tmp2);
1791*9880d681SAndroid Build Coastguard Worker
1792*9880d681SAndroid Build Coastguard Worker K = DAG.getNode(ISD::AND, SL, MVT::i64, K, DAG.getNOT(SL, M, MVT::i64));
1793*9880d681SAndroid Build Coastguard Worker K = DAG.getNode(ISD::BITCAST, SL, MVT::f64, K);
1794*9880d681SAndroid Build Coastguard Worker
1795*9880d681SAndroid Build Coastguard Worker SDValue ExpLt0 = DAG.getSetCC(SL, SetCCVT, Exp, Zero, ISD::SETLT);
1796*9880d681SAndroid Build Coastguard Worker SDValue ExpGt51 = DAG.getSetCC(SL, SetCCVT, Exp, FiftyOne, ISD::SETGT);
1797*9880d681SAndroid Build Coastguard Worker SDValue ExpEqNegOne = DAG.getSetCC(SL, SetCCVT, NegOne, Exp, ISD::SETEQ);
1798*9880d681SAndroid Build Coastguard Worker
1799*9880d681SAndroid Build Coastguard Worker SDValue Mag = DAG.getNode(ISD::SELECT, SL, MVT::f64,
1800*9880d681SAndroid Build Coastguard Worker ExpEqNegOne,
1801*9880d681SAndroid Build Coastguard Worker DAG.getConstantFP(1.0, SL, MVT::f64),
1802*9880d681SAndroid Build Coastguard Worker DAG.getConstantFP(0.0, SL, MVT::f64));
1803*9880d681SAndroid Build Coastguard Worker
1804*9880d681SAndroid Build Coastguard Worker SDValue S = DAG.getNode(ISD::FCOPYSIGN, SL, MVT::f64, Mag, X);
1805*9880d681SAndroid Build Coastguard Worker
1806*9880d681SAndroid Build Coastguard Worker K = DAG.getNode(ISD::SELECT, SL, MVT::f64, ExpLt0, S, K);
1807*9880d681SAndroid Build Coastguard Worker K = DAG.getNode(ISD::SELECT, SL, MVT::f64, ExpGt51, X, K);
1808*9880d681SAndroid Build Coastguard Worker
1809*9880d681SAndroid Build Coastguard Worker return K;
1810*9880d681SAndroid Build Coastguard Worker }
1811*9880d681SAndroid Build Coastguard Worker
LowerFROUND(SDValue Op,SelectionDAG & DAG) const1812*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFROUND(SDValue Op, SelectionDAG &DAG) const {
1813*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
1814*9880d681SAndroid Build Coastguard Worker
1815*9880d681SAndroid Build Coastguard Worker if (VT == MVT::f32)
1816*9880d681SAndroid Build Coastguard Worker return LowerFROUND32(Op, DAG);
1817*9880d681SAndroid Build Coastguard Worker
1818*9880d681SAndroid Build Coastguard Worker if (VT == MVT::f64)
1819*9880d681SAndroid Build Coastguard Worker return LowerFROUND64(Op, DAG);
1820*9880d681SAndroid Build Coastguard Worker
1821*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unhandled type");
1822*9880d681SAndroid Build Coastguard Worker }
1823*9880d681SAndroid Build Coastguard Worker
LowerFFLOOR(SDValue Op,SelectionDAG & DAG) const1824*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFFLOOR(SDValue Op, SelectionDAG &DAG) const {
1825*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1826*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
1827*9880d681SAndroid Build Coastguard Worker
1828*9880d681SAndroid Build Coastguard Worker // result = trunc(src);
1829*9880d681SAndroid Build Coastguard Worker // if (src < 0.0 && src != result)
1830*9880d681SAndroid Build Coastguard Worker // result += -1.0.
1831*9880d681SAndroid Build Coastguard Worker
1832*9880d681SAndroid Build Coastguard Worker SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);
1833*9880d681SAndroid Build Coastguard Worker
1834*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstantFP(0.0, SL, MVT::f64);
1835*9880d681SAndroid Build Coastguard Worker const SDValue NegOne = DAG.getConstantFP(-1.0, SL, MVT::f64);
1836*9880d681SAndroid Build Coastguard Worker
1837*9880d681SAndroid Build Coastguard Worker EVT SetCCVT =
1838*9880d681SAndroid Build Coastguard Worker getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), MVT::f64);
1839*9880d681SAndroid Build Coastguard Worker
1840*9880d681SAndroid Build Coastguard Worker SDValue Lt0 = DAG.getSetCC(SL, SetCCVT, Src, Zero, ISD::SETOLT);
1841*9880d681SAndroid Build Coastguard Worker SDValue NeTrunc = DAG.getSetCC(SL, SetCCVT, Src, Trunc, ISD::SETONE);
1842*9880d681SAndroid Build Coastguard Worker SDValue And = DAG.getNode(ISD::AND, SL, SetCCVT, Lt0, NeTrunc);
1843*9880d681SAndroid Build Coastguard Worker
1844*9880d681SAndroid Build Coastguard Worker SDValue Add = DAG.getNode(ISD::SELECT, SL, MVT::f64, And, NegOne, Zero);
1845*9880d681SAndroid Build Coastguard Worker // TODO: Should this propagate fast-math-flags?
1846*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::FADD, SL, MVT::f64, Trunc, Add);
1847*9880d681SAndroid Build Coastguard Worker }
1848*9880d681SAndroid Build Coastguard Worker
LowerCTLZ(SDValue Op,SelectionDAG & DAG) const1849*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerCTLZ(SDValue Op, SelectionDAG &DAG) const {
1850*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1851*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
1852*9880d681SAndroid Build Coastguard Worker bool ZeroUndef = Op.getOpcode() == ISD::CTLZ_ZERO_UNDEF;
1853*9880d681SAndroid Build Coastguard Worker
1854*9880d681SAndroid Build Coastguard Worker if (ZeroUndef && Src.getValueType() == MVT::i32)
1855*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::FFBH_U32, SL, MVT::i32, Src);
1856*9880d681SAndroid Build Coastguard Worker
1857*9880d681SAndroid Build Coastguard Worker SDValue Vec = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Src);
1858*9880d681SAndroid Build Coastguard Worker
1859*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
1860*9880d681SAndroid Build Coastguard Worker const SDValue One = DAG.getConstant(1, SL, MVT::i32);
1861*9880d681SAndroid Build Coastguard Worker
1862*9880d681SAndroid Build Coastguard Worker SDValue Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, Zero);
1863*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, Vec, One);
1864*9880d681SAndroid Build Coastguard Worker
1865*9880d681SAndroid Build Coastguard Worker EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(),
1866*9880d681SAndroid Build Coastguard Worker *DAG.getContext(), MVT::i32);
1867*9880d681SAndroid Build Coastguard Worker
1868*9880d681SAndroid Build Coastguard Worker SDValue Hi0 = DAG.getSetCC(SL, SetCCVT, Hi, Zero, ISD::SETEQ);
1869*9880d681SAndroid Build Coastguard Worker
1870*9880d681SAndroid Build Coastguard Worker SDValue CtlzLo = DAG.getNode(ISD::CTLZ_ZERO_UNDEF, SL, MVT::i32, Lo);
1871*9880d681SAndroid Build Coastguard Worker SDValue CtlzHi = DAG.getNode(ISD::CTLZ_ZERO_UNDEF, SL, MVT::i32, Hi);
1872*9880d681SAndroid Build Coastguard Worker
1873*9880d681SAndroid Build Coastguard Worker const SDValue Bits32 = DAG.getConstant(32, SL, MVT::i32);
1874*9880d681SAndroid Build Coastguard Worker SDValue Add = DAG.getNode(ISD::ADD, SL, MVT::i32, CtlzLo, Bits32);
1875*9880d681SAndroid Build Coastguard Worker
1876*9880d681SAndroid Build Coastguard Worker // ctlz(x) = hi_32(x) == 0 ? ctlz(lo_32(x)) + 32 : ctlz(hi_32(x))
1877*9880d681SAndroid Build Coastguard Worker SDValue NewCtlz = DAG.getNode(ISD::SELECT, SL, MVT::i32, Hi0, Add, CtlzHi);
1878*9880d681SAndroid Build Coastguard Worker
1879*9880d681SAndroid Build Coastguard Worker if (!ZeroUndef) {
1880*9880d681SAndroid Build Coastguard Worker // Test if the full 64-bit input is zero.
1881*9880d681SAndroid Build Coastguard Worker
1882*9880d681SAndroid Build Coastguard Worker // FIXME: DAG combines turn what should be an s_and_b64 into a v_or_b32,
1883*9880d681SAndroid Build Coastguard Worker // which we probably don't want.
1884*9880d681SAndroid Build Coastguard Worker SDValue Lo0 = DAG.getSetCC(SL, SetCCVT, Lo, Zero, ISD::SETEQ);
1885*9880d681SAndroid Build Coastguard Worker SDValue SrcIsZero = DAG.getNode(ISD::AND, SL, SetCCVT, Lo0, Hi0);
1886*9880d681SAndroid Build Coastguard Worker
1887*9880d681SAndroid Build Coastguard Worker // TODO: If i64 setcc is half rate, it can result in 1 fewer instruction
1888*9880d681SAndroid Build Coastguard Worker // with the same cycles, otherwise it is slower.
1889*9880d681SAndroid Build Coastguard Worker // SDValue SrcIsZero = DAG.getSetCC(SL, SetCCVT, Src,
1890*9880d681SAndroid Build Coastguard Worker // DAG.getConstant(0, SL, MVT::i64), ISD::SETEQ);
1891*9880d681SAndroid Build Coastguard Worker
1892*9880d681SAndroid Build Coastguard Worker const SDValue Bits32 = DAG.getConstant(64, SL, MVT::i32);
1893*9880d681SAndroid Build Coastguard Worker
1894*9880d681SAndroid Build Coastguard Worker // The instruction returns -1 for 0 input, but the defined intrinsic
1895*9880d681SAndroid Build Coastguard Worker // behavior is to return the number of bits.
1896*9880d681SAndroid Build Coastguard Worker NewCtlz = DAG.getNode(ISD::SELECT, SL, MVT::i32,
1897*9880d681SAndroid Build Coastguard Worker SrcIsZero, Bits32, NewCtlz);
1898*9880d681SAndroid Build Coastguard Worker }
1899*9880d681SAndroid Build Coastguard Worker
1900*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i64, NewCtlz);
1901*9880d681SAndroid Build Coastguard Worker }
1902*9880d681SAndroid Build Coastguard Worker
LowerINT_TO_FP32(SDValue Op,SelectionDAG & DAG,bool Signed) const1903*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerINT_TO_FP32(SDValue Op, SelectionDAG &DAG,
1904*9880d681SAndroid Build Coastguard Worker bool Signed) const {
1905*9880d681SAndroid Build Coastguard Worker // Unsigned
1906*9880d681SAndroid Build Coastguard Worker // cul2f(ulong u)
1907*9880d681SAndroid Build Coastguard Worker //{
1908*9880d681SAndroid Build Coastguard Worker // uint lz = clz(u);
1909*9880d681SAndroid Build Coastguard Worker // uint e = (u != 0) ? 127U + 63U - lz : 0;
1910*9880d681SAndroid Build Coastguard Worker // u = (u << lz) & 0x7fffffffffffffffUL;
1911*9880d681SAndroid Build Coastguard Worker // ulong t = u & 0xffffffffffUL;
1912*9880d681SAndroid Build Coastguard Worker // uint v = (e << 23) | (uint)(u >> 40);
1913*9880d681SAndroid Build Coastguard Worker // uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U);
1914*9880d681SAndroid Build Coastguard Worker // return as_float(v + r);
1915*9880d681SAndroid Build Coastguard Worker //}
1916*9880d681SAndroid Build Coastguard Worker // Signed
1917*9880d681SAndroid Build Coastguard Worker // cl2f(long l)
1918*9880d681SAndroid Build Coastguard Worker //{
1919*9880d681SAndroid Build Coastguard Worker // long s = l >> 63;
1920*9880d681SAndroid Build Coastguard Worker // float r = cul2f((l + s) ^ s);
1921*9880d681SAndroid Build Coastguard Worker // return s ? -r : r;
1922*9880d681SAndroid Build Coastguard Worker //}
1923*9880d681SAndroid Build Coastguard Worker
1924*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1925*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
1926*9880d681SAndroid Build Coastguard Worker SDValue L = Src;
1927*9880d681SAndroid Build Coastguard Worker
1928*9880d681SAndroid Build Coastguard Worker SDValue S;
1929*9880d681SAndroid Build Coastguard Worker if (Signed) {
1930*9880d681SAndroid Build Coastguard Worker const SDValue SignBit = DAG.getConstant(63, SL, MVT::i64);
1931*9880d681SAndroid Build Coastguard Worker S = DAG.getNode(ISD::SRA, SL, MVT::i64, L, SignBit);
1932*9880d681SAndroid Build Coastguard Worker
1933*9880d681SAndroid Build Coastguard Worker SDValue LPlusS = DAG.getNode(ISD::ADD, SL, MVT::i64, L, S);
1934*9880d681SAndroid Build Coastguard Worker L = DAG.getNode(ISD::XOR, SL, MVT::i64, LPlusS, S);
1935*9880d681SAndroid Build Coastguard Worker }
1936*9880d681SAndroid Build Coastguard Worker
1937*9880d681SAndroid Build Coastguard Worker EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(),
1938*9880d681SAndroid Build Coastguard Worker *DAG.getContext(), MVT::f32);
1939*9880d681SAndroid Build Coastguard Worker
1940*9880d681SAndroid Build Coastguard Worker
1941*9880d681SAndroid Build Coastguard Worker SDValue ZeroI32 = DAG.getConstant(0, SL, MVT::i32);
1942*9880d681SAndroid Build Coastguard Worker SDValue ZeroI64 = DAG.getConstant(0, SL, MVT::i64);
1943*9880d681SAndroid Build Coastguard Worker SDValue LZ = DAG.getNode(ISD::CTLZ_ZERO_UNDEF, SL, MVT::i64, L);
1944*9880d681SAndroid Build Coastguard Worker LZ = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LZ);
1945*9880d681SAndroid Build Coastguard Worker
1946*9880d681SAndroid Build Coastguard Worker SDValue K = DAG.getConstant(127U + 63U, SL, MVT::i32);
1947*9880d681SAndroid Build Coastguard Worker SDValue E = DAG.getSelect(SL, MVT::i32,
1948*9880d681SAndroid Build Coastguard Worker DAG.getSetCC(SL, SetCCVT, L, ZeroI64, ISD::SETNE),
1949*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::SUB, SL, MVT::i32, K, LZ),
1950*9880d681SAndroid Build Coastguard Worker ZeroI32);
1951*9880d681SAndroid Build Coastguard Worker
1952*9880d681SAndroid Build Coastguard Worker SDValue U = DAG.getNode(ISD::AND, SL, MVT::i64,
1953*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::SHL, SL, MVT::i64, L, LZ),
1954*9880d681SAndroid Build Coastguard Worker DAG.getConstant((-1ULL) >> 1, SL, MVT::i64));
1955*9880d681SAndroid Build Coastguard Worker
1956*9880d681SAndroid Build Coastguard Worker SDValue T = DAG.getNode(ISD::AND, SL, MVT::i64, U,
1957*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0xffffffffffULL, SL, MVT::i64));
1958*9880d681SAndroid Build Coastguard Worker
1959*9880d681SAndroid Build Coastguard Worker SDValue UShl = DAG.getNode(ISD::SRL, SL, MVT::i64,
1960*9880d681SAndroid Build Coastguard Worker U, DAG.getConstant(40, SL, MVT::i64));
1961*9880d681SAndroid Build Coastguard Worker
1962*9880d681SAndroid Build Coastguard Worker SDValue V = DAG.getNode(ISD::OR, SL, MVT::i32,
1963*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::SHL, SL, MVT::i32, E, DAG.getConstant(23, SL, MVT::i32)),
1964*9880d681SAndroid Build Coastguard Worker DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, UShl));
1965*9880d681SAndroid Build Coastguard Worker
1966*9880d681SAndroid Build Coastguard Worker SDValue C = DAG.getConstant(0x8000000000ULL, SL, MVT::i64);
1967*9880d681SAndroid Build Coastguard Worker SDValue RCmp = DAG.getSetCC(SL, SetCCVT, T, C, ISD::SETUGT);
1968*9880d681SAndroid Build Coastguard Worker SDValue TCmp = DAG.getSetCC(SL, SetCCVT, T, C, ISD::SETEQ);
1969*9880d681SAndroid Build Coastguard Worker
1970*9880d681SAndroid Build Coastguard Worker SDValue One = DAG.getConstant(1, SL, MVT::i32);
1971*9880d681SAndroid Build Coastguard Worker
1972*9880d681SAndroid Build Coastguard Worker SDValue VTrunc1 = DAG.getNode(ISD::AND, SL, MVT::i32, V, One);
1973*9880d681SAndroid Build Coastguard Worker
1974*9880d681SAndroid Build Coastguard Worker SDValue R = DAG.getSelect(SL, MVT::i32,
1975*9880d681SAndroid Build Coastguard Worker RCmp,
1976*9880d681SAndroid Build Coastguard Worker One,
1977*9880d681SAndroid Build Coastguard Worker DAG.getSelect(SL, MVT::i32, TCmp, VTrunc1, ZeroI32));
1978*9880d681SAndroid Build Coastguard Worker R = DAG.getNode(ISD::ADD, SL, MVT::i32, V, R);
1979*9880d681SAndroid Build Coastguard Worker R = DAG.getNode(ISD::BITCAST, SL, MVT::f32, R);
1980*9880d681SAndroid Build Coastguard Worker
1981*9880d681SAndroid Build Coastguard Worker if (!Signed)
1982*9880d681SAndroid Build Coastguard Worker return R;
1983*9880d681SAndroid Build Coastguard Worker
1984*9880d681SAndroid Build Coastguard Worker SDValue RNeg = DAG.getNode(ISD::FNEG, SL, MVT::f32, R);
1985*9880d681SAndroid Build Coastguard Worker return DAG.getSelect(SL, MVT::f32, DAG.getSExtOrTrunc(S, SL, SetCCVT), RNeg, R);
1986*9880d681SAndroid Build Coastguard Worker }
1987*9880d681SAndroid Build Coastguard Worker
LowerINT_TO_FP64(SDValue Op,SelectionDAG & DAG,bool Signed) const1988*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerINT_TO_FP64(SDValue Op, SelectionDAG &DAG,
1989*9880d681SAndroid Build Coastguard Worker bool Signed) const {
1990*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
1991*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
1992*9880d681SAndroid Build Coastguard Worker
1993*9880d681SAndroid Build Coastguard Worker SDValue BC = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, Src);
1994*9880d681SAndroid Build Coastguard Worker
1995*9880d681SAndroid Build Coastguard Worker SDValue Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BC,
1996*9880d681SAndroid Build Coastguard Worker DAG.getConstant(0, SL, MVT::i32));
1997*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32, BC,
1998*9880d681SAndroid Build Coastguard Worker DAG.getConstant(1, SL, MVT::i32));
1999*9880d681SAndroid Build Coastguard Worker
2000*9880d681SAndroid Build Coastguard Worker SDValue CvtHi = DAG.getNode(Signed ? ISD::SINT_TO_FP : ISD::UINT_TO_FP,
2001*9880d681SAndroid Build Coastguard Worker SL, MVT::f64, Hi);
2002*9880d681SAndroid Build Coastguard Worker
2003*9880d681SAndroid Build Coastguard Worker SDValue CvtLo = DAG.getNode(ISD::UINT_TO_FP, SL, MVT::f64, Lo);
2004*9880d681SAndroid Build Coastguard Worker
2005*9880d681SAndroid Build Coastguard Worker SDValue LdExp = DAG.getNode(AMDGPUISD::LDEXP, SL, MVT::f64, CvtHi,
2006*9880d681SAndroid Build Coastguard Worker DAG.getConstant(32, SL, MVT::i32));
2007*9880d681SAndroid Build Coastguard Worker // TODO: Should this propagate fast-math-flags?
2008*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::FADD, SL, MVT::f64, LdExp, CvtLo);
2009*9880d681SAndroid Build Coastguard Worker }
2010*9880d681SAndroid Build Coastguard Worker
LowerUINT_TO_FP(SDValue Op,SelectionDAG & DAG) const2011*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerUINT_TO_FP(SDValue Op,
2012*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2013*9880d681SAndroid Build Coastguard Worker assert(Op.getOperand(0).getValueType() == MVT::i64 &&
2014*9880d681SAndroid Build Coastguard Worker "operation should be legal");
2015*9880d681SAndroid Build Coastguard Worker
2016*9880d681SAndroid Build Coastguard Worker EVT DestVT = Op.getValueType();
2017*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::f64)
2018*9880d681SAndroid Build Coastguard Worker return LowerINT_TO_FP64(Op, DAG, false);
2019*9880d681SAndroid Build Coastguard Worker
2020*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::f32)
2021*9880d681SAndroid Build Coastguard Worker return LowerINT_TO_FP32(Op, DAG, false);
2022*9880d681SAndroid Build Coastguard Worker
2023*9880d681SAndroid Build Coastguard Worker return SDValue();
2024*9880d681SAndroid Build Coastguard Worker }
2025*9880d681SAndroid Build Coastguard Worker
LowerSINT_TO_FP(SDValue Op,SelectionDAG & DAG) const2026*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerSINT_TO_FP(SDValue Op,
2027*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2028*9880d681SAndroid Build Coastguard Worker assert(Op.getOperand(0).getValueType() == MVT::i64 &&
2029*9880d681SAndroid Build Coastguard Worker "operation should be legal");
2030*9880d681SAndroid Build Coastguard Worker
2031*9880d681SAndroid Build Coastguard Worker EVT DestVT = Op.getValueType();
2032*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::f32)
2033*9880d681SAndroid Build Coastguard Worker return LowerINT_TO_FP32(Op, DAG, true);
2034*9880d681SAndroid Build Coastguard Worker
2035*9880d681SAndroid Build Coastguard Worker if (DestVT == MVT::f64)
2036*9880d681SAndroid Build Coastguard Worker return LowerINT_TO_FP64(Op, DAG, true);
2037*9880d681SAndroid Build Coastguard Worker
2038*9880d681SAndroid Build Coastguard Worker return SDValue();
2039*9880d681SAndroid Build Coastguard Worker }
2040*9880d681SAndroid Build Coastguard Worker
LowerFP64_TO_INT(SDValue Op,SelectionDAG & DAG,bool Signed) const2041*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFP64_TO_INT(SDValue Op, SelectionDAG &DAG,
2042*9880d681SAndroid Build Coastguard Worker bool Signed) const {
2043*9880d681SAndroid Build Coastguard Worker SDLoc SL(Op);
2044*9880d681SAndroid Build Coastguard Worker
2045*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
2046*9880d681SAndroid Build Coastguard Worker
2047*9880d681SAndroid Build Coastguard Worker SDValue Trunc = DAG.getNode(ISD::FTRUNC, SL, MVT::f64, Src);
2048*9880d681SAndroid Build Coastguard Worker
2049*9880d681SAndroid Build Coastguard Worker SDValue K0 = DAG.getConstantFP(BitsToDouble(UINT64_C(0x3df0000000000000)), SL,
2050*9880d681SAndroid Build Coastguard Worker MVT::f64);
2051*9880d681SAndroid Build Coastguard Worker SDValue K1 = DAG.getConstantFP(BitsToDouble(UINT64_C(0xc1f0000000000000)), SL,
2052*9880d681SAndroid Build Coastguard Worker MVT::f64);
2053*9880d681SAndroid Build Coastguard Worker // TODO: Should this propagate fast-math-flags?
2054*9880d681SAndroid Build Coastguard Worker SDValue Mul = DAG.getNode(ISD::FMUL, SL, MVT::f64, Trunc, K0);
2055*9880d681SAndroid Build Coastguard Worker
2056*9880d681SAndroid Build Coastguard Worker SDValue FloorMul = DAG.getNode(ISD::FFLOOR, SL, MVT::f64, Mul);
2057*9880d681SAndroid Build Coastguard Worker
2058*9880d681SAndroid Build Coastguard Worker
2059*9880d681SAndroid Build Coastguard Worker SDValue Fma = DAG.getNode(ISD::FMA, SL, MVT::f64, FloorMul, K1, Trunc);
2060*9880d681SAndroid Build Coastguard Worker
2061*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(Signed ? ISD::FP_TO_SINT : ISD::FP_TO_UINT, SL,
2062*9880d681SAndroid Build Coastguard Worker MVT::i32, FloorMul);
2063*9880d681SAndroid Build Coastguard Worker SDValue Lo = DAG.getNode(ISD::FP_TO_UINT, SL, MVT::i32, Fma);
2064*9880d681SAndroid Build Coastguard Worker
2065*9880d681SAndroid Build Coastguard Worker SDValue Result = DAG.getBuildVector(MVT::v2i32, SL, {Lo, Hi});
2066*9880d681SAndroid Build Coastguard Worker
2067*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Result);
2068*9880d681SAndroid Build Coastguard Worker }
2069*9880d681SAndroid Build Coastguard Worker
LowerFP_TO_SINT(SDValue Op,SelectionDAG & DAG) const2070*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFP_TO_SINT(SDValue Op,
2071*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2072*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
2073*9880d681SAndroid Build Coastguard Worker
2074*9880d681SAndroid Build Coastguard Worker if (Op.getValueType() == MVT::i64 && Src.getValueType() == MVT::f64)
2075*9880d681SAndroid Build Coastguard Worker return LowerFP64_TO_INT(Op, DAG, true);
2076*9880d681SAndroid Build Coastguard Worker
2077*9880d681SAndroid Build Coastguard Worker return SDValue();
2078*9880d681SAndroid Build Coastguard Worker }
2079*9880d681SAndroid Build Coastguard Worker
LowerFP_TO_UINT(SDValue Op,SelectionDAG & DAG) const2080*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerFP_TO_UINT(SDValue Op,
2081*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2082*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
2083*9880d681SAndroid Build Coastguard Worker
2084*9880d681SAndroid Build Coastguard Worker if (Op.getValueType() == MVT::i64 && Src.getValueType() == MVT::f64)
2085*9880d681SAndroid Build Coastguard Worker return LowerFP64_TO_INT(Op, DAG, false);
2086*9880d681SAndroid Build Coastguard Worker
2087*9880d681SAndroid Build Coastguard Worker return SDValue();
2088*9880d681SAndroid Build Coastguard Worker }
2089*9880d681SAndroid Build Coastguard Worker
LowerSIGN_EXTEND_INREG(SDValue Op,SelectionDAG & DAG) const2090*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
2091*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG) const {
2092*9880d681SAndroid Build Coastguard Worker EVT ExtraVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
2093*9880d681SAndroid Build Coastguard Worker MVT VT = Op.getSimpleValueType();
2094*9880d681SAndroid Build Coastguard Worker MVT ScalarVT = VT.getScalarType();
2095*9880d681SAndroid Build Coastguard Worker
2096*9880d681SAndroid Build Coastguard Worker if (!VT.isVector())
2097*9880d681SAndroid Build Coastguard Worker return SDValue();
2098*9880d681SAndroid Build Coastguard Worker
2099*9880d681SAndroid Build Coastguard Worker SDValue Src = Op.getOperand(0);
2100*9880d681SAndroid Build Coastguard Worker SDLoc DL(Op);
2101*9880d681SAndroid Build Coastguard Worker
2102*9880d681SAndroid Build Coastguard Worker // TODO: Don't scalarize on Evergreen?
2103*9880d681SAndroid Build Coastguard Worker unsigned NElts = VT.getVectorNumElements();
2104*9880d681SAndroid Build Coastguard Worker SmallVector<SDValue, 8> Args;
2105*9880d681SAndroid Build Coastguard Worker DAG.ExtractVectorElements(Src, Args, 0, NElts);
2106*9880d681SAndroid Build Coastguard Worker
2107*9880d681SAndroid Build Coastguard Worker SDValue VTOp = DAG.getValueType(ExtraVT.getScalarType());
2108*9880d681SAndroid Build Coastguard Worker for (unsigned I = 0; I < NElts; ++I)
2109*9880d681SAndroid Build Coastguard Worker Args[I] = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, ScalarVT, Args[I], VTOp);
2110*9880d681SAndroid Build Coastguard Worker
2111*9880d681SAndroid Build Coastguard Worker return DAG.getBuildVector(VT, DL, Args);
2112*9880d681SAndroid Build Coastguard Worker }
2113*9880d681SAndroid Build Coastguard Worker
2114*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2115*9880d681SAndroid Build Coastguard Worker // Custom DAG optimizations
2116*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2117*9880d681SAndroid Build Coastguard Worker
isU24(SDValue Op,SelectionDAG & DAG)2118*9880d681SAndroid Build Coastguard Worker static bool isU24(SDValue Op, SelectionDAG &DAG) {
2119*9880d681SAndroid Build Coastguard Worker APInt KnownZero, KnownOne;
2120*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
2121*9880d681SAndroid Build Coastguard Worker DAG.computeKnownBits(Op, KnownZero, KnownOne);
2122*9880d681SAndroid Build Coastguard Worker
2123*9880d681SAndroid Build Coastguard Worker return (VT.getSizeInBits() - KnownZero.countLeadingOnes()) <= 24;
2124*9880d681SAndroid Build Coastguard Worker }
2125*9880d681SAndroid Build Coastguard Worker
isI24(SDValue Op,SelectionDAG & DAG)2126*9880d681SAndroid Build Coastguard Worker static bool isI24(SDValue Op, SelectionDAG &DAG) {
2127*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
2128*9880d681SAndroid Build Coastguard Worker
2129*9880d681SAndroid Build Coastguard Worker // In order for this to be a signed 24-bit value, bit 23, must
2130*9880d681SAndroid Build Coastguard Worker // be a sign bit.
2131*9880d681SAndroid Build Coastguard Worker return VT.getSizeInBits() >= 24 && // Types less than 24-bit should be treated
2132*9880d681SAndroid Build Coastguard Worker // as unsigned 24-bit values.
2133*9880d681SAndroid Build Coastguard Worker (VT.getSizeInBits() - DAG.ComputeNumSignBits(Op)) < 24;
2134*9880d681SAndroid Build Coastguard Worker }
2135*9880d681SAndroid Build Coastguard Worker
simplifyI24(SDValue Op,TargetLowering::DAGCombinerInfo & DCI)2136*9880d681SAndroid Build Coastguard Worker static void simplifyI24(SDValue Op, TargetLowering::DAGCombinerInfo &DCI) {
2137*9880d681SAndroid Build Coastguard Worker
2138*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2139*9880d681SAndroid Build Coastguard Worker const TargetLowering &TLI = DAG.getTargetLoweringInfo();
2140*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
2141*9880d681SAndroid Build Coastguard Worker
2142*9880d681SAndroid Build Coastguard Worker APInt Demanded = APInt::getLowBitsSet(VT.getSizeInBits(), 24);
2143*9880d681SAndroid Build Coastguard Worker APInt KnownZero, KnownOne;
2144*9880d681SAndroid Build Coastguard Worker TargetLowering::TargetLoweringOpt TLO(DAG, true, true);
2145*9880d681SAndroid Build Coastguard Worker if (TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO))
2146*9880d681SAndroid Build Coastguard Worker DCI.CommitTargetLoweringOpt(TLO);
2147*9880d681SAndroid Build Coastguard Worker }
2148*9880d681SAndroid Build Coastguard Worker
2149*9880d681SAndroid Build Coastguard Worker template <typename IntTy>
constantFoldBFE(SelectionDAG & DAG,IntTy Src0,uint32_t Offset,uint32_t Width,const SDLoc & DL)2150*9880d681SAndroid Build Coastguard Worker static SDValue constantFoldBFE(SelectionDAG &DAG, IntTy Src0, uint32_t Offset,
2151*9880d681SAndroid Build Coastguard Worker uint32_t Width, const SDLoc &DL) {
2152*9880d681SAndroid Build Coastguard Worker if (Width + Offset < 32) {
2153*9880d681SAndroid Build Coastguard Worker uint32_t Shl = static_cast<uint32_t>(Src0) << (32 - Offset - Width);
2154*9880d681SAndroid Build Coastguard Worker IntTy Result = static_cast<IntTy>(Shl) >> (32 - Width);
2155*9880d681SAndroid Build Coastguard Worker return DAG.getConstant(Result, DL, MVT::i32);
2156*9880d681SAndroid Build Coastguard Worker }
2157*9880d681SAndroid Build Coastguard Worker
2158*9880d681SAndroid Build Coastguard Worker return DAG.getConstant(Src0 >> Offset, DL, MVT::i32);
2159*9880d681SAndroid Build Coastguard Worker }
2160*9880d681SAndroid Build Coastguard Worker
hasVolatileUser(SDNode * Val)2161*9880d681SAndroid Build Coastguard Worker static bool hasVolatileUser(SDNode *Val) {
2162*9880d681SAndroid Build Coastguard Worker for (SDNode *U : Val->uses()) {
2163*9880d681SAndroid Build Coastguard Worker if (MemSDNode *M = dyn_cast<MemSDNode>(U)) {
2164*9880d681SAndroid Build Coastguard Worker if (M->isVolatile())
2165*9880d681SAndroid Build Coastguard Worker return true;
2166*9880d681SAndroid Build Coastguard Worker }
2167*9880d681SAndroid Build Coastguard Worker }
2168*9880d681SAndroid Build Coastguard Worker
2169*9880d681SAndroid Build Coastguard Worker return false;
2170*9880d681SAndroid Build Coastguard Worker }
2171*9880d681SAndroid Build Coastguard Worker
shouldCombineMemoryType(EVT VT) const2172*9880d681SAndroid Build Coastguard Worker bool AMDGPUTargetLowering::shouldCombineMemoryType(EVT VT) const {
2173*9880d681SAndroid Build Coastguard Worker // i32 vectors are the canonical memory type.
2174*9880d681SAndroid Build Coastguard Worker if (VT.getScalarType() == MVT::i32 || isTypeLegal(VT))
2175*9880d681SAndroid Build Coastguard Worker return false;
2176*9880d681SAndroid Build Coastguard Worker
2177*9880d681SAndroid Build Coastguard Worker if (!VT.isByteSized())
2178*9880d681SAndroid Build Coastguard Worker return false;
2179*9880d681SAndroid Build Coastguard Worker
2180*9880d681SAndroid Build Coastguard Worker unsigned Size = VT.getStoreSize();
2181*9880d681SAndroid Build Coastguard Worker
2182*9880d681SAndroid Build Coastguard Worker if ((Size == 1 || Size == 2 || Size == 4) && !VT.isVector())
2183*9880d681SAndroid Build Coastguard Worker return false;
2184*9880d681SAndroid Build Coastguard Worker
2185*9880d681SAndroid Build Coastguard Worker if (Size == 3 || (Size > 4 && (Size % 4 != 0)))
2186*9880d681SAndroid Build Coastguard Worker return false;
2187*9880d681SAndroid Build Coastguard Worker
2188*9880d681SAndroid Build Coastguard Worker return true;
2189*9880d681SAndroid Build Coastguard Worker }
2190*9880d681SAndroid Build Coastguard Worker
2191*9880d681SAndroid Build Coastguard Worker // Replace load of an illegal type with a store of a bitcast to a friendlier
2192*9880d681SAndroid Build Coastguard Worker // type.
performLoadCombine(SDNode * N,DAGCombinerInfo & DCI) const2193*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performLoadCombine(SDNode *N,
2194*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2195*9880d681SAndroid Build Coastguard Worker if (!DCI.isBeforeLegalize())
2196*9880d681SAndroid Build Coastguard Worker return SDValue();
2197*9880d681SAndroid Build Coastguard Worker
2198*9880d681SAndroid Build Coastguard Worker LoadSDNode *LN = cast<LoadSDNode>(N);
2199*9880d681SAndroid Build Coastguard Worker if (LN->isVolatile() || !ISD::isNormalLoad(LN) || hasVolatileUser(LN))
2200*9880d681SAndroid Build Coastguard Worker return SDValue();
2201*9880d681SAndroid Build Coastguard Worker
2202*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
2203*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2204*9880d681SAndroid Build Coastguard Worker EVT VT = LN->getMemoryVT();
2205*9880d681SAndroid Build Coastguard Worker
2206*9880d681SAndroid Build Coastguard Worker unsigned Size = VT.getStoreSize();
2207*9880d681SAndroid Build Coastguard Worker unsigned Align = LN->getAlignment();
2208*9880d681SAndroid Build Coastguard Worker if (Align < Size && isTypeLegal(VT)) {
2209*9880d681SAndroid Build Coastguard Worker bool IsFast;
2210*9880d681SAndroid Build Coastguard Worker unsigned AS = LN->getAddressSpace();
2211*9880d681SAndroid Build Coastguard Worker
2212*9880d681SAndroid Build Coastguard Worker // Expand unaligned loads earlier than legalization. Due to visitation order
2213*9880d681SAndroid Build Coastguard Worker // problems during legalization, the emitted instructions to pack and unpack
2214*9880d681SAndroid Build Coastguard Worker // the bytes again are not eliminated in the case of an unaligned copy.
2215*9880d681SAndroid Build Coastguard Worker if (!allowsMisalignedMemoryAccesses(VT, AS, Align, &IsFast)) {
2216*9880d681SAndroid Build Coastguard Worker SDValue Ops[2];
2217*9880d681SAndroid Build Coastguard Worker std::tie(Ops[0], Ops[1]) = expandUnalignedLoad(LN, DAG);
2218*9880d681SAndroid Build Coastguard Worker return DAG.getMergeValues(Ops, SDLoc(N));
2219*9880d681SAndroid Build Coastguard Worker }
2220*9880d681SAndroid Build Coastguard Worker
2221*9880d681SAndroid Build Coastguard Worker if (!IsFast)
2222*9880d681SAndroid Build Coastguard Worker return SDValue();
2223*9880d681SAndroid Build Coastguard Worker }
2224*9880d681SAndroid Build Coastguard Worker
2225*9880d681SAndroid Build Coastguard Worker if (!shouldCombineMemoryType(VT))
2226*9880d681SAndroid Build Coastguard Worker return SDValue();
2227*9880d681SAndroid Build Coastguard Worker
2228*9880d681SAndroid Build Coastguard Worker EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
2229*9880d681SAndroid Build Coastguard Worker
2230*9880d681SAndroid Build Coastguard Worker SDValue NewLoad
2231*9880d681SAndroid Build Coastguard Worker = DAG.getLoad(NewVT, SL, LN->getChain(),
2232*9880d681SAndroid Build Coastguard Worker LN->getBasePtr(), LN->getMemOperand());
2233*9880d681SAndroid Build Coastguard Worker
2234*9880d681SAndroid Build Coastguard Worker SDValue BC = DAG.getNode(ISD::BITCAST, SL, VT, NewLoad);
2235*9880d681SAndroid Build Coastguard Worker DCI.CombineTo(N, BC, NewLoad.getValue(1));
2236*9880d681SAndroid Build Coastguard Worker return SDValue(N, 0);
2237*9880d681SAndroid Build Coastguard Worker }
2238*9880d681SAndroid Build Coastguard Worker
2239*9880d681SAndroid Build Coastguard Worker // Replace store of an illegal type with a store of a bitcast to a friendlier
2240*9880d681SAndroid Build Coastguard Worker // type.
performStoreCombine(SDNode * N,DAGCombinerInfo & DCI) const2241*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performStoreCombine(SDNode *N,
2242*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2243*9880d681SAndroid Build Coastguard Worker if (!DCI.isBeforeLegalize())
2244*9880d681SAndroid Build Coastguard Worker return SDValue();
2245*9880d681SAndroid Build Coastguard Worker
2246*9880d681SAndroid Build Coastguard Worker StoreSDNode *SN = cast<StoreSDNode>(N);
2247*9880d681SAndroid Build Coastguard Worker if (SN->isVolatile() || !ISD::isNormalStore(SN))
2248*9880d681SAndroid Build Coastguard Worker return SDValue();
2249*9880d681SAndroid Build Coastguard Worker
2250*9880d681SAndroid Build Coastguard Worker EVT VT = SN->getMemoryVT();
2251*9880d681SAndroid Build Coastguard Worker unsigned Size = VT.getStoreSize();
2252*9880d681SAndroid Build Coastguard Worker
2253*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
2254*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2255*9880d681SAndroid Build Coastguard Worker unsigned Align = SN->getAlignment();
2256*9880d681SAndroid Build Coastguard Worker if (Align < Size && isTypeLegal(VT)) {
2257*9880d681SAndroid Build Coastguard Worker bool IsFast;
2258*9880d681SAndroid Build Coastguard Worker unsigned AS = SN->getAddressSpace();
2259*9880d681SAndroid Build Coastguard Worker
2260*9880d681SAndroid Build Coastguard Worker // Expand unaligned stores earlier than legalization. Due to visitation
2261*9880d681SAndroid Build Coastguard Worker // order problems during legalization, the emitted instructions to pack and
2262*9880d681SAndroid Build Coastguard Worker // unpack the bytes again are not eliminated in the case of an unaligned
2263*9880d681SAndroid Build Coastguard Worker // copy.
2264*9880d681SAndroid Build Coastguard Worker if (!allowsMisalignedMemoryAccesses(VT, AS, Align, &IsFast))
2265*9880d681SAndroid Build Coastguard Worker return expandUnalignedStore(SN, DAG);
2266*9880d681SAndroid Build Coastguard Worker
2267*9880d681SAndroid Build Coastguard Worker if (!IsFast)
2268*9880d681SAndroid Build Coastguard Worker return SDValue();
2269*9880d681SAndroid Build Coastguard Worker }
2270*9880d681SAndroid Build Coastguard Worker
2271*9880d681SAndroid Build Coastguard Worker if (!shouldCombineMemoryType(VT))
2272*9880d681SAndroid Build Coastguard Worker return SDValue();
2273*9880d681SAndroid Build Coastguard Worker
2274*9880d681SAndroid Build Coastguard Worker EVT NewVT = getEquivalentMemType(*DAG.getContext(), VT);
2275*9880d681SAndroid Build Coastguard Worker SDValue Val = SN->getValue();
2276*9880d681SAndroid Build Coastguard Worker
2277*9880d681SAndroid Build Coastguard Worker //DCI.AddToWorklist(Val.getNode());
2278*9880d681SAndroid Build Coastguard Worker
2279*9880d681SAndroid Build Coastguard Worker bool OtherUses = !Val.hasOneUse();
2280*9880d681SAndroid Build Coastguard Worker SDValue CastVal = DAG.getNode(ISD::BITCAST, SL, NewVT, Val);
2281*9880d681SAndroid Build Coastguard Worker if (OtherUses) {
2282*9880d681SAndroid Build Coastguard Worker SDValue CastBack = DAG.getNode(ISD::BITCAST, SL, VT, CastVal);
2283*9880d681SAndroid Build Coastguard Worker DAG.ReplaceAllUsesOfValueWith(Val, CastBack);
2284*9880d681SAndroid Build Coastguard Worker }
2285*9880d681SAndroid Build Coastguard Worker
2286*9880d681SAndroid Build Coastguard Worker return DAG.getStore(SN->getChain(), SL, CastVal,
2287*9880d681SAndroid Build Coastguard Worker SN->getBasePtr(), SN->getMemOperand());
2288*9880d681SAndroid Build Coastguard Worker }
2289*9880d681SAndroid Build Coastguard Worker
2290*9880d681SAndroid Build Coastguard Worker // TODO: Should repeat for other bit ops.
performAndCombine(SDNode * N,DAGCombinerInfo & DCI) const2291*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performAndCombine(SDNode *N,
2292*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2293*9880d681SAndroid Build Coastguard Worker if (N->getValueType(0) != MVT::i64)
2294*9880d681SAndroid Build Coastguard Worker return SDValue();
2295*9880d681SAndroid Build Coastguard Worker
2296*9880d681SAndroid Build Coastguard Worker // Break up 64-bit and of a constant into two 32-bit ands. This will typically
2297*9880d681SAndroid Build Coastguard Worker // happen anyway for a VALU 64-bit and. This exposes other 32-bit integer
2298*9880d681SAndroid Build Coastguard Worker // combine opportunities since most 64-bit operations are decomposed this way.
2299*9880d681SAndroid Build Coastguard Worker // TODO: We won't want this for SALU especially if it is an inline immediate.
2300*9880d681SAndroid Build Coastguard Worker const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
2301*9880d681SAndroid Build Coastguard Worker if (!RHS)
2302*9880d681SAndroid Build Coastguard Worker return SDValue();
2303*9880d681SAndroid Build Coastguard Worker
2304*9880d681SAndroid Build Coastguard Worker uint64_t Val = RHS->getZExtValue();
2305*9880d681SAndroid Build Coastguard Worker if (Lo_32(Val) != 0 && Hi_32(Val) != 0 && !RHS->hasOneUse()) {
2306*9880d681SAndroid Build Coastguard Worker // If either half of the constant is 0, this is really a 32-bit and, so
2307*9880d681SAndroid Build Coastguard Worker // split it. If we can re-use the full materialized constant, keep it.
2308*9880d681SAndroid Build Coastguard Worker return SDValue();
2309*9880d681SAndroid Build Coastguard Worker }
2310*9880d681SAndroid Build Coastguard Worker
2311*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
2312*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2313*9880d681SAndroid Build Coastguard Worker
2314*9880d681SAndroid Build Coastguard Worker SDValue Lo, Hi;
2315*9880d681SAndroid Build Coastguard Worker std::tie(Lo, Hi) = split64BitValue(N->getOperand(0), DAG);
2316*9880d681SAndroid Build Coastguard Worker
2317*9880d681SAndroid Build Coastguard Worker SDValue LoRHS = DAG.getConstant(Lo_32(Val), SL, MVT::i32);
2318*9880d681SAndroid Build Coastguard Worker SDValue HiRHS = DAG.getConstant(Hi_32(Val), SL, MVT::i32);
2319*9880d681SAndroid Build Coastguard Worker
2320*9880d681SAndroid Build Coastguard Worker SDValue LoAnd = DAG.getNode(ISD::AND, SL, MVT::i32, Lo, LoRHS);
2321*9880d681SAndroid Build Coastguard Worker SDValue HiAnd = DAG.getNode(ISD::AND, SL, MVT::i32, Hi, HiRHS);
2322*9880d681SAndroid Build Coastguard Worker
2323*9880d681SAndroid Build Coastguard Worker // Re-visit the ands. It's possible we eliminated one of them and it could
2324*9880d681SAndroid Build Coastguard Worker // simplify the vector.
2325*9880d681SAndroid Build Coastguard Worker DCI.AddToWorklist(Lo.getNode());
2326*9880d681SAndroid Build Coastguard Worker DCI.AddToWorklist(Hi.getNode());
2327*9880d681SAndroid Build Coastguard Worker
2328*9880d681SAndroid Build Coastguard Worker SDValue Vec = DAG.getBuildVector(MVT::v2i32, SL, {LoAnd, HiAnd});
2329*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
2330*9880d681SAndroid Build Coastguard Worker }
2331*9880d681SAndroid Build Coastguard Worker
performShlCombine(SDNode * N,DAGCombinerInfo & DCI) const2332*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performShlCombine(SDNode *N,
2333*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2334*9880d681SAndroid Build Coastguard Worker if (N->getValueType(0) != MVT::i64)
2335*9880d681SAndroid Build Coastguard Worker return SDValue();
2336*9880d681SAndroid Build Coastguard Worker
2337*9880d681SAndroid Build Coastguard Worker // i64 (shl x, C) -> (build_pair 0, (shl x, C -32))
2338*9880d681SAndroid Build Coastguard Worker
2339*9880d681SAndroid Build Coastguard Worker // On some subtargets, 64-bit shift is a quarter rate instruction. In the
2340*9880d681SAndroid Build Coastguard Worker // common case, splitting this into a move and a 32-bit shift is faster and
2341*9880d681SAndroid Build Coastguard Worker // the same code size.
2342*9880d681SAndroid Build Coastguard Worker const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
2343*9880d681SAndroid Build Coastguard Worker if (!RHS)
2344*9880d681SAndroid Build Coastguard Worker return SDValue();
2345*9880d681SAndroid Build Coastguard Worker
2346*9880d681SAndroid Build Coastguard Worker unsigned RHSVal = RHS->getZExtValue();
2347*9880d681SAndroid Build Coastguard Worker if (RHSVal < 32)
2348*9880d681SAndroid Build Coastguard Worker return SDValue();
2349*9880d681SAndroid Build Coastguard Worker
2350*9880d681SAndroid Build Coastguard Worker SDValue LHS = N->getOperand(0);
2351*9880d681SAndroid Build Coastguard Worker
2352*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
2353*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2354*9880d681SAndroid Build Coastguard Worker
2355*9880d681SAndroid Build Coastguard Worker SDValue ShiftAmt = DAG.getConstant(RHSVal - 32, SL, MVT::i32);
2356*9880d681SAndroid Build Coastguard Worker
2357*9880d681SAndroid Build Coastguard Worker SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, MVT::i32, LHS);
2358*9880d681SAndroid Build Coastguard Worker SDValue NewShift = DAG.getNode(ISD::SHL, SL, MVT::i32, Lo, ShiftAmt);
2359*9880d681SAndroid Build Coastguard Worker
2360*9880d681SAndroid Build Coastguard Worker const SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
2361*9880d681SAndroid Build Coastguard Worker
2362*9880d681SAndroid Build Coastguard Worker SDValue Vec = DAG.getBuildVector(MVT::v2i32, SL, {Zero, NewShift});
2363*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SL, MVT::i64, Vec);
2364*9880d681SAndroid Build Coastguard Worker }
2365*9880d681SAndroid Build Coastguard Worker
performSraCombine(SDNode * N,DAGCombinerInfo & DCI) const2366*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performSraCombine(SDNode *N,
2367*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2368*9880d681SAndroid Build Coastguard Worker if (N->getValueType(0) != MVT::i64)
2369*9880d681SAndroid Build Coastguard Worker return SDValue();
2370*9880d681SAndroid Build Coastguard Worker
2371*9880d681SAndroid Build Coastguard Worker const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
2372*9880d681SAndroid Build Coastguard Worker if (!RHS)
2373*9880d681SAndroid Build Coastguard Worker return SDValue();
2374*9880d681SAndroid Build Coastguard Worker
2375*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2376*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
2377*9880d681SAndroid Build Coastguard Worker unsigned RHSVal = RHS->getZExtValue();
2378*9880d681SAndroid Build Coastguard Worker
2379*9880d681SAndroid Build Coastguard Worker // (sra i64:x, 32) -> build_pair x, (sra hi_32(x), 31)
2380*9880d681SAndroid Build Coastguard Worker if (RHSVal == 32) {
2381*9880d681SAndroid Build Coastguard Worker SDValue Hi = getHiHalf64(N->getOperand(0), DAG);
2382*9880d681SAndroid Build Coastguard Worker SDValue NewShift = DAG.getNode(ISD::SRA, SL, MVT::i32, Hi,
2383*9880d681SAndroid Build Coastguard Worker DAG.getConstant(31, SL, MVT::i32));
2384*9880d681SAndroid Build Coastguard Worker
2385*9880d681SAndroid Build Coastguard Worker SDValue BuildVec = DAG.getBuildVector(MVT::v2i32, SL, {Hi, NewShift});
2386*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SL, MVT::i64, BuildVec);
2387*9880d681SAndroid Build Coastguard Worker }
2388*9880d681SAndroid Build Coastguard Worker
2389*9880d681SAndroid Build Coastguard Worker // (sra i64:x, 63) -> build_pair (sra hi_32(x), 31), (sra hi_32(x), 31)
2390*9880d681SAndroid Build Coastguard Worker if (RHSVal == 63) {
2391*9880d681SAndroid Build Coastguard Worker SDValue Hi = getHiHalf64(N->getOperand(0), DAG);
2392*9880d681SAndroid Build Coastguard Worker SDValue NewShift = DAG.getNode(ISD::SRA, SL, MVT::i32, Hi,
2393*9880d681SAndroid Build Coastguard Worker DAG.getConstant(31, SL, MVT::i32));
2394*9880d681SAndroid Build Coastguard Worker SDValue BuildVec = DAG.getBuildVector(MVT::v2i32, SL, {NewShift, NewShift});
2395*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SL, MVT::i64, BuildVec);
2396*9880d681SAndroid Build Coastguard Worker }
2397*9880d681SAndroid Build Coastguard Worker
2398*9880d681SAndroid Build Coastguard Worker return SDValue();
2399*9880d681SAndroid Build Coastguard Worker }
2400*9880d681SAndroid Build Coastguard Worker
performSrlCombine(SDNode * N,DAGCombinerInfo & DCI) const2401*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performSrlCombine(SDNode *N,
2402*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2403*9880d681SAndroid Build Coastguard Worker if (N->getValueType(0) != MVT::i64)
2404*9880d681SAndroid Build Coastguard Worker return SDValue();
2405*9880d681SAndroid Build Coastguard Worker
2406*9880d681SAndroid Build Coastguard Worker const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N->getOperand(1));
2407*9880d681SAndroid Build Coastguard Worker if (!RHS)
2408*9880d681SAndroid Build Coastguard Worker return SDValue();
2409*9880d681SAndroid Build Coastguard Worker
2410*9880d681SAndroid Build Coastguard Worker unsigned ShiftAmt = RHS->getZExtValue();
2411*9880d681SAndroid Build Coastguard Worker if (ShiftAmt < 32)
2412*9880d681SAndroid Build Coastguard Worker return SDValue();
2413*9880d681SAndroid Build Coastguard Worker
2414*9880d681SAndroid Build Coastguard Worker // srl i64:x, C for C >= 32
2415*9880d681SAndroid Build Coastguard Worker // =>
2416*9880d681SAndroid Build Coastguard Worker // build_pair (srl hi_32(x), C - 32), 0
2417*9880d681SAndroid Build Coastguard Worker
2418*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2419*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
2420*9880d681SAndroid Build Coastguard Worker
2421*9880d681SAndroid Build Coastguard Worker SDValue One = DAG.getConstant(1, SL, MVT::i32);
2422*9880d681SAndroid Build Coastguard Worker SDValue Zero = DAG.getConstant(0, SL, MVT::i32);
2423*9880d681SAndroid Build Coastguard Worker
2424*9880d681SAndroid Build Coastguard Worker SDValue VecOp = DAG.getNode(ISD::BITCAST, SL, MVT::v2i32, N->getOperand(0));
2425*9880d681SAndroid Build Coastguard Worker SDValue Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SL, MVT::i32,
2426*9880d681SAndroid Build Coastguard Worker VecOp, One);
2427*9880d681SAndroid Build Coastguard Worker
2428*9880d681SAndroid Build Coastguard Worker SDValue NewConst = DAG.getConstant(ShiftAmt - 32, SL, MVT::i32);
2429*9880d681SAndroid Build Coastguard Worker SDValue NewShift = DAG.getNode(ISD::SRL, SL, MVT::i32, Hi, NewConst);
2430*9880d681SAndroid Build Coastguard Worker
2431*9880d681SAndroid Build Coastguard Worker SDValue BuildPair = DAG.getBuildVector(MVT::v2i32, SL, {NewShift, Zero});
2432*9880d681SAndroid Build Coastguard Worker
2433*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SL, MVT::i64, BuildPair);
2434*9880d681SAndroid Build Coastguard Worker }
2435*9880d681SAndroid Build Coastguard Worker
performMulCombine(SDNode * N,DAGCombinerInfo & DCI) const2436*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performMulCombine(SDNode *N,
2437*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2438*9880d681SAndroid Build Coastguard Worker EVT VT = N->getValueType(0);
2439*9880d681SAndroid Build Coastguard Worker
2440*9880d681SAndroid Build Coastguard Worker if (VT.isVector() || VT.getSizeInBits() > 32)
2441*9880d681SAndroid Build Coastguard Worker return SDValue();
2442*9880d681SAndroid Build Coastguard Worker
2443*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2444*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
2445*9880d681SAndroid Build Coastguard Worker
2446*9880d681SAndroid Build Coastguard Worker SDValue N0 = N->getOperand(0);
2447*9880d681SAndroid Build Coastguard Worker SDValue N1 = N->getOperand(1);
2448*9880d681SAndroid Build Coastguard Worker SDValue Mul;
2449*9880d681SAndroid Build Coastguard Worker
2450*9880d681SAndroid Build Coastguard Worker if (Subtarget->hasMulU24() && isU24(N0, DAG) && isU24(N1, DAG)) {
2451*9880d681SAndroid Build Coastguard Worker N0 = DAG.getZExtOrTrunc(N0, DL, MVT::i32);
2452*9880d681SAndroid Build Coastguard Worker N1 = DAG.getZExtOrTrunc(N1, DL, MVT::i32);
2453*9880d681SAndroid Build Coastguard Worker Mul = DAG.getNode(AMDGPUISD::MUL_U24, DL, MVT::i32, N0, N1);
2454*9880d681SAndroid Build Coastguard Worker } else if (Subtarget->hasMulI24() && isI24(N0, DAG) && isI24(N1, DAG)) {
2455*9880d681SAndroid Build Coastguard Worker N0 = DAG.getSExtOrTrunc(N0, DL, MVT::i32);
2456*9880d681SAndroid Build Coastguard Worker N1 = DAG.getSExtOrTrunc(N1, DL, MVT::i32);
2457*9880d681SAndroid Build Coastguard Worker Mul = DAG.getNode(AMDGPUISD::MUL_I24, DL, MVT::i32, N0, N1);
2458*9880d681SAndroid Build Coastguard Worker } else {
2459*9880d681SAndroid Build Coastguard Worker return SDValue();
2460*9880d681SAndroid Build Coastguard Worker }
2461*9880d681SAndroid Build Coastguard Worker
2462*9880d681SAndroid Build Coastguard Worker // We need to use sext even for MUL_U24, because MUL_U24 is used
2463*9880d681SAndroid Build Coastguard Worker // for signed multiply of 8 and 16-bit types.
2464*9880d681SAndroid Build Coastguard Worker return DAG.getSExtOrTrunc(Mul, DL, VT);
2465*9880d681SAndroid Build Coastguard Worker }
2466*9880d681SAndroid Build Coastguard Worker
isNegativeOne(SDValue Val)2467*9880d681SAndroid Build Coastguard Worker static bool isNegativeOne(SDValue Val) {
2468*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val))
2469*9880d681SAndroid Build Coastguard Worker return C->isAllOnesValue();
2470*9880d681SAndroid Build Coastguard Worker return false;
2471*9880d681SAndroid Build Coastguard Worker }
2472*9880d681SAndroid Build Coastguard Worker
isCtlzOpc(unsigned Opc)2473*9880d681SAndroid Build Coastguard Worker static bool isCtlzOpc(unsigned Opc) {
2474*9880d681SAndroid Build Coastguard Worker return Opc == ISD::CTLZ || Opc == ISD::CTLZ_ZERO_UNDEF;
2475*9880d681SAndroid Build Coastguard Worker }
2476*9880d681SAndroid Build Coastguard Worker
2477*9880d681SAndroid Build Coastguard Worker // Get FFBH node if the incoming op may have been type legalized from a smaller
2478*9880d681SAndroid Build Coastguard Worker // type VT.
2479*9880d681SAndroid Build Coastguard Worker // Need to match pre-legalized type because the generic legalization inserts the
2480*9880d681SAndroid Build Coastguard Worker // add/sub between the select and compare.
getFFBH_U32(const TargetLowering & TLI,SelectionDAG & DAG,const SDLoc & SL,SDValue Op)2481*9880d681SAndroid Build Coastguard Worker static SDValue getFFBH_U32(const TargetLowering &TLI, SelectionDAG &DAG,
2482*9880d681SAndroid Build Coastguard Worker const SDLoc &SL, SDValue Op) {
2483*9880d681SAndroid Build Coastguard Worker EVT VT = Op.getValueType();
2484*9880d681SAndroid Build Coastguard Worker EVT LegalVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
2485*9880d681SAndroid Build Coastguard Worker if (LegalVT != MVT::i32)
2486*9880d681SAndroid Build Coastguard Worker return SDValue();
2487*9880d681SAndroid Build Coastguard Worker
2488*9880d681SAndroid Build Coastguard Worker if (VT != MVT::i32)
2489*9880d681SAndroid Build Coastguard Worker Op = DAG.getNode(ISD::ZERO_EXTEND, SL, MVT::i32, Op);
2490*9880d681SAndroid Build Coastguard Worker
2491*9880d681SAndroid Build Coastguard Worker SDValue FFBH = DAG.getNode(AMDGPUISD::FFBH_U32, SL, MVT::i32, Op);
2492*9880d681SAndroid Build Coastguard Worker if (VT != MVT::i32)
2493*9880d681SAndroid Build Coastguard Worker FFBH = DAG.getNode(ISD::TRUNCATE, SL, VT, FFBH);
2494*9880d681SAndroid Build Coastguard Worker
2495*9880d681SAndroid Build Coastguard Worker return FFBH;
2496*9880d681SAndroid Build Coastguard Worker }
2497*9880d681SAndroid Build Coastguard Worker
2498*9880d681SAndroid Build Coastguard Worker // The native instructions return -1 on 0 input. Optimize out a select that
2499*9880d681SAndroid Build Coastguard Worker // produces -1 on 0.
2500*9880d681SAndroid Build Coastguard Worker //
2501*9880d681SAndroid Build Coastguard Worker // TODO: If zero is not undef, we could also do this if the output is compared
2502*9880d681SAndroid Build Coastguard Worker // against the bitwidth.
2503*9880d681SAndroid Build Coastguard Worker //
2504*9880d681SAndroid Build Coastguard Worker // TODO: Should probably combine against FFBH_U32 instead of ctlz directly.
performCtlzCombine(const SDLoc & SL,SDValue Cond,SDValue LHS,SDValue RHS,DAGCombinerInfo & DCI) const2505*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performCtlzCombine(const SDLoc &SL, SDValue Cond,
2506*9880d681SAndroid Build Coastguard Worker SDValue LHS, SDValue RHS,
2507*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2508*9880d681SAndroid Build Coastguard Worker ConstantSDNode *CmpRhs = dyn_cast<ConstantSDNode>(Cond.getOperand(1));
2509*9880d681SAndroid Build Coastguard Worker if (!CmpRhs || !CmpRhs->isNullValue())
2510*9880d681SAndroid Build Coastguard Worker return SDValue();
2511*9880d681SAndroid Build Coastguard Worker
2512*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2513*9880d681SAndroid Build Coastguard Worker ISD::CondCode CCOpcode = cast<CondCodeSDNode>(Cond.getOperand(2))->get();
2514*9880d681SAndroid Build Coastguard Worker SDValue CmpLHS = Cond.getOperand(0);
2515*9880d681SAndroid Build Coastguard Worker
2516*9880d681SAndroid Build Coastguard Worker // select (setcc x, 0, eq), -1, (ctlz_zero_undef x) -> ffbh_u32 x
2517*9880d681SAndroid Build Coastguard Worker if (CCOpcode == ISD::SETEQ &&
2518*9880d681SAndroid Build Coastguard Worker isCtlzOpc(RHS.getOpcode()) &&
2519*9880d681SAndroid Build Coastguard Worker RHS.getOperand(0) == CmpLHS &&
2520*9880d681SAndroid Build Coastguard Worker isNegativeOne(LHS)) {
2521*9880d681SAndroid Build Coastguard Worker return getFFBH_U32(*this, DAG, SL, CmpLHS);
2522*9880d681SAndroid Build Coastguard Worker }
2523*9880d681SAndroid Build Coastguard Worker
2524*9880d681SAndroid Build Coastguard Worker // select (setcc x, 0, ne), (ctlz_zero_undef x), -1 -> ffbh_u32 x
2525*9880d681SAndroid Build Coastguard Worker if (CCOpcode == ISD::SETNE &&
2526*9880d681SAndroid Build Coastguard Worker isCtlzOpc(LHS.getOpcode()) &&
2527*9880d681SAndroid Build Coastguard Worker LHS.getOperand(0) == CmpLHS &&
2528*9880d681SAndroid Build Coastguard Worker isNegativeOne(RHS)) {
2529*9880d681SAndroid Build Coastguard Worker return getFFBH_U32(*this, DAG, SL, CmpLHS);
2530*9880d681SAndroid Build Coastguard Worker }
2531*9880d681SAndroid Build Coastguard Worker
2532*9880d681SAndroid Build Coastguard Worker return SDValue();
2533*9880d681SAndroid Build Coastguard Worker }
2534*9880d681SAndroid Build Coastguard Worker
performSelectCombine(SDNode * N,DAGCombinerInfo & DCI) const2535*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::performSelectCombine(SDNode *N,
2536*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2537*9880d681SAndroid Build Coastguard Worker SDValue Cond = N->getOperand(0);
2538*9880d681SAndroid Build Coastguard Worker if (Cond.getOpcode() != ISD::SETCC)
2539*9880d681SAndroid Build Coastguard Worker return SDValue();
2540*9880d681SAndroid Build Coastguard Worker
2541*9880d681SAndroid Build Coastguard Worker EVT VT = N->getValueType(0);
2542*9880d681SAndroid Build Coastguard Worker SDValue LHS = Cond.getOperand(0);
2543*9880d681SAndroid Build Coastguard Worker SDValue RHS = Cond.getOperand(1);
2544*9880d681SAndroid Build Coastguard Worker SDValue CC = Cond.getOperand(2);
2545*9880d681SAndroid Build Coastguard Worker
2546*9880d681SAndroid Build Coastguard Worker SDValue True = N->getOperand(1);
2547*9880d681SAndroid Build Coastguard Worker SDValue False = N->getOperand(2);
2548*9880d681SAndroid Build Coastguard Worker
2549*9880d681SAndroid Build Coastguard Worker if (VT == MVT::f32 && Cond.hasOneUse()) {
2550*9880d681SAndroid Build Coastguard Worker SDValue MinMax
2551*9880d681SAndroid Build Coastguard Worker = CombineFMinMaxLegacy(SDLoc(N), VT, LHS, RHS, True, False, CC, DCI);
2552*9880d681SAndroid Build Coastguard Worker // Revisit this node so we can catch min3/max3/med3 patterns.
2553*9880d681SAndroid Build Coastguard Worker //DCI.AddToWorklist(MinMax.getNode());
2554*9880d681SAndroid Build Coastguard Worker return MinMax;
2555*9880d681SAndroid Build Coastguard Worker }
2556*9880d681SAndroid Build Coastguard Worker
2557*9880d681SAndroid Build Coastguard Worker // There's no reason to not do this if the condition has other uses.
2558*9880d681SAndroid Build Coastguard Worker return performCtlzCombine(SDLoc(N), Cond, True, False, DCI);
2559*9880d681SAndroid Build Coastguard Worker }
2560*9880d681SAndroid Build Coastguard Worker
PerformDAGCombine(SDNode * N,DAGCombinerInfo & DCI) const2561*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::PerformDAGCombine(SDNode *N,
2562*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI) const {
2563*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2564*9880d681SAndroid Build Coastguard Worker SDLoc DL(N);
2565*9880d681SAndroid Build Coastguard Worker
2566*9880d681SAndroid Build Coastguard Worker switch(N->getOpcode()) {
2567*9880d681SAndroid Build Coastguard Worker default:
2568*9880d681SAndroid Build Coastguard Worker break;
2569*9880d681SAndroid Build Coastguard Worker case ISD::BITCAST: {
2570*9880d681SAndroid Build Coastguard Worker EVT DestVT = N->getValueType(0);
2571*9880d681SAndroid Build Coastguard Worker if (DestVT.getSizeInBits() != 64 && !DestVT.isVector())
2572*9880d681SAndroid Build Coastguard Worker break;
2573*9880d681SAndroid Build Coastguard Worker
2574*9880d681SAndroid Build Coastguard Worker // Fold bitcasts of constants.
2575*9880d681SAndroid Build Coastguard Worker //
2576*9880d681SAndroid Build Coastguard Worker // v2i32 (bitcast i64:k) -> build_vector lo_32(k), hi_32(k)
2577*9880d681SAndroid Build Coastguard Worker // TODO: Generalize and move to DAGCombiner
2578*9880d681SAndroid Build Coastguard Worker SDValue Src = N->getOperand(0);
2579*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Src)) {
2580*9880d681SAndroid Build Coastguard Worker assert(Src.getValueType() == MVT::i64);
2581*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
2582*9880d681SAndroid Build Coastguard Worker uint64_t CVal = C->getZExtValue();
2583*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BUILD_VECTOR, SL, DestVT,
2584*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Lo_32(CVal), SL, MVT::i32),
2585*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Hi_32(CVal), SL, MVT::i32));
2586*9880d681SAndroid Build Coastguard Worker }
2587*9880d681SAndroid Build Coastguard Worker
2588*9880d681SAndroid Build Coastguard Worker if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Src)) {
2589*9880d681SAndroid Build Coastguard Worker const APInt &Val = C->getValueAPF().bitcastToAPInt();
2590*9880d681SAndroid Build Coastguard Worker SDLoc SL(N);
2591*9880d681SAndroid Build Coastguard Worker uint64_t CVal = Val.getZExtValue();
2592*9880d681SAndroid Build Coastguard Worker SDValue Vec = DAG.getNode(ISD::BUILD_VECTOR, SL, MVT::v2i32,
2593*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Lo_32(CVal), SL, MVT::i32),
2594*9880d681SAndroid Build Coastguard Worker DAG.getConstant(Hi_32(CVal), SL, MVT::i32));
2595*9880d681SAndroid Build Coastguard Worker
2596*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::BITCAST, SL, DestVT, Vec);
2597*9880d681SAndroid Build Coastguard Worker }
2598*9880d681SAndroid Build Coastguard Worker
2599*9880d681SAndroid Build Coastguard Worker break;
2600*9880d681SAndroid Build Coastguard Worker }
2601*9880d681SAndroid Build Coastguard Worker case ISD::SHL: {
2602*9880d681SAndroid Build Coastguard Worker if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
2603*9880d681SAndroid Build Coastguard Worker break;
2604*9880d681SAndroid Build Coastguard Worker
2605*9880d681SAndroid Build Coastguard Worker return performShlCombine(N, DCI);
2606*9880d681SAndroid Build Coastguard Worker }
2607*9880d681SAndroid Build Coastguard Worker case ISD::SRL: {
2608*9880d681SAndroid Build Coastguard Worker if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
2609*9880d681SAndroid Build Coastguard Worker break;
2610*9880d681SAndroid Build Coastguard Worker
2611*9880d681SAndroid Build Coastguard Worker return performSrlCombine(N, DCI);
2612*9880d681SAndroid Build Coastguard Worker }
2613*9880d681SAndroid Build Coastguard Worker case ISD::SRA: {
2614*9880d681SAndroid Build Coastguard Worker if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
2615*9880d681SAndroid Build Coastguard Worker break;
2616*9880d681SAndroid Build Coastguard Worker
2617*9880d681SAndroid Build Coastguard Worker return performSraCombine(N, DCI);
2618*9880d681SAndroid Build Coastguard Worker }
2619*9880d681SAndroid Build Coastguard Worker case ISD::AND: {
2620*9880d681SAndroid Build Coastguard Worker if (DCI.getDAGCombineLevel() < AfterLegalizeDAG)
2621*9880d681SAndroid Build Coastguard Worker break;
2622*9880d681SAndroid Build Coastguard Worker
2623*9880d681SAndroid Build Coastguard Worker return performAndCombine(N, DCI);
2624*9880d681SAndroid Build Coastguard Worker }
2625*9880d681SAndroid Build Coastguard Worker case ISD::MUL:
2626*9880d681SAndroid Build Coastguard Worker return performMulCombine(N, DCI);
2627*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::MUL_I24:
2628*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::MUL_U24: {
2629*9880d681SAndroid Build Coastguard Worker SDValue N0 = N->getOperand(0);
2630*9880d681SAndroid Build Coastguard Worker SDValue N1 = N->getOperand(1);
2631*9880d681SAndroid Build Coastguard Worker simplifyI24(N0, DCI);
2632*9880d681SAndroid Build Coastguard Worker simplifyI24(N1, DCI);
2633*9880d681SAndroid Build Coastguard Worker return SDValue();
2634*9880d681SAndroid Build Coastguard Worker }
2635*9880d681SAndroid Build Coastguard Worker case ISD::SELECT:
2636*9880d681SAndroid Build Coastguard Worker return performSelectCombine(N, DCI);
2637*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BFE_I32:
2638*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BFE_U32: {
2639*9880d681SAndroid Build Coastguard Worker assert(!N->getValueType(0).isVector() &&
2640*9880d681SAndroid Build Coastguard Worker "Vector handling of BFE not implemented");
2641*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Width = dyn_cast<ConstantSDNode>(N->getOperand(2));
2642*9880d681SAndroid Build Coastguard Worker if (!Width)
2643*9880d681SAndroid Build Coastguard Worker break;
2644*9880d681SAndroid Build Coastguard Worker
2645*9880d681SAndroid Build Coastguard Worker uint32_t WidthVal = Width->getZExtValue() & 0x1f;
2646*9880d681SAndroid Build Coastguard Worker if (WidthVal == 0)
2647*9880d681SAndroid Build Coastguard Worker return DAG.getConstant(0, DL, MVT::i32);
2648*9880d681SAndroid Build Coastguard Worker
2649*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1));
2650*9880d681SAndroid Build Coastguard Worker if (!Offset)
2651*9880d681SAndroid Build Coastguard Worker break;
2652*9880d681SAndroid Build Coastguard Worker
2653*9880d681SAndroid Build Coastguard Worker SDValue BitsFrom = N->getOperand(0);
2654*9880d681SAndroid Build Coastguard Worker uint32_t OffsetVal = Offset->getZExtValue() & 0x1f;
2655*9880d681SAndroid Build Coastguard Worker
2656*9880d681SAndroid Build Coastguard Worker bool Signed = N->getOpcode() == AMDGPUISD::BFE_I32;
2657*9880d681SAndroid Build Coastguard Worker
2658*9880d681SAndroid Build Coastguard Worker if (OffsetVal == 0) {
2659*9880d681SAndroid Build Coastguard Worker // This is already sign / zero extended, so try to fold away extra BFEs.
2660*9880d681SAndroid Build Coastguard Worker unsigned SignBits = Signed ? (32 - WidthVal + 1) : (32 - WidthVal);
2661*9880d681SAndroid Build Coastguard Worker
2662*9880d681SAndroid Build Coastguard Worker unsigned OpSignBits = DAG.ComputeNumSignBits(BitsFrom);
2663*9880d681SAndroid Build Coastguard Worker if (OpSignBits >= SignBits)
2664*9880d681SAndroid Build Coastguard Worker return BitsFrom;
2665*9880d681SAndroid Build Coastguard Worker
2666*9880d681SAndroid Build Coastguard Worker EVT SmallVT = EVT::getIntegerVT(*DAG.getContext(), WidthVal);
2667*9880d681SAndroid Build Coastguard Worker if (Signed) {
2668*9880d681SAndroid Build Coastguard Worker // This is a sign_extend_inreg. Replace it to take advantage of existing
2669*9880d681SAndroid Build Coastguard Worker // DAG Combines. If not eliminated, we will match back to BFE during
2670*9880d681SAndroid Build Coastguard Worker // selection.
2671*9880d681SAndroid Build Coastguard Worker
2672*9880d681SAndroid Build Coastguard Worker // TODO: The sext_inreg of extended types ends, although we can could
2673*9880d681SAndroid Build Coastguard Worker // handle them in a single BFE.
2674*9880d681SAndroid Build Coastguard Worker return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i32, BitsFrom,
2675*9880d681SAndroid Build Coastguard Worker DAG.getValueType(SmallVT));
2676*9880d681SAndroid Build Coastguard Worker }
2677*9880d681SAndroid Build Coastguard Worker
2678*9880d681SAndroid Build Coastguard Worker return DAG.getZeroExtendInReg(BitsFrom, DL, SmallVT);
2679*9880d681SAndroid Build Coastguard Worker }
2680*9880d681SAndroid Build Coastguard Worker
2681*9880d681SAndroid Build Coastguard Worker if (ConstantSDNode *CVal = dyn_cast<ConstantSDNode>(BitsFrom)) {
2682*9880d681SAndroid Build Coastguard Worker if (Signed) {
2683*9880d681SAndroid Build Coastguard Worker return constantFoldBFE<int32_t>(DAG,
2684*9880d681SAndroid Build Coastguard Worker CVal->getSExtValue(),
2685*9880d681SAndroid Build Coastguard Worker OffsetVal,
2686*9880d681SAndroid Build Coastguard Worker WidthVal,
2687*9880d681SAndroid Build Coastguard Worker DL);
2688*9880d681SAndroid Build Coastguard Worker }
2689*9880d681SAndroid Build Coastguard Worker
2690*9880d681SAndroid Build Coastguard Worker return constantFoldBFE<uint32_t>(DAG,
2691*9880d681SAndroid Build Coastguard Worker CVal->getZExtValue(),
2692*9880d681SAndroid Build Coastguard Worker OffsetVal,
2693*9880d681SAndroid Build Coastguard Worker WidthVal,
2694*9880d681SAndroid Build Coastguard Worker DL);
2695*9880d681SAndroid Build Coastguard Worker }
2696*9880d681SAndroid Build Coastguard Worker
2697*9880d681SAndroid Build Coastguard Worker if ((OffsetVal + WidthVal) >= 32) {
2698*9880d681SAndroid Build Coastguard Worker SDValue ShiftVal = DAG.getConstant(OffsetVal, DL, MVT::i32);
2699*9880d681SAndroid Build Coastguard Worker return DAG.getNode(Signed ? ISD::SRA : ISD::SRL, DL, MVT::i32,
2700*9880d681SAndroid Build Coastguard Worker BitsFrom, ShiftVal);
2701*9880d681SAndroid Build Coastguard Worker }
2702*9880d681SAndroid Build Coastguard Worker
2703*9880d681SAndroid Build Coastguard Worker if (BitsFrom.hasOneUse()) {
2704*9880d681SAndroid Build Coastguard Worker APInt Demanded = APInt::getBitsSet(32,
2705*9880d681SAndroid Build Coastguard Worker OffsetVal,
2706*9880d681SAndroid Build Coastguard Worker OffsetVal + WidthVal);
2707*9880d681SAndroid Build Coastguard Worker
2708*9880d681SAndroid Build Coastguard Worker APInt KnownZero, KnownOne;
2709*9880d681SAndroid Build Coastguard Worker TargetLowering::TargetLoweringOpt TLO(DAG, !DCI.isBeforeLegalize(),
2710*9880d681SAndroid Build Coastguard Worker !DCI.isBeforeLegalizeOps());
2711*9880d681SAndroid Build Coastguard Worker const TargetLowering &TLI = DAG.getTargetLoweringInfo();
2712*9880d681SAndroid Build Coastguard Worker if (TLO.ShrinkDemandedConstant(BitsFrom, Demanded) ||
2713*9880d681SAndroid Build Coastguard Worker TLI.SimplifyDemandedBits(BitsFrom, Demanded,
2714*9880d681SAndroid Build Coastguard Worker KnownZero, KnownOne, TLO)) {
2715*9880d681SAndroid Build Coastguard Worker DCI.CommitTargetLoweringOpt(TLO);
2716*9880d681SAndroid Build Coastguard Worker }
2717*9880d681SAndroid Build Coastguard Worker }
2718*9880d681SAndroid Build Coastguard Worker
2719*9880d681SAndroid Build Coastguard Worker break;
2720*9880d681SAndroid Build Coastguard Worker }
2721*9880d681SAndroid Build Coastguard Worker case ISD::LOAD:
2722*9880d681SAndroid Build Coastguard Worker return performLoadCombine(N, DCI);
2723*9880d681SAndroid Build Coastguard Worker case ISD::STORE:
2724*9880d681SAndroid Build Coastguard Worker return performStoreCombine(N, DCI);
2725*9880d681SAndroid Build Coastguard Worker }
2726*9880d681SAndroid Build Coastguard Worker return SDValue();
2727*9880d681SAndroid Build Coastguard Worker }
2728*9880d681SAndroid Build Coastguard Worker
2729*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2730*9880d681SAndroid Build Coastguard Worker // Helper functions
2731*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2732*9880d681SAndroid Build Coastguard Worker
getOriginalFunctionArgs(SelectionDAG & DAG,const Function * F,const SmallVectorImpl<ISD::InputArg> & Ins,SmallVectorImpl<ISD::InputArg> & OrigIns) const2733*9880d681SAndroid Build Coastguard Worker void AMDGPUTargetLowering::getOriginalFunctionArgs(
2734*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG,
2735*9880d681SAndroid Build Coastguard Worker const Function *F,
2736*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<ISD::InputArg> &Ins,
2737*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<ISD::InputArg> &OrigIns) const {
2738*9880d681SAndroid Build Coastguard Worker
2739*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Ins.size(); i < e; ++i) {
2740*9880d681SAndroid Build Coastguard Worker if (Ins[i].ArgVT == Ins[i].VT) {
2741*9880d681SAndroid Build Coastguard Worker OrigIns.push_back(Ins[i]);
2742*9880d681SAndroid Build Coastguard Worker continue;
2743*9880d681SAndroid Build Coastguard Worker }
2744*9880d681SAndroid Build Coastguard Worker
2745*9880d681SAndroid Build Coastguard Worker EVT VT;
2746*9880d681SAndroid Build Coastguard Worker if (Ins[i].ArgVT.isVector() && !Ins[i].VT.isVector()) {
2747*9880d681SAndroid Build Coastguard Worker // Vector has been split into scalars.
2748*9880d681SAndroid Build Coastguard Worker VT = Ins[i].ArgVT.getVectorElementType();
2749*9880d681SAndroid Build Coastguard Worker } else if (Ins[i].VT.isVector() && Ins[i].ArgVT.isVector() &&
2750*9880d681SAndroid Build Coastguard Worker Ins[i].ArgVT.getVectorElementType() !=
2751*9880d681SAndroid Build Coastguard Worker Ins[i].VT.getVectorElementType()) {
2752*9880d681SAndroid Build Coastguard Worker // Vector elements have been promoted
2753*9880d681SAndroid Build Coastguard Worker VT = Ins[i].ArgVT;
2754*9880d681SAndroid Build Coastguard Worker } else {
2755*9880d681SAndroid Build Coastguard Worker // Vector has been spilt into smaller vectors.
2756*9880d681SAndroid Build Coastguard Worker VT = Ins[i].VT;
2757*9880d681SAndroid Build Coastguard Worker }
2758*9880d681SAndroid Build Coastguard Worker
2759*9880d681SAndroid Build Coastguard Worker ISD::InputArg Arg(Ins[i].Flags, VT, VT, Ins[i].Used,
2760*9880d681SAndroid Build Coastguard Worker Ins[i].OrigArgIndex, Ins[i].PartOffset);
2761*9880d681SAndroid Build Coastguard Worker OrigIns.push_back(Arg);
2762*9880d681SAndroid Build Coastguard Worker }
2763*9880d681SAndroid Build Coastguard Worker }
2764*9880d681SAndroid Build Coastguard Worker
CreateLiveInRegister(SelectionDAG & DAG,const TargetRegisterClass * RC,unsigned Reg,EVT VT) const2765*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::CreateLiveInRegister(SelectionDAG &DAG,
2766*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC,
2767*9880d681SAndroid Build Coastguard Worker unsigned Reg, EVT VT) const {
2768*9880d681SAndroid Build Coastguard Worker MachineFunction &MF = DAG.getMachineFunction();
2769*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MF.getRegInfo();
2770*9880d681SAndroid Build Coastguard Worker unsigned VirtualRegister;
2771*9880d681SAndroid Build Coastguard Worker if (!MRI.isLiveIn(Reg)) {
2772*9880d681SAndroid Build Coastguard Worker VirtualRegister = MRI.createVirtualRegister(RC);
2773*9880d681SAndroid Build Coastguard Worker MRI.addLiveIn(Reg, VirtualRegister);
2774*9880d681SAndroid Build Coastguard Worker } else {
2775*9880d681SAndroid Build Coastguard Worker VirtualRegister = MRI.getLiveInVirtReg(Reg);
2776*9880d681SAndroid Build Coastguard Worker }
2777*9880d681SAndroid Build Coastguard Worker return DAG.getRegister(VirtualRegister, VT);
2778*9880d681SAndroid Build Coastguard Worker }
2779*9880d681SAndroid Build Coastguard Worker
getImplicitParameterOffset(const AMDGPUMachineFunction * MFI,const ImplicitParameter Param) const2780*9880d681SAndroid Build Coastguard Worker uint32_t AMDGPUTargetLowering::getImplicitParameterOffset(
2781*9880d681SAndroid Build Coastguard Worker const AMDGPUMachineFunction *MFI, const ImplicitParameter Param) const {
2782*9880d681SAndroid Build Coastguard Worker uint64_t ArgOffset = MFI->ABIArgOffset;
2783*9880d681SAndroid Build Coastguard Worker switch (Param) {
2784*9880d681SAndroid Build Coastguard Worker case GRID_DIM:
2785*9880d681SAndroid Build Coastguard Worker return ArgOffset;
2786*9880d681SAndroid Build Coastguard Worker case GRID_OFFSET:
2787*9880d681SAndroid Build Coastguard Worker return ArgOffset + 4;
2788*9880d681SAndroid Build Coastguard Worker }
2789*9880d681SAndroid Build Coastguard Worker llvm_unreachable("unexpected implicit parameter type");
2790*9880d681SAndroid Build Coastguard Worker }
2791*9880d681SAndroid Build Coastguard Worker
2792*9880d681SAndroid Build Coastguard Worker #define NODE_NAME_CASE(node) case AMDGPUISD::node: return #node;
2793*9880d681SAndroid Build Coastguard Worker
getTargetNodeName(unsigned Opcode) const2794*9880d681SAndroid Build Coastguard Worker const char* AMDGPUTargetLowering::getTargetNodeName(unsigned Opcode) const {
2795*9880d681SAndroid Build Coastguard Worker switch ((AMDGPUISD::NodeType)Opcode) {
2796*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::FIRST_NUMBER: break;
2797*9880d681SAndroid Build Coastguard Worker // AMDIL DAG nodes
2798*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CALL);
2799*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(UMUL);
2800*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(BRANCH_COND);
2801*9880d681SAndroid Build Coastguard Worker
2802*9880d681SAndroid Build Coastguard Worker // AMDGPU DAG nodes
2803*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(ENDPGM)
2804*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(RETURN)
2805*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(DWORDADDR)
2806*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(FRACT)
2807*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CLAMP)
2808*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(COS_HW)
2809*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SIN_HW)
2810*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(FMAX_LEGACY)
2811*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(FMIN_LEGACY)
2812*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(FMAX3)
2813*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SMAX3)
2814*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(UMAX3)
2815*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(FMIN3)
2816*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SMIN3)
2817*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(UMIN3)
2818*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(FMED3)
2819*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SMED3)
2820*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(UMED3)
2821*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(URECIP)
2822*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(DIV_SCALE)
2823*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(DIV_FMAS)
2824*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(DIV_FIXUP)
2825*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(TRIG_PREOP)
2826*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(RCP)
2827*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(RSQ)
2828*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(RSQ_LEGACY)
2829*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(RSQ_CLAMP)
2830*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(LDEXP)
2831*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(FP_CLASS)
2832*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(DOT4)
2833*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CARRY)
2834*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(BORROW)
2835*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(BFE_U32)
2836*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(BFE_I32)
2837*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(BFI)
2838*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(BFM)
2839*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(FFBH_U32)
2840*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(MUL_U24)
2841*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(MUL_I24)
2842*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(MAD_U24)
2843*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(MAD_I24)
2844*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(TEXTURE_FETCH)
2845*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(EXPORT)
2846*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CONST_ADDRESS)
2847*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(REGISTER_LOAD)
2848*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(REGISTER_STORE)
2849*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(LOAD_INPUT)
2850*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SAMPLE)
2851*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SAMPLEB)
2852*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SAMPLED)
2853*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SAMPLEL)
2854*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CVT_F32_UBYTE0)
2855*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CVT_F32_UBYTE1)
2856*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CVT_F32_UBYTE2)
2857*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CVT_F32_UBYTE3)
2858*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(BUILD_VERTICAL_VECTOR)
2859*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(CONST_DATA_PTR)
2860*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(PC_ADD_REL_OFFSET)
2861*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::FIRST_MEM_OPCODE_NUMBER: break;
2862*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(SENDMSG)
2863*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(INTERP_MOV)
2864*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(INTERP_P1)
2865*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(INTERP_P2)
2866*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(STORE_MSKOR)
2867*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(LOAD_CONSTANT)
2868*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(TBUFFER_STORE_FORMAT)
2869*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(ATOMIC_CMP_SWAP)
2870*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(ATOMIC_INC)
2871*9880d681SAndroid Build Coastguard Worker NODE_NAME_CASE(ATOMIC_DEC)
2872*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::LAST_AMDGPU_ISD_NUMBER: break;
2873*9880d681SAndroid Build Coastguard Worker }
2874*9880d681SAndroid Build Coastguard Worker return nullptr;
2875*9880d681SAndroid Build Coastguard Worker }
2876*9880d681SAndroid Build Coastguard Worker
getRsqrtEstimate(SDValue Operand,DAGCombinerInfo & DCI,unsigned & RefinementSteps,bool & UseOneConstNR) const2877*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::getRsqrtEstimate(SDValue Operand,
2878*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI,
2879*9880d681SAndroid Build Coastguard Worker unsigned &RefinementSteps,
2880*9880d681SAndroid Build Coastguard Worker bool &UseOneConstNR) const {
2881*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2882*9880d681SAndroid Build Coastguard Worker EVT VT = Operand.getValueType();
2883*9880d681SAndroid Build Coastguard Worker
2884*9880d681SAndroid Build Coastguard Worker if (VT == MVT::f32) {
2885*9880d681SAndroid Build Coastguard Worker RefinementSteps = 0;
2886*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::RSQ, SDLoc(Operand), VT, Operand);
2887*9880d681SAndroid Build Coastguard Worker }
2888*9880d681SAndroid Build Coastguard Worker
2889*9880d681SAndroid Build Coastguard Worker // TODO: There is also f64 rsq instruction, but the documentation is less
2890*9880d681SAndroid Build Coastguard Worker // clear on its precision.
2891*9880d681SAndroid Build Coastguard Worker
2892*9880d681SAndroid Build Coastguard Worker return SDValue();
2893*9880d681SAndroid Build Coastguard Worker }
2894*9880d681SAndroid Build Coastguard Worker
getRecipEstimate(SDValue Operand,DAGCombinerInfo & DCI,unsigned & RefinementSteps) const2895*9880d681SAndroid Build Coastguard Worker SDValue AMDGPUTargetLowering::getRecipEstimate(SDValue Operand,
2896*9880d681SAndroid Build Coastguard Worker DAGCombinerInfo &DCI,
2897*9880d681SAndroid Build Coastguard Worker unsigned &RefinementSteps) const {
2898*9880d681SAndroid Build Coastguard Worker SelectionDAG &DAG = DCI.DAG;
2899*9880d681SAndroid Build Coastguard Worker EVT VT = Operand.getValueType();
2900*9880d681SAndroid Build Coastguard Worker
2901*9880d681SAndroid Build Coastguard Worker if (VT == MVT::f32) {
2902*9880d681SAndroid Build Coastguard Worker // Reciprocal, < 1 ulp error.
2903*9880d681SAndroid Build Coastguard Worker //
2904*9880d681SAndroid Build Coastguard Worker // This reciprocal approximation converges to < 0.5 ulp error with one
2905*9880d681SAndroid Build Coastguard Worker // newton rhapson performed with two fused multiple adds (FMAs).
2906*9880d681SAndroid Build Coastguard Worker
2907*9880d681SAndroid Build Coastguard Worker RefinementSteps = 0;
2908*9880d681SAndroid Build Coastguard Worker return DAG.getNode(AMDGPUISD::RCP, SDLoc(Operand), VT, Operand);
2909*9880d681SAndroid Build Coastguard Worker }
2910*9880d681SAndroid Build Coastguard Worker
2911*9880d681SAndroid Build Coastguard Worker // TODO: There is also f64 rcp instruction, but the documentation is less
2912*9880d681SAndroid Build Coastguard Worker // clear on its precision.
2913*9880d681SAndroid Build Coastguard Worker
2914*9880d681SAndroid Build Coastguard Worker return SDValue();
2915*9880d681SAndroid Build Coastguard Worker }
2916*9880d681SAndroid Build Coastguard Worker
computeKnownBitsForTargetNode(const SDValue Op,APInt & KnownZero,APInt & KnownOne,const SelectionDAG & DAG,unsigned Depth) const2917*9880d681SAndroid Build Coastguard Worker void AMDGPUTargetLowering::computeKnownBitsForTargetNode(
2918*9880d681SAndroid Build Coastguard Worker const SDValue Op,
2919*9880d681SAndroid Build Coastguard Worker APInt &KnownZero,
2920*9880d681SAndroid Build Coastguard Worker APInt &KnownOne,
2921*9880d681SAndroid Build Coastguard Worker const SelectionDAG &DAG,
2922*9880d681SAndroid Build Coastguard Worker unsigned Depth) const {
2923*9880d681SAndroid Build Coastguard Worker
2924*9880d681SAndroid Build Coastguard Worker KnownZero = KnownOne = APInt(KnownOne.getBitWidth(), 0); // Don't know anything.
2925*9880d681SAndroid Build Coastguard Worker
2926*9880d681SAndroid Build Coastguard Worker APInt KnownZero2;
2927*9880d681SAndroid Build Coastguard Worker APInt KnownOne2;
2928*9880d681SAndroid Build Coastguard Worker unsigned Opc = Op.getOpcode();
2929*9880d681SAndroid Build Coastguard Worker
2930*9880d681SAndroid Build Coastguard Worker switch (Opc) {
2931*9880d681SAndroid Build Coastguard Worker default:
2932*9880d681SAndroid Build Coastguard Worker break;
2933*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::CARRY:
2934*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BORROW: {
2935*9880d681SAndroid Build Coastguard Worker KnownZero = APInt::getHighBitsSet(32, 31);
2936*9880d681SAndroid Build Coastguard Worker break;
2937*9880d681SAndroid Build Coastguard Worker }
2938*9880d681SAndroid Build Coastguard Worker
2939*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BFE_I32:
2940*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BFE_U32: {
2941*9880d681SAndroid Build Coastguard Worker ConstantSDNode *CWidth = dyn_cast<ConstantSDNode>(Op.getOperand(2));
2942*9880d681SAndroid Build Coastguard Worker if (!CWidth)
2943*9880d681SAndroid Build Coastguard Worker return;
2944*9880d681SAndroid Build Coastguard Worker
2945*9880d681SAndroid Build Coastguard Worker unsigned BitWidth = 32;
2946*9880d681SAndroid Build Coastguard Worker uint32_t Width = CWidth->getZExtValue() & 0x1f;
2947*9880d681SAndroid Build Coastguard Worker
2948*9880d681SAndroid Build Coastguard Worker if (Opc == AMDGPUISD::BFE_U32)
2949*9880d681SAndroid Build Coastguard Worker KnownZero = APInt::getHighBitsSet(BitWidth, BitWidth - Width);
2950*9880d681SAndroid Build Coastguard Worker
2951*9880d681SAndroid Build Coastguard Worker break;
2952*9880d681SAndroid Build Coastguard Worker }
2953*9880d681SAndroid Build Coastguard Worker }
2954*9880d681SAndroid Build Coastguard Worker }
2955*9880d681SAndroid Build Coastguard Worker
ComputeNumSignBitsForTargetNode(SDValue Op,const SelectionDAG & DAG,unsigned Depth) const2956*9880d681SAndroid Build Coastguard Worker unsigned AMDGPUTargetLowering::ComputeNumSignBitsForTargetNode(
2957*9880d681SAndroid Build Coastguard Worker SDValue Op,
2958*9880d681SAndroid Build Coastguard Worker const SelectionDAG &DAG,
2959*9880d681SAndroid Build Coastguard Worker unsigned Depth) const {
2960*9880d681SAndroid Build Coastguard Worker switch (Op.getOpcode()) {
2961*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BFE_I32: {
2962*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Width = dyn_cast<ConstantSDNode>(Op.getOperand(2));
2963*9880d681SAndroid Build Coastguard Worker if (!Width)
2964*9880d681SAndroid Build Coastguard Worker return 1;
2965*9880d681SAndroid Build Coastguard Worker
2966*9880d681SAndroid Build Coastguard Worker unsigned SignBits = 32 - Width->getZExtValue() + 1;
2967*9880d681SAndroid Build Coastguard Worker if (!isNullConstant(Op.getOperand(1)))
2968*9880d681SAndroid Build Coastguard Worker return SignBits;
2969*9880d681SAndroid Build Coastguard Worker
2970*9880d681SAndroid Build Coastguard Worker // TODO: Could probably figure something out with non-0 offsets.
2971*9880d681SAndroid Build Coastguard Worker unsigned Op0SignBits = DAG.ComputeNumSignBits(Op.getOperand(0), Depth + 1);
2972*9880d681SAndroid Build Coastguard Worker return std::max(SignBits, Op0SignBits);
2973*9880d681SAndroid Build Coastguard Worker }
2974*9880d681SAndroid Build Coastguard Worker
2975*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BFE_U32: {
2976*9880d681SAndroid Build Coastguard Worker ConstantSDNode *Width = dyn_cast<ConstantSDNode>(Op.getOperand(2));
2977*9880d681SAndroid Build Coastguard Worker return Width ? 32 - (Width->getZExtValue() & 0x1f) : 1;
2978*9880d681SAndroid Build Coastguard Worker }
2979*9880d681SAndroid Build Coastguard Worker
2980*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::CARRY:
2981*9880d681SAndroid Build Coastguard Worker case AMDGPUISD::BORROW:
2982*9880d681SAndroid Build Coastguard Worker return 31;
2983*9880d681SAndroid Build Coastguard Worker
2984*9880d681SAndroid Build Coastguard Worker default:
2985*9880d681SAndroid Build Coastguard Worker return 1;
2986*9880d681SAndroid Build Coastguard Worker }
2987*9880d681SAndroid Build Coastguard Worker }
2988