R600: Remove dead code
[oota-llvm.git] / lib / Target / R600 / AMDILISelLowering.cpp
1 //===-- AMDILISelLowering.cpp - AMDIL DAG Lowering Implementation ---------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //==-----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// \brief TargetLowering functions borrowed from AMDIL.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "AMDGPUISelLowering.h"
16 #include "AMDGPURegisterInfo.h"
17 #include "AMDGPUSubtarget.h"
18 #include "AMDILIntrinsicInfo.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/CodeGen/PseudoSourceValue.h"
22 #include "llvm/CodeGen/SelectionDAG.h"
23 #include "llvm/CodeGen/SelectionDAGNodes.h"
24 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
25 #include "llvm/IR/CallingConv.h"
26 #include "llvm/IR/DerivedTypes.h"
27 #include "llvm/IR/Instructions.h"
28 #include "llvm/IR/Intrinsics.h"
29 #include "llvm/Support/raw_ostream.h"
30 #include "llvm/Target/TargetInstrInfo.h"
31 #include "llvm/Target/TargetOptions.h"
32
33 using namespace llvm;
34 //===----------------------------------------------------------------------===//
35 // TargetLowering Implementation Help Functions End
36 //===----------------------------------------------------------------------===//
37
38 //===----------------------------------------------------------------------===//
39 // TargetLowering Class Implementation Begins
40 //===----------------------------------------------------------------------===//
41 void AMDGPUTargetLowering::InitAMDILLowering() {
42   static const MVT::SimpleValueType types[] = {
43     MVT::i32,
44     MVT::f32,
45     MVT::f64,
46     MVT::i64,
47     MVT::v4f32,
48     MVT::v4i32,
49     MVT::v2f32,
50     MVT::v2i32
51   };
52
53   static const MVT::SimpleValueType FloatTypes[] = {
54     MVT::f32,
55     MVT::f64
56   };
57
58   static const MVT::SimpleValueType VectorTypes[] = {
59     MVT::v4f32,
60     MVT::v4i32,
61     MVT::v2f32,
62     MVT::v2i32
63   };
64
65   const AMDGPUSubtarget &STM = getTargetMachine().getSubtarget<AMDGPUSubtarget>();
66
67   for (MVT VT : types) {
68     setOperationAction(ISD::SUBE, VT, Expand);
69     setOperationAction(ISD::SUBC, VT, Expand);
70     setOperationAction(ISD::ADDE, VT, Expand);
71     setOperationAction(ISD::ADDC, VT, Expand);
72     setOperationAction(ISD::BRCOND, VT, Custom);
73     setOperationAction(ISD::BR_JT, VT, Expand);
74     setOperationAction(ISD::BRIND, VT, Expand);
75     // TODO: Implement custom UREM/SREM routines
76     setOperationAction(ISD::SREM, VT, Expand);
77     setOperationAction(ISD::SMUL_LOHI, VT, Expand);
78     setOperationAction(ISD::UMUL_LOHI, VT, Expand);
79     if (VT != MVT::i64)
80       setOperationAction(ISD::SDIV, VT, Custom);
81   }
82
83   for (MVT VT : FloatTypes) {
84     setOperationAction(ISD::FP_ROUND_INREG, VT, Expand);
85   }
86
87   for (MVT VT : VectorTypes) {
88     setOperationAction(ISD::VECTOR_SHUFFLE, VT, Expand);
89     setOperationAction(ISD::SELECT_CC, VT, Expand);
90   }
91
92   setOperationAction(ISD::MULHU, MVT::i64, Expand);
93   setOperationAction(ISD::MULHS, MVT::i64, Expand);
94   if (STM.hasHWFP64()) {
95     setOperationAction(ISD::ConstantFP, MVT::f64, Legal);
96     setOperationAction(ISD::FABS, MVT::f64, Expand);
97   }
98
99   setOperationAction(ISD::SUBC, MVT::Other, Expand);
100   setOperationAction(ISD::ADDE, MVT::Other, Expand);
101   setOperationAction(ISD::ADDC, MVT::Other, Expand);
102   setOperationAction(ISD::BRCOND, MVT::Other, Custom);
103   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
104   setOperationAction(ISD::BRIND, MVT::Other, Expand);
105
106   setOperationAction(ISD::Constant, MVT::i32, Legal);
107   setOperationAction(ISD::Constant, MVT::i64, Legal);
108   setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
109
110   setPow2DivIsCheap(false);
111   setSelectIsExpensive(true); // FIXME: This makes no sense at all
112 }
113
114 bool
115 AMDGPUTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
116     const CallInst &I, unsigned Intrinsic) const {
117   return false;
118 }
119
120 // The backend supports 32 and 64 bit floating point immediates
121 bool
122 AMDGPUTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
123   if (VT.getScalarType().getSimpleVT().SimpleTy == MVT::f32
124       || VT.getScalarType().getSimpleVT().SimpleTy == MVT::f64) {
125     return true;
126   } else {
127     return false;
128   }
129 }
130
131 bool
132 AMDGPUTargetLowering::ShouldShrinkFPConstant(EVT VT) const {
133   if (VT.getScalarType().getSimpleVT().SimpleTy == MVT::f32
134       || VT.getScalarType().getSimpleVT().SimpleTy == MVT::f64) {
135     return false;
136   } else {
137     return true;
138   }
139 }
140
141
142 // isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
143 // be zero. Op is expected to be a target specific node. Used by DAG
144 // combiner.
145
146 //===----------------------------------------------------------------------===//
147 //                           Other Lowering Hooks
148 //===----------------------------------------------------------------------===//
149
150 SDValue
151 AMDGPUTargetLowering::LowerSDIV(SDValue Op, SelectionDAG &DAG) const {
152   EVT OVT = Op.getValueType();
153   SDValue DST;
154   if (OVT.getScalarType() == MVT::i64) {
155     DST = LowerSDIV64(Op, DAG);
156   } else if (OVT.getScalarType() == MVT::i32) {
157     DST = LowerSDIV32(Op, DAG);
158   } else if (OVT.getScalarType() == MVT::i16
159       || OVT.getScalarType() == MVT::i8) {
160     DST = LowerSDIV24(Op, DAG);
161   } else {
162     DST = SDValue(Op.getNode(), 0);
163   }
164   return DST;
165 }
166
167 SDValue
168 AMDGPUTargetLowering::LowerSREM(SDValue Op, SelectionDAG &DAG) const {
169   EVT OVT = Op.getValueType();
170
171   if (OVT.getScalarType() == MVT::i64)
172     return LowerSREM64(Op, DAG);
173
174   if (OVT.getScalarType() == MVT::i32)
175     return LowerSREM32(Op, DAG);
176
177   return SDValue(Op.getNode(), 0);
178 }
179
180 SDValue
181 AMDGPUTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
182   SDValue Chain = Op.getOperand(0);
183   SDValue Cond  = Op.getOperand(1);
184   SDValue Jump  = Op.getOperand(2);
185   SDValue Result;
186   Result = DAG.getNode(
187       AMDGPUISD::BRANCH_COND,
188       SDLoc(Op),
189       Op.getValueType(),
190       Chain, Jump, Cond);
191   return Result;
192 }
193
194 SDValue
195 AMDGPUTargetLowering::LowerSDIV24(SDValue Op, SelectionDAG &DAG) const {
196   SDLoc DL(Op);
197   EVT OVT = Op.getValueType();
198   SDValue LHS = Op.getOperand(0);
199   SDValue RHS = Op.getOperand(1);
200   MVT INTTY;
201   MVT FLTTY;
202   if (!OVT.isVector()) {
203     INTTY = MVT::i32;
204     FLTTY = MVT::f32;
205   } else if (OVT.getVectorNumElements() == 2) {
206     INTTY = MVT::v2i32;
207     FLTTY = MVT::v2f32;
208   } else if (OVT.getVectorNumElements() == 4) {
209     INTTY = MVT::v4i32;
210     FLTTY = MVT::v4f32;
211   }
212   unsigned bitsize = OVT.getScalarType().getSizeInBits();
213   // char|short jq = ia ^ ib;
214   SDValue jq = DAG.getNode(ISD::XOR, DL, OVT, LHS, RHS);
215
216   // jq = jq >> (bitsize - 2)
217   jq = DAG.getNode(ISD::SRA, DL, OVT, jq, DAG.getConstant(bitsize - 2, OVT));
218
219   // jq = jq | 0x1
220   jq = DAG.getNode(ISD::OR, DL, OVT, jq, DAG.getConstant(1, OVT));
221
222   // jq = (int)jq
223   jq = DAG.getSExtOrTrunc(jq, DL, INTTY);
224
225   // int ia = (int)LHS;
226   SDValue ia = DAG.getSExtOrTrunc(LHS, DL, INTTY);
227
228   // int ib, (int)RHS;
229   SDValue ib = DAG.getSExtOrTrunc(RHS, DL, INTTY);
230
231   // float fa = (float)ia;
232   SDValue fa = DAG.getNode(ISD::SINT_TO_FP, DL, FLTTY, ia);
233
234   // float fb = (float)ib;
235   SDValue fb = DAG.getNode(ISD::SINT_TO_FP, DL, FLTTY, ib);
236
237   // float fq = native_divide(fa, fb);
238   SDValue fq = DAG.getNode(AMDGPUISD::DIV_INF, DL, FLTTY, fa, fb);
239
240   // fq = trunc(fq);
241   fq = DAG.getNode(ISD::FTRUNC, DL, FLTTY, fq);
242
243   // float fqneg = -fq;
244   SDValue fqneg = DAG.getNode(ISD::FNEG, DL, FLTTY, fq);
245
246   // float fr = mad(fqneg, fb, fa);
247   SDValue fr = DAG.getNode(ISD::FADD, DL, FLTTY,
248       DAG.getNode(ISD::MUL, DL, FLTTY, fqneg, fb), fa);
249
250   // int iq = (int)fq;
251   SDValue iq = DAG.getNode(ISD::FP_TO_SINT, DL, INTTY, fq);
252
253   // fr = fabs(fr);
254   fr = DAG.getNode(ISD::FABS, DL, FLTTY, fr);
255
256   // fb = fabs(fb);
257   fb = DAG.getNode(ISD::FABS, DL, FLTTY, fb);
258
259   // int cv = fr >= fb;
260   SDValue cv;
261   if (INTTY == MVT::i32) {
262     cv = DAG.getSetCC(DL, INTTY, fr, fb, ISD::SETOGE);
263   } else {
264     cv = DAG.getSetCC(DL, INTTY, fr, fb, ISD::SETOGE);
265   }
266   // jq = (cv ? jq : 0);
267   jq = DAG.getNode(ISD::SELECT, DL, OVT, cv, jq,
268       DAG.getConstant(0, OVT));
269   // dst = iq + jq;
270   iq = DAG.getSExtOrTrunc(iq, DL, OVT);
271   iq = DAG.getNode(ISD::ADD, DL, OVT, iq, jq);
272   return iq;
273 }
274
275 SDValue
276 AMDGPUTargetLowering::LowerSDIV32(SDValue Op, SelectionDAG &DAG) const {
277   SDLoc DL(Op);
278   EVT OVT = Op.getValueType();
279   SDValue LHS = Op.getOperand(0);
280   SDValue RHS = Op.getOperand(1);
281   // The LowerSDIV32 function generates equivalent to the following IL.
282   // mov r0, LHS
283   // mov r1, RHS
284   // ilt r10, r0, 0
285   // ilt r11, r1, 0
286   // iadd r0, r0, r10
287   // iadd r1, r1, r11
288   // ixor r0, r0, r10
289   // ixor r1, r1, r11
290   // udiv r0, r0, r1
291   // ixor r10, r10, r11
292   // iadd r0, r0, r10
293   // ixor DST, r0, r10
294
295   // mov r0, LHS
296   SDValue r0 = LHS;
297
298   // mov r1, RHS
299   SDValue r1 = RHS;
300
301   // ilt r10, r0, 0
302   SDValue r10 = DAG.getSelectCC(DL,
303       r0, DAG.getConstant(0, OVT),
304       DAG.getConstant(-1, MVT::i32),
305       DAG.getConstant(0, MVT::i32),
306       ISD::SETLT);
307
308   // ilt r11, r1, 0
309   SDValue r11 = DAG.getSelectCC(DL,
310       r1, DAG.getConstant(0, OVT),
311       DAG.getConstant(-1, MVT::i32),
312       DAG.getConstant(0, MVT::i32),
313       ISD::SETLT);
314
315   // iadd r0, r0, r10
316   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
317
318   // iadd r1, r1, r11
319   r1 = DAG.getNode(ISD::ADD, DL, OVT, r1, r11);
320
321   // ixor r0, r0, r10
322   r0 = DAG.getNode(ISD::XOR, DL, OVT, r0, r10);
323
324   // ixor r1, r1, r11
325   r1 = DAG.getNode(ISD::XOR, DL, OVT, r1, r11);
326
327   // udiv r0, r0, r1
328   r0 = DAG.getNode(ISD::UDIV, DL, OVT, r0, r1);
329
330   // ixor r10, r10, r11
331   r10 = DAG.getNode(ISD::XOR, DL, OVT, r10, r11);
332
333   // iadd r0, r0, r10
334   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
335
336   // ixor DST, r0, r10
337   SDValue DST = DAG.getNode(ISD::XOR, DL, OVT, r0, r10);
338   return DST;
339 }
340
341 SDValue
342 AMDGPUTargetLowering::LowerSDIV64(SDValue Op, SelectionDAG &DAG) const {
343   return SDValue(Op.getNode(), 0);
344 }
345
346 SDValue
347 AMDGPUTargetLowering::LowerSREM32(SDValue Op, SelectionDAG &DAG) const {
348   SDLoc DL(Op);
349   EVT OVT = Op.getValueType();
350   SDValue LHS = Op.getOperand(0);
351   SDValue RHS = Op.getOperand(1);
352   // The LowerSREM32 function generates equivalent to the following IL.
353   // mov r0, LHS
354   // mov r1, RHS
355   // ilt r10, r0, 0
356   // ilt r11, r1, 0
357   // iadd r0, r0, r10
358   // iadd r1, r1, r11
359   // ixor r0, r0, r10
360   // ixor r1, r1, r11
361   // udiv r20, r0, r1
362   // umul r20, r20, r1
363   // sub r0, r0, r20
364   // iadd r0, r0, r10
365   // ixor DST, r0, r10
366
367   // mov r0, LHS
368   SDValue r0 = LHS;
369
370   // mov r1, RHS
371   SDValue r1 = RHS;
372
373   // ilt r10, r0, 0
374   SDValue r10 = DAG.getSetCC(DL, OVT, r0, DAG.getConstant(0, OVT), ISD::SETLT);
375
376   // ilt r11, r1, 0
377   SDValue r11 = DAG.getSetCC(DL, OVT, r1, DAG.getConstant(0, OVT), ISD::SETLT);
378
379   // iadd r0, r0, r10
380   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
381
382   // iadd r1, r1, r11
383   r1 = DAG.getNode(ISD::ADD, DL, OVT, r1, r11);
384
385   // ixor r0, r0, r10
386   r0 = DAG.getNode(ISD::XOR, DL, OVT, r0, r10);
387
388   // ixor r1, r1, r11
389   r1 = DAG.getNode(ISD::XOR, DL, OVT, r1, r11);
390
391   // udiv r20, r0, r1
392   SDValue r20 = DAG.getNode(ISD::UREM, DL, OVT, r0, r1);
393
394   // umul r20, r20, r1
395   r20 = DAG.getNode(AMDGPUISD::UMUL, DL, OVT, r20, r1);
396
397   // sub r0, r0, r20
398   r0 = DAG.getNode(ISD::SUB, DL, OVT, r0, r20);
399
400   // iadd r0, r0, r10
401   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
402
403   // ixor DST, r0, r10
404   SDValue DST = DAG.getNode(ISD::XOR, DL, OVT, r0, r10);
405   return DST;
406 }
407
408 SDValue
409 AMDGPUTargetLowering::LowerSREM64(SDValue Op, SelectionDAG &DAG) const {
410   return SDValue(Op.getNode(), 0);
411 }