26d1a84e44cd99bee5a4c590f5ff69ff71f01c81
[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   SDValue DST;
171   if (OVT.getScalarType() == MVT::i64) {
172     DST = LowerSREM64(Op, DAG);
173   } else if (OVT.getScalarType() == MVT::i32) {
174     DST = LowerSREM32(Op, DAG);
175   } else if (OVT.getScalarType() == MVT::i16) {
176     DST = LowerSREM16(Op, DAG);
177   } else if (OVT.getScalarType() == MVT::i8) {
178     DST = LowerSREM8(Op, DAG);
179   } else {
180     DST = SDValue(Op.getNode(), 0);
181   }
182   return DST;
183 }
184
185 EVT
186 AMDGPUTargetLowering::genIntType(uint32_t size, uint32_t numEle) const {
187   int iSize = (size * numEle);
188   int vEle = (iSize >> ((size == 64) ? 6 : 5));
189   if (!vEle) {
190     vEle = 1;
191   }
192   if (size == 64) {
193     if (vEle == 1) {
194       return EVT(MVT::i64);
195     } else {
196       return EVT(MVT::getVectorVT(MVT::i64, vEle));
197     }
198   } else {
199     if (vEle == 1) {
200       return EVT(MVT::i32);
201     } else {
202       return EVT(MVT::getVectorVT(MVT::i32, vEle));
203     }
204   }
205 }
206
207 SDValue
208 AMDGPUTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
209   SDValue Chain = Op.getOperand(0);
210   SDValue Cond  = Op.getOperand(1);
211   SDValue Jump  = Op.getOperand(2);
212   SDValue Result;
213   Result = DAG.getNode(
214       AMDGPUISD::BRANCH_COND,
215       SDLoc(Op),
216       Op.getValueType(),
217       Chain, Jump, Cond);
218   return Result;
219 }
220
221 SDValue
222 AMDGPUTargetLowering::LowerSDIV24(SDValue Op, SelectionDAG &DAG) const {
223   SDLoc DL(Op);
224   EVT OVT = Op.getValueType();
225   SDValue LHS = Op.getOperand(0);
226   SDValue RHS = Op.getOperand(1);
227   MVT INTTY;
228   MVT FLTTY;
229   if (!OVT.isVector()) {
230     INTTY = MVT::i32;
231     FLTTY = MVT::f32;
232   } else if (OVT.getVectorNumElements() == 2) {
233     INTTY = MVT::v2i32;
234     FLTTY = MVT::v2f32;
235   } else if (OVT.getVectorNumElements() == 4) {
236     INTTY = MVT::v4i32;
237     FLTTY = MVT::v4f32;
238   }
239   unsigned bitsize = OVT.getScalarType().getSizeInBits();
240   // char|short jq = ia ^ ib;
241   SDValue jq = DAG.getNode(ISD::XOR, DL, OVT, LHS, RHS);
242
243   // jq = jq >> (bitsize - 2)
244   jq = DAG.getNode(ISD::SRA, DL, OVT, jq, DAG.getConstant(bitsize - 2, OVT)); 
245
246   // jq = jq | 0x1
247   jq = DAG.getNode(ISD::OR, DL, OVT, jq, DAG.getConstant(1, OVT));
248
249   // jq = (int)jq
250   jq = DAG.getSExtOrTrunc(jq, DL, INTTY);
251
252   // int ia = (int)LHS;
253   SDValue ia = DAG.getSExtOrTrunc(LHS, DL, INTTY);
254
255   // int ib, (int)RHS;
256   SDValue ib = DAG.getSExtOrTrunc(RHS, DL, INTTY);
257
258   // float fa = (float)ia;
259   SDValue fa = DAG.getNode(ISD::SINT_TO_FP, DL, FLTTY, ia);
260
261   // float fb = (float)ib;
262   SDValue fb = DAG.getNode(ISD::SINT_TO_FP, DL, FLTTY, ib);
263
264   // float fq = native_divide(fa, fb);
265   SDValue fq = DAG.getNode(AMDGPUISD::DIV_INF, DL, FLTTY, fa, fb);
266
267   // fq = trunc(fq);
268   fq = DAG.getNode(ISD::FTRUNC, DL, FLTTY, fq);
269
270   // float fqneg = -fq;
271   SDValue fqneg = DAG.getNode(ISD::FNEG, DL, FLTTY, fq);
272
273   // float fr = mad(fqneg, fb, fa);
274   SDValue fr = DAG.getNode(ISD::FADD, DL, FLTTY,
275       DAG.getNode(ISD::MUL, DL, FLTTY, fqneg, fb), fa);
276
277   // int iq = (int)fq;
278   SDValue iq = DAG.getNode(ISD::FP_TO_SINT, DL, INTTY, fq);
279
280   // fr = fabs(fr);
281   fr = DAG.getNode(ISD::FABS, DL, FLTTY, fr);
282
283   // fb = fabs(fb);
284   fb = DAG.getNode(ISD::FABS, DL, FLTTY, fb);
285
286   // int cv = fr >= fb;
287   SDValue cv;
288   if (INTTY == MVT::i32) {
289     cv = DAG.getSetCC(DL, INTTY, fr, fb, ISD::SETOGE);
290   } else {
291     cv = DAG.getSetCC(DL, INTTY, fr, fb, ISD::SETOGE);
292   }
293   // jq = (cv ? jq : 0);
294   jq = DAG.getNode(ISD::SELECT, DL, OVT, cv, jq, 
295       DAG.getConstant(0, OVT));
296   // dst = iq + jq;
297   iq = DAG.getSExtOrTrunc(iq, DL, OVT);
298   iq = DAG.getNode(ISD::ADD, DL, OVT, iq, jq);
299   return iq;
300 }
301
302 SDValue
303 AMDGPUTargetLowering::LowerSDIV32(SDValue Op, SelectionDAG &DAG) const {
304   SDLoc DL(Op);
305   EVT OVT = Op.getValueType();
306   SDValue LHS = Op.getOperand(0);
307   SDValue RHS = Op.getOperand(1);
308   // The LowerSDIV32 function generates equivalent to the following IL.
309   // mov r0, LHS
310   // mov r1, RHS
311   // ilt r10, r0, 0
312   // ilt r11, r1, 0
313   // iadd r0, r0, r10
314   // iadd r1, r1, r11
315   // ixor r0, r0, r10
316   // ixor r1, r1, r11
317   // udiv r0, r0, r1
318   // ixor r10, r10, r11
319   // iadd r0, r0, r10
320   // ixor DST, r0, r10
321
322   // mov r0, LHS
323   SDValue r0 = LHS;
324
325   // mov r1, RHS
326   SDValue r1 = RHS;
327
328   // ilt r10, r0, 0
329   SDValue r10 = DAG.getSelectCC(DL,
330       r0, DAG.getConstant(0, OVT),
331       DAG.getConstant(-1, MVT::i32),
332       DAG.getConstant(0, MVT::i32),
333       ISD::SETLT);
334
335   // ilt r11, r1, 0
336   SDValue r11 = DAG.getSelectCC(DL,
337       r1, DAG.getConstant(0, OVT),
338       DAG.getConstant(-1, MVT::i32),
339       DAG.getConstant(0, MVT::i32),
340       ISD::SETLT);
341
342   // iadd r0, r0, r10
343   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
344
345   // iadd r1, r1, r11
346   r1 = DAG.getNode(ISD::ADD, DL, OVT, r1, r11);
347
348   // ixor r0, r0, r10
349   r0 = DAG.getNode(ISD::XOR, DL, OVT, r0, r10);
350
351   // ixor r1, r1, r11
352   r1 = DAG.getNode(ISD::XOR, DL, OVT, r1, r11);
353
354   // udiv r0, r0, r1
355   r0 = DAG.getNode(ISD::UDIV, DL, OVT, r0, r1);
356
357   // ixor r10, r10, r11
358   r10 = DAG.getNode(ISD::XOR, DL, OVT, r10, r11);
359
360   // iadd r0, r0, r10
361   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
362
363   // ixor DST, r0, r10
364   SDValue DST = DAG.getNode(ISD::XOR, DL, OVT, r0, r10); 
365   return DST;
366 }
367
368 SDValue
369 AMDGPUTargetLowering::LowerSDIV64(SDValue Op, SelectionDAG &DAG) const {
370   return SDValue(Op.getNode(), 0);
371 }
372
373 SDValue
374 AMDGPUTargetLowering::LowerSREM8(SDValue Op, SelectionDAG &DAG) const {
375   SDLoc DL(Op);
376   EVT OVT = Op.getValueType();
377   MVT INTTY = MVT::i32;
378   if (OVT == MVT::v2i8) {
379     INTTY = MVT::v2i32;
380   } else if (OVT == MVT::v4i8) {
381     INTTY = MVT::v4i32;
382   }
383   SDValue LHS = DAG.getSExtOrTrunc(Op.getOperand(0), DL, INTTY);
384   SDValue RHS = DAG.getSExtOrTrunc(Op.getOperand(1), DL, INTTY);
385   LHS = DAG.getNode(ISD::SREM, DL, INTTY, LHS, RHS);
386   LHS = DAG.getSExtOrTrunc(LHS, DL, OVT);
387   return LHS;
388 }
389
390 SDValue
391 AMDGPUTargetLowering::LowerSREM16(SDValue Op, SelectionDAG &DAG) const {
392   SDLoc DL(Op);
393   EVT OVT = Op.getValueType();
394   MVT INTTY = MVT::i32;
395   if (OVT == MVT::v2i16) {
396     INTTY = MVT::v2i32;
397   } else if (OVT == MVT::v4i16) {
398     INTTY = MVT::v4i32;
399   }
400   SDValue LHS = DAG.getSExtOrTrunc(Op.getOperand(0), DL, INTTY);
401   SDValue RHS = DAG.getSExtOrTrunc(Op.getOperand(1), DL, INTTY);
402   LHS = DAG.getNode(ISD::SREM, DL, INTTY, LHS, RHS);
403   LHS = DAG.getSExtOrTrunc(LHS, DL, OVT);
404   return LHS;
405 }
406
407 SDValue
408 AMDGPUTargetLowering::LowerSREM32(SDValue Op, SelectionDAG &DAG) const {
409   SDLoc DL(Op);
410   EVT OVT = Op.getValueType();
411   SDValue LHS = Op.getOperand(0);
412   SDValue RHS = Op.getOperand(1);
413   // The LowerSREM32 function generates equivalent to the following IL.
414   // mov r0, LHS
415   // mov r1, RHS
416   // ilt r10, r0, 0
417   // ilt r11, r1, 0
418   // iadd r0, r0, r10
419   // iadd r1, r1, r11
420   // ixor r0, r0, r10
421   // ixor r1, r1, r11
422   // udiv r20, r0, r1
423   // umul r20, r20, r1
424   // sub r0, r0, r20
425   // iadd r0, r0, r10
426   // ixor DST, r0, r10
427
428   // mov r0, LHS
429   SDValue r0 = LHS;
430
431   // mov r1, RHS
432   SDValue r1 = RHS;
433
434   // ilt r10, r0, 0
435   SDValue r10 = DAG.getSetCC(DL, OVT, r0, DAG.getConstant(0, OVT), ISD::SETLT);
436
437   // ilt r11, r1, 0
438   SDValue r11 = DAG.getSetCC(DL, OVT, r1, DAG.getConstant(0, OVT), ISD::SETLT);
439
440   // iadd r0, r0, r10
441   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
442
443   // iadd r1, r1, r11
444   r1 = DAG.getNode(ISD::ADD, DL, OVT, r1, r11);
445
446   // ixor r0, r0, r10
447   r0 = DAG.getNode(ISD::XOR, DL, OVT, r0, r10);
448
449   // ixor r1, r1, r11
450   r1 = DAG.getNode(ISD::XOR, DL, OVT, r1, r11);
451
452   // udiv r20, r0, r1
453   SDValue r20 = DAG.getNode(ISD::UREM, DL, OVT, r0, r1);
454
455   // umul r20, r20, r1
456   r20 = DAG.getNode(AMDGPUISD::UMUL, DL, OVT, r20, r1);
457
458   // sub r0, r0, r20
459   r0 = DAG.getNode(ISD::SUB, DL, OVT, r0, r20);
460
461   // iadd r0, r0, r10
462   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
463
464   // ixor DST, r0, r10
465   SDValue DST = DAG.getNode(ISD::XOR, DL, OVT, r0, r10); 
466   return DST;
467 }
468
469 SDValue
470 AMDGPUTargetLowering::LowerSREM64(SDValue Op, SelectionDAG &DAG) const {
471   return SDValue(Op.getNode(), 0);
472 }