AMDGPUISelLowering.cpp revision 7e3cd8df183448e2cc01a8f2645a001b0972f4ab
1//===-- AMDGPUISelLowering.cpp - AMDGPU Common DAG lowering functions -----===//
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// This is the parent TargetLowering class for hardware code gen targets.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPUISelLowering.h"
15#include "AMDILIntrinsicInfo.h"
16#include "AMDGPUUtil.h"
17#include "llvm/CodeGen/MachineRegisterInfo.h"
18
19using namespace llvm;
20
21AMDGPUTargetLowering::AMDGPUTargetLowering(TargetMachine &TM) :
22  AMDILTargetLowering(TM)
23{
24  // We need to custom lower some of the intrinsics
25  setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
26}
27
28SDValue AMDGPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
29    const
30{
31  switch (Op.getOpcode()) {
32  default: return AMDILTargetLowering::LowerOperation(Op, DAG);
33  case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
34  }
35}
36
37SDValue AMDGPUTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
38    SelectionDAG &DAG) const
39{
40  unsigned IntrinsicID = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
41  DebugLoc DL = Op.getDebugLoc();
42  EVT VT = Op.getValueType();
43
44  switch (IntrinsicID) {
45    default: return Op;
46    case AMDGPUIntrinsic::AMDIL_abs:
47      return LowerIntrinsicIABS(Op, DAG);
48    case AMDGPUIntrinsic::AMDGPU_lrp:
49      return LowerIntrinsicLRP(Op, DAG);
50    case AMDGPUIntrinsic::AMDIL_mad:
51      return DAG.getNode(AMDILISD::MAD, DL, VT, Op.getOperand(1),
52                              Op.getOperand(2), Op.getOperand(3));
53    case AMDGPUIntrinsic::AMDIL_max:
54      return DAG.getNode(AMDGPUISD::FMAX, DL, VT, Op.getOperand(1),
55                                                  Op.getOperand(2));
56    case AMDGPUIntrinsic::AMDGPU_imax:
57      return DAG.getNode(AMDGPUISD::SMAX, DL, VT, Op.getOperand(1),
58                                                  Op.getOperand(2));
59    case AMDGPUIntrinsic::AMDGPU_umax:
60      return DAG.getNode(AMDGPUISD::UMAX, DL, VT, Op.getOperand(1),
61                                                  Op.getOperand(2));
62    case AMDGPUIntrinsic::AMDIL_min:
63      return DAG.getNode(AMDGPUISD::FMIN, DL, VT, Op.getOperand(1),
64                                                  Op.getOperand(2));
65    case AMDGPUIntrinsic::AMDGPU_imin:
66      return DAG.getNode(AMDGPUISD::SMIN, DL, VT, Op.getOperand(1),
67                                                  Op.getOperand(2));
68    case AMDGPUIntrinsic::AMDGPU_umin:
69      return DAG.getNode(AMDGPUISD::UMIN, DL, VT, Op.getOperand(1),
70                                                  Op.getOperand(2));
71  }
72}
73
74///IABS(a) = SMAX(sub(0, a), a)
75SDValue AMDGPUTargetLowering::LowerIntrinsicIABS(SDValue Op,
76    SelectionDAG &DAG) const
77{
78
79  DebugLoc DL = Op.getDebugLoc();
80  EVT VT = Op.getValueType();
81  SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, VT),
82                                              Op.getOperand(1));
83
84  return DAG.getNode(AMDGPUISD::SMAX, DL, VT, Neg, Op.getOperand(1));
85}
86
87/// Linear Interpolation
88/// LRP(a, b, c) = muladd(a,  b, (1 - a) * c)
89SDValue AMDGPUTargetLowering::LowerIntrinsicLRP(SDValue Op,
90    SelectionDAG &DAG) const
91{
92  DebugLoc DL = Op.getDebugLoc();
93  EVT VT = Op.getValueType();
94  SDValue OneSubA = DAG.getNode(ISD::FSUB, DL, VT, DAG.getConstant(1, VT),
95                                                   Op.getOperand(1));
96  SDValue OneSubAC = DAG.getNode(ISD::FMUL, DL, VT, OneSubA,
97                                                    Op.getOperand(3));
98  return DAG.getNode(AMDILISD::MAD, DL, VT, Op.getOperand(1),
99                                               Op.getOperand(2),
100                                               OneSubAC);
101}
102
103void AMDGPUTargetLowering::addLiveIn(MachineInstr * MI,
104    MachineFunction * MF, MachineRegisterInfo & MRI,
105    const TargetInstrInfo * TII, unsigned reg) const
106{
107  AMDGPU::utilAddLiveIn(MF, MRI, TII, reg, MI->getOperand(0).getReg());
108}
109
110#define NODE_NAME_CASE(node) case AMDGPUISD::node: return #node;
111
112const char* AMDGPUTargetLowering::getTargetNodeName(unsigned Opcode) const
113{
114  switch (Opcode) {
115  default: return AMDILTargetLowering::getTargetNodeName(Opcode);
116
117  NODE_NAME_CASE(FMAX)
118  NODE_NAME_CASE(SMAX)
119  NODE_NAME_CASE(UMAX)
120  NODE_NAME_CASE(FMIN)
121  NODE_NAME_CASE(SMIN)
122  NODE_NAME_CASE(UMIN)
123  }
124}
125