6001899ac8dd77cf284560ea2c5eca4aaa668f79
[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::i8,
44     MVT::i16,
45     MVT::i32,
46     MVT::f32,
47     MVT::f64,
48     MVT::i64,
49     MVT::v2i8,
50     MVT::v4i8,
51     MVT::v2i16,
52     MVT::v4i16,
53     MVT::v4f32,
54     MVT::v4i32,
55     MVT::v2f32,
56     MVT::v2i32,
57     MVT::v2f64,
58     MVT::v2i64
59   };
60
61   static const MVT::SimpleValueType IntTypes[] = {
62     MVT::i8,
63     MVT::i16,
64     MVT::i32,
65     MVT::i64
66   };
67
68   static const MVT::SimpleValueType FloatTypes[] = {
69     MVT::f32,
70     MVT::f64
71   };
72
73   static const MVT::SimpleValueType VectorTypes[] = {
74     MVT::v2i8,
75     MVT::v4i8,
76     MVT::v2i16,
77     MVT::v4i16,
78     MVT::v4f32,
79     MVT::v4i32,
80     MVT::v2f32,
81     MVT::v2i32,
82     MVT::v2f64,
83     MVT::v2i64
84   };
85
86   const AMDGPUSubtarget &STM = getTargetMachine().getSubtarget<AMDGPUSubtarget>();
87   // These are the current register classes that are
88   // supported
89
90   for (MVT VT : types) {
91     setOperationAction(ISD::SUBE, VT, Expand);
92     setOperationAction(ISD::SUBC, VT, Expand);
93     setOperationAction(ISD::ADDE, VT, Expand);
94     setOperationAction(ISD::ADDC, VT, Expand);
95     setOperationAction(ISD::BRCOND, VT, Custom);
96     setOperationAction(ISD::BR_JT, VT, Expand);
97     setOperationAction(ISD::BRIND, VT, Expand);
98     // TODO: Implement custom UREM/SREM routines
99     setOperationAction(ISD::SREM, VT, Expand);
100     setOperationAction(ISD::SMUL_LOHI, VT, Expand);
101     setOperationAction(ISD::UMUL_LOHI, VT, Expand);
102     if (VT != MVT::i64 && VT != MVT::v2i64) {
103       setOperationAction(ISD::SDIV, VT, Custom);
104     }
105   }
106   for (MVT VT : FloatTypes) {
107     // IL does not have these operations for floating point types
108     setOperationAction(ISD::FP_ROUND_INREG, VT, Expand);
109     setOperationAction(ISD::SETOLT, VT, Expand);
110     setOperationAction(ISD::SETOGE, VT, Expand);
111     setOperationAction(ISD::SETOGT, VT, Expand);
112     setOperationAction(ISD::SETOLE, VT, Expand);
113     setOperationAction(ISD::SETULT, VT, Expand);
114     setOperationAction(ISD::SETUGE, VT, Expand);
115     setOperationAction(ISD::SETUGT, VT, Expand);
116     setOperationAction(ISD::SETULE, VT, Expand);
117   }
118
119   for (MVT VT : IntTypes) {
120     // GPU also does not have divrem function for signed or unsigned
121     setOperationAction(ISD::SDIVREM, VT, Expand);
122
123     // GPU does not have [S|U]MUL_LOHI functions as a single instruction
124     setOperationAction(ISD::SMUL_LOHI, VT, Expand);
125     setOperationAction(ISD::UMUL_LOHI, VT, Expand);
126
127     setOperationAction(ISD::BSWAP, VT, Expand);
128   }
129
130   for (MVT VT : VectorTypes) {
131     setOperationAction(ISD::VECTOR_SHUFFLE, VT, Expand);
132     setOperationAction(ISD::SDIVREM, VT, Expand);
133     setOperationAction(ISD::SMUL_LOHI, VT, Expand);
134     // setOperationAction(ISD::VSETCC, VT, Expand);
135     setOperationAction(ISD::SELECT_CC, VT, Expand);
136
137   }
138   setOperationAction(ISD::MULHU, MVT::i64, Expand);
139   setOperationAction(ISD::MULHU, MVT::v2i64, Expand);
140   setOperationAction(ISD::MULHS, MVT::i64, Expand);
141   setOperationAction(ISD::MULHS, MVT::v2i64, Expand);
142   setOperationAction(ISD::ADD, MVT::v2i64, Expand);
143   setOperationAction(ISD::SREM, MVT::v2i64, Expand);
144   setOperationAction(ISD::Constant          , MVT::i64  , Legal);
145   setOperationAction(ISD::SDIV, MVT::v2i64, Expand);
146   setOperationAction(ISD::TRUNCATE, MVT::v2i64, Expand);
147   setOperationAction(ISD::SIGN_EXTEND, MVT::v2i64, Expand);
148   setOperationAction(ISD::ZERO_EXTEND, MVT::v2i64, Expand);
149   setOperationAction(ISD::ANY_EXTEND, MVT::v2i64, Expand);
150   if (STM.hasHWFP64()) {
151     // we support loading/storing v2f64 but not operations on the type
152     setOperationAction(ISD::FADD, MVT::v2f64, Expand);
153     setOperationAction(ISD::FSUB, MVT::v2f64, Expand);
154     setOperationAction(ISD::FMUL, MVT::v2f64, Expand);
155     setOperationAction(ISD::FP_ROUND_INREG, MVT::v2f64, Expand);
156     setOperationAction(ISD::FP_EXTEND, MVT::v2f64, Expand);
157     setOperationAction(ISD::ConstantFP        , MVT::f64  , Legal);
158     // We want to expand vector conversions into their scalar
159     // counterparts.
160     setOperationAction(ISD::TRUNCATE, MVT::v2f64, Expand);
161     setOperationAction(ISD::SIGN_EXTEND, MVT::v2f64, Expand);
162     setOperationAction(ISD::ZERO_EXTEND, MVT::v2f64, Expand);
163     setOperationAction(ISD::ANY_EXTEND, MVT::v2f64, Expand);
164     setOperationAction(ISD::FABS, MVT::f64, Expand);
165     setOperationAction(ISD::FABS, MVT::v2f64, Expand);
166   }
167   // TODO: Fix the UDIV24 algorithm so it works for these
168   // types correctly. This needs vector comparisons
169   // for this to work correctly.
170   setOperationAction(ISD::UDIV, MVT::v2i8, Expand);
171   setOperationAction(ISD::UDIV, MVT::v4i8, Expand);
172   setOperationAction(ISD::UDIV, MVT::v2i16, Expand);
173   setOperationAction(ISD::UDIV, MVT::v4i16, Expand);
174   setOperationAction(ISD::SUBC, MVT::Other, Expand);
175   setOperationAction(ISD::ADDE, MVT::Other, Expand);
176   setOperationAction(ISD::ADDC, MVT::Other, Expand);
177   setOperationAction(ISD::BRCOND, MVT::Other, Custom);
178   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
179   setOperationAction(ISD::BRIND, MVT::Other, Expand);
180
181
182   // Use the default implementation.
183   setOperationAction(ISD::ConstantFP        , MVT::f32    , Legal);
184   setOperationAction(ISD::Constant          , MVT::i32    , Legal);
185
186   setSchedulingPreference(Sched::RegPressure);
187   setPow2DivIsCheap(false);
188   setSelectIsExpensive(true);
189   setJumpIsExpensive(true);
190
191   MaxStoresPerMemcpy  = 4096;
192   MaxStoresPerMemmove = 4096;
193   MaxStoresPerMemset  = 4096;
194
195 }
196
197 bool
198 AMDGPUTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
199     const CallInst &I, unsigned Intrinsic) const {
200   return false;
201 }
202
203 // The backend supports 32 and 64 bit floating point immediates
204 bool
205 AMDGPUTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
206   if (VT.getScalarType().getSimpleVT().SimpleTy == MVT::f32
207       || VT.getScalarType().getSimpleVT().SimpleTy == MVT::f64) {
208     return true;
209   } else {
210     return false;
211   }
212 }
213
214 bool
215 AMDGPUTargetLowering::ShouldShrinkFPConstant(EVT VT) const {
216   if (VT.getScalarType().getSimpleVT().SimpleTy == MVT::f32
217       || VT.getScalarType().getSimpleVT().SimpleTy == MVT::f64) {
218     return false;
219   } else {
220     return true;
221   }
222 }
223
224
225 // isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
226 // be zero. Op is expected to be a target specific node. Used by DAG
227 // combiner.
228
229 //===----------------------------------------------------------------------===//
230 //                           Other Lowering Hooks
231 //===----------------------------------------------------------------------===//
232
233 SDValue
234 AMDGPUTargetLowering::LowerSDIV(SDValue Op, SelectionDAG &DAG) const {
235   EVT OVT = Op.getValueType();
236   SDValue DST;
237   if (OVT.getScalarType() == MVT::i64) {
238     DST = LowerSDIV64(Op, DAG);
239   } else if (OVT.getScalarType() == MVT::i32) {
240     DST = LowerSDIV32(Op, DAG);
241   } else if (OVT.getScalarType() == MVT::i16
242       || OVT.getScalarType() == MVT::i8) {
243     DST = LowerSDIV24(Op, DAG);
244   } else {
245     DST = SDValue(Op.getNode(), 0);
246   }
247   return DST;
248 }
249
250 SDValue
251 AMDGPUTargetLowering::LowerSREM(SDValue Op, SelectionDAG &DAG) const {
252   EVT OVT = Op.getValueType();
253   SDValue DST;
254   if (OVT.getScalarType() == MVT::i64) {
255     DST = LowerSREM64(Op, DAG);
256   } else if (OVT.getScalarType() == MVT::i32) {
257     DST = LowerSREM32(Op, DAG);
258   } else if (OVT.getScalarType() == MVT::i16) {
259     DST = LowerSREM16(Op, DAG);
260   } else if (OVT.getScalarType() == MVT::i8) {
261     DST = LowerSREM8(Op, DAG);
262   } else {
263     DST = SDValue(Op.getNode(), 0);
264   }
265   return DST;
266 }
267
268 EVT
269 AMDGPUTargetLowering::genIntType(uint32_t size, uint32_t numEle) const {
270   int iSize = (size * numEle);
271   int vEle = (iSize >> ((size == 64) ? 6 : 5));
272   if (!vEle) {
273     vEle = 1;
274   }
275   if (size == 64) {
276     if (vEle == 1) {
277       return EVT(MVT::i64);
278     } else {
279       return EVT(MVT::getVectorVT(MVT::i64, vEle));
280     }
281   } else {
282     if (vEle == 1) {
283       return EVT(MVT::i32);
284     } else {
285       return EVT(MVT::getVectorVT(MVT::i32, vEle));
286     }
287   }
288 }
289
290 SDValue
291 AMDGPUTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const {
292   SDValue Chain = Op.getOperand(0);
293   SDValue Cond  = Op.getOperand(1);
294   SDValue Jump  = Op.getOperand(2);
295   SDValue Result;
296   Result = DAG.getNode(
297       AMDGPUISD::BRANCH_COND,
298       SDLoc(Op),
299       Op.getValueType(),
300       Chain, Jump, Cond);
301   return Result;
302 }
303
304 SDValue
305 AMDGPUTargetLowering::LowerSDIV24(SDValue Op, SelectionDAG &DAG) const {
306   SDLoc DL(Op);
307   EVT OVT = Op.getValueType();
308   SDValue LHS = Op.getOperand(0);
309   SDValue RHS = Op.getOperand(1);
310   MVT INTTY;
311   MVT FLTTY;
312   if (!OVT.isVector()) {
313     INTTY = MVT::i32;
314     FLTTY = MVT::f32;
315   } else if (OVT.getVectorNumElements() == 2) {
316     INTTY = MVT::v2i32;
317     FLTTY = MVT::v2f32;
318   } else if (OVT.getVectorNumElements() == 4) {
319     INTTY = MVT::v4i32;
320     FLTTY = MVT::v4f32;
321   }
322   unsigned bitsize = OVT.getScalarType().getSizeInBits();
323   // char|short jq = ia ^ ib;
324   SDValue jq = DAG.getNode(ISD::XOR, DL, OVT, LHS, RHS);
325
326   // jq = jq >> (bitsize - 2)
327   jq = DAG.getNode(ISD::SRA, DL, OVT, jq, DAG.getConstant(bitsize - 2, OVT)); 
328
329   // jq = jq | 0x1
330   jq = DAG.getNode(ISD::OR, DL, OVT, jq, DAG.getConstant(1, OVT));
331
332   // jq = (int)jq
333   jq = DAG.getSExtOrTrunc(jq, DL, INTTY);
334
335   // int ia = (int)LHS;
336   SDValue ia = DAG.getSExtOrTrunc(LHS, DL, INTTY);
337
338   // int ib, (int)RHS;
339   SDValue ib = DAG.getSExtOrTrunc(RHS, DL, INTTY);
340
341   // float fa = (float)ia;
342   SDValue fa = DAG.getNode(ISD::SINT_TO_FP, DL, FLTTY, ia);
343
344   // float fb = (float)ib;
345   SDValue fb = DAG.getNode(ISD::SINT_TO_FP, DL, FLTTY, ib);
346
347   // float fq = native_divide(fa, fb);
348   SDValue fq = DAG.getNode(AMDGPUISD::DIV_INF, DL, FLTTY, fa, fb);
349
350   // fq = trunc(fq);
351   fq = DAG.getNode(ISD::FTRUNC, DL, FLTTY, fq);
352
353   // float fqneg = -fq;
354   SDValue fqneg = DAG.getNode(ISD::FNEG, DL, FLTTY, fq);
355
356   // float fr = mad(fqneg, fb, fa);
357   SDValue fr = DAG.getNode(ISD::FADD, DL, FLTTY,
358       DAG.getNode(ISD::MUL, DL, FLTTY, fqneg, fb), fa);
359
360   // int iq = (int)fq;
361   SDValue iq = DAG.getNode(ISD::FP_TO_SINT, DL, INTTY, fq);
362
363   // fr = fabs(fr);
364   fr = DAG.getNode(ISD::FABS, DL, FLTTY, fr);
365
366   // fb = fabs(fb);
367   fb = DAG.getNode(ISD::FABS, DL, FLTTY, fb);
368
369   // int cv = fr >= fb;
370   SDValue cv;
371   if (INTTY == MVT::i32) {
372     cv = DAG.getSetCC(DL, INTTY, fr, fb, ISD::SETOGE);
373   } else {
374     cv = DAG.getSetCC(DL, INTTY, fr, fb, ISD::SETOGE);
375   }
376   // jq = (cv ? jq : 0);
377   jq = DAG.getNode(ISD::SELECT, DL, OVT, cv, jq, 
378       DAG.getConstant(0, OVT));
379   // dst = iq + jq;
380   iq = DAG.getSExtOrTrunc(iq, DL, OVT);
381   iq = DAG.getNode(ISD::ADD, DL, OVT, iq, jq);
382   return iq;
383 }
384
385 SDValue
386 AMDGPUTargetLowering::LowerSDIV32(SDValue Op, SelectionDAG &DAG) const {
387   SDLoc DL(Op);
388   EVT OVT = Op.getValueType();
389   SDValue LHS = Op.getOperand(0);
390   SDValue RHS = Op.getOperand(1);
391   // The LowerSDIV32 function generates equivalent to the following IL.
392   // mov r0, LHS
393   // mov r1, RHS
394   // ilt r10, r0, 0
395   // ilt r11, r1, 0
396   // iadd r0, r0, r10
397   // iadd r1, r1, r11
398   // ixor r0, r0, r10
399   // ixor r1, r1, r11
400   // udiv r0, r0, r1
401   // ixor r10, r10, r11
402   // iadd r0, r0, r10
403   // ixor DST, r0, r10
404
405   // mov r0, LHS
406   SDValue r0 = LHS;
407
408   // mov r1, RHS
409   SDValue r1 = RHS;
410
411   // ilt r10, r0, 0
412   SDValue r10 = DAG.getSelectCC(DL,
413       r0, DAG.getConstant(0, OVT),
414       DAG.getConstant(-1, MVT::i32),
415       DAG.getConstant(0, MVT::i32),
416       ISD::SETLT);
417
418   // ilt r11, r1, 0
419   SDValue r11 = DAG.getSelectCC(DL,
420       r1, DAG.getConstant(0, OVT),
421       DAG.getConstant(-1, MVT::i32),
422       DAG.getConstant(0, MVT::i32),
423       ISD::SETLT);
424
425   // iadd r0, r0, r10
426   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
427
428   // iadd r1, r1, r11
429   r1 = DAG.getNode(ISD::ADD, DL, OVT, r1, r11);
430
431   // ixor r0, r0, r10
432   r0 = DAG.getNode(ISD::XOR, DL, OVT, r0, r10);
433
434   // ixor r1, r1, r11
435   r1 = DAG.getNode(ISD::XOR, DL, OVT, r1, r11);
436
437   // udiv r0, r0, r1
438   r0 = DAG.getNode(ISD::UDIV, DL, OVT, r0, r1);
439
440   // ixor r10, r10, r11
441   r10 = DAG.getNode(ISD::XOR, DL, OVT, r10, r11);
442
443   // iadd r0, r0, r10
444   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
445
446   // ixor DST, r0, r10
447   SDValue DST = DAG.getNode(ISD::XOR, DL, OVT, r0, r10); 
448   return DST;
449 }
450
451 SDValue
452 AMDGPUTargetLowering::LowerSDIV64(SDValue Op, SelectionDAG &DAG) const {
453   return SDValue(Op.getNode(), 0);
454 }
455
456 SDValue
457 AMDGPUTargetLowering::LowerSREM8(SDValue Op, SelectionDAG &DAG) const {
458   SDLoc DL(Op);
459   EVT OVT = Op.getValueType();
460   MVT INTTY = MVT::i32;
461   if (OVT == MVT::v2i8) {
462     INTTY = MVT::v2i32;
463   } else if (OVT == MVT::v4i8) {
464     INTTY = MVT::v4i32;
465   }
466   SDValue LHS = DAG.getSExtOrTrunc(Op.getOperand(0), DL, INTTY);
467   SDValue RHS = DAG.getSExtOrTrunc(Op.getOperand(1), DL, INTTY);
468   LHS = DAG.getNode(ISD::SREM, DL, INTTY, LHS, RHS);
469   LHS = DAG.getSExtOrTrunc(LHS, DL, OVT);
470   return LHS;
471 }
472
473 SDValue
474 AMDGPUTargetLowering::LowerSREM16(SDValue Op, SelectionDAG &DAG) const {
475   SDLoc DL(Op);
476   EVT OVT = Op.getValueType();
477   MVT INTTY = MVT::i32;
478   if (OVT == MVT::v2i16) {
479     INTTY = MVT::v2i32;
480   } else if (OVT == MVT::v4i16) {
481     INTTY = MVT::v4i32;
482   }
483   SDValue LHS = DAG.getSExtOrTrunc(Op.getOperand(0), DL, INTTY);
484   SDValue RHS = DAG.getSExtOrTrunc(Op.getOperand(1), DL, INTTY);
485   LHS = DAG.getNode(ISD::SREM, DL, INTTY, LHS, RHS);
486   LHS = DAG.getSExtOrTrunc(LHS, DL, OVT);
487   return LHS;
488 }
489
490 SDValue
491 AMDGPUTargetLowering::LowerSREM32(SDValue Op, SelectionDAG &DAG) const {
492   SDLoc DL(Op);
493   EVT OVT = Op.getValueType();
494   SDValue LHS = Op.getOperand(0);
495   SDValue RHS = Op.getOperand(1);
496   // The LowerSREM32 function generates equivalent to the following IL.
497   // mov r0, LHS
498   // mov r1, RHS
499   // ilt r10, r0, 0
500   // ilt r11, r1, 0
501   // iadd r0, r0, r10
502   // iadd r1, r1, r11
503   // ixor r0, r0, r10
504   // ixor r1, r1, r11
505   // udiv r20, r0, r1
506   // umul r20, r20, r1
507   // sub r0, r0, r20
508   // iadd r0, r0, r10
509   // ixor DST, r0, r10
510
511   // mov r0, LHS
512   SDValue r0 = LHS;
513
514   // mov r1, RHS
515   SDValue r1 = RHS;
516
517   // ilt r10, r0, 0
518   SDValue r10 = DAG.getSetCC(DL, OVT, r0, DAG.getConstant(0, OVT), ISD::SETLT);
519
520   // ilt r11, r1, 0
521   SDValue r11 = DAG.getSetCC(DL, OVT, r1, DAG.getConstant(0, OVT), ISD::SETLT);
522
523   // iadd r0, r0, r10
524   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
525
526   // iadd r1, r1, r11
527   r1 = DAG.getNode(ISD::ADD, DL, OVT, r1, r11);
528
529   // ixor r0, r0, r10
530   r0 = DAG.getNode(ISD::XOR, DL, OVT, r0, r10);
531
532   // ixor r1, r1, r11
533   r1 = DAG.getNode(ISD::XOR, DL, OVT, r1, r11);
534
535   // udiv r20, r0, r1
536   SDValue r20 = DAG.getNode(ISD::UREM, DL, OVT, r0, r1);
537
538   // umul r20, r20, r1
539   r20 = DAG.getNode(AMDGPUISD::UMUL, DL, OVT, r20, r1);
540
541   // sub r0, r0, r20
542   r0 = DAG.getNode(ISD::SUB, DL, OVT, r0, r20);
543
544   // iadd r0, r0, r10
545   r0 = DAG.getNode(ISD::ADD, DL, OVT, r0, r10);
546
547   // ixor DST, r0, r10
548   SDValue DST = DAG.getNode(ISD::XOR, DL, OVT, r0, r10); 
549   return DST;
550 }
551
552 SDValue
553 AMDGPUTargetLowering::LowerSREM64(SDValue Op, SelectionDAG &DAG) const {
554   return SDValue(Op.getNode(), 0);
555 }