SIISelLowering.cpp revision d784bc77405012b442ae9d68f200e9d115030b3c
1//===-- SIISelLowering.cpp - SI 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// Most of the DAG lowering is handled in AMDILISelLowering.cpp.  This file is
11// mostly EmitInstrWithCustomInserter().
12//
13//===----------------------------------------------------------------------===//
14
15#include "SIISelLowering.h"
16#include "SIInstrInfo.h"
17#include "SIRegisterInfo.h"
18#include "llvm/CodeGen/MachineRegisterInfo.h"
19
20using namespace llvm;
21
22SITargetLowering::SITargetLowering(TargetMachine &TM) :
23    AMDGPUTargetLowering(TM),
24    TII(static_cast<const SIInstrInfo*>(TM.getInstrInfo()))
25{
26  addRegisterClass(MVT::v4f32, &AMDIL::VReg_128RegClass);
27  addRegisterClass(MVT::f32, &AMDIL::VReg_32RegClass);
28
29  setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4f32, Legal);
30  setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f32, Legal);
31}
32
33MachineBasicBlock * SITargetLowering::EmitInstrWithCustomInserter(
34    MachineInstr * MI, MachineBasicBlock * BB) const
35{
36  const TargetInstrInfo * TII = getTargetMachine().getInstrInfo();
37  MachineRegisterInfo & MRI = BB->getParent()->getRegInfo();
38  MachineBasicBlock::iterator I = MI;
39
40  if (TII->get(MI->getOpcode()).TSFlags & SIInstrFlags::NEED_WAIT) {
41    AppendS_WAITCNT(MI, *BB, llvm::next(I));
42    return BB;
43  }
44
45  switch (MI->getOpcode()) {
46  default:
47    return AMDGPUTargetLowering::EmitInstrWithCustomInserter(MI, BB);
48
49  case AMDIL::CLAMP_SI:
50    BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDIL::V_MOV_B32_e64))
51           .addOperand(MI->getOperand(0))
52           .addOperand(MI->getOperand(1))
53          /* VSRC1-2 are unused, but we still need to fill all the
54           * operand slots, so we just reuse the VSRC0 operand */
55           .addOperand(MI->getOperand(1))
56           .addOperand(MI->getOperand(1))
57           .addImm(0) // ABS
58           .addImm(1) // CLAMP
59           .addImm(0) // OMOD
60           .addImm(0); // NEG
61    MI->eraseFromParent();
62    break;
63
64  case AMDIL::FABS_SI:
65    BuildMI(*BB, I, BB->findDebugLoc(I), TII->get(AMDIL::V_MOV_B32_e64))
66                 .addOperand(MI->getOperand(0))
67                 .addOperand(MI->getOperand(1))
68                /* VSRC1-2 are unused, but we still need to fill all the
69                 * operand slots, so we just reuse the VSRC0 operand */
70                 .addOperand(MI->getOperand(1))
71                 .addOperand(MI->getOperand(1))
72                 .addImm(1) // ABS
73                 .addImm(0) // CLAMP
74                 .addImm(0) // OMOD
75                 .addImm(0); // NEG
76    MI->eraseFromParent();
77    break;
78
79  case AMDIL::SI_INTERP:
80    LowerSI_INTERP(MI, *BB, I, MRI);
81    break;
82  case AMDIL::SI_INTERP_CONST:
83    LowerSI_INTERP_CONST(MI, *BB, I);
84    break;
85  case AMDIL::SI_V_CNDLT:
86    LowerSI_V_CNDLT(MI, *BB, I, MRI);
87    break;
88  case AMDIL::USE_SGPR_32:
89  case AMDIL::USE_SGPR_64:
90    lowerUSE_SGPR(MI, BB->getParent(), MRI);
91    MI->eraseFromParent();
92    break;
93  case AMDIL::VS_LOAD_BUFFER_INDEX:
94    addLiveIn(MI, BB->getParent(), MRI, TII, AMDIL::VGPR0);
95    MI->eraseFromParent();
96    break;
97  }
98  return BB;
99}
100
101void SITargetLowering::AppendS_WAITCNT(MachineInstr *MI, MachineBasicBlock &BB,
102    MachineBasicBlock::iterator I) const
103{
104  BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_WAITCNT))
105          .addImm(0);
106}
107
108void SITargetLowering::LowerSI_INTERP(MachineInstr *MI, MachineBasicBlock &BB,
109    MachineBasicBlock::iterator I, MachineRegisterInfo & MRI) const
110{
111  unsigned tmp = MRI.createVirtualRegister(&AMDIL::VReg_32RegClass);
112  MachineOperand dst = MI->getOperand(0);
113  MachineOperand iReg = MI->getOperand(1);
114  MachineOperand jReg = MI->getOperand(2);
115  MachineOperand attr_chan = MI->getOperand(3);
116  MachineOperand attr = MI->getOperand(4);
117  MachineOperand params = MI->getOperand(5);
118
119  BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_MOV_B32))
120          .addReg(AMDIL::M0)
121          .addOperand(params);
122
123  BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_P1_F32), tmp)
124          .addOperand(iReg)
125          .addOperand(attr_chan)
126          .addOperand(attr);
127
128  BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_P2_F32))
129          .addOperand(dst)
130          .addReg(tmp)
131          .addOperand(jReg)
132          .addOperand(attr_chan)
133          .addOperand(attr);
134
135  MI->eraseFromParent();
136}
137
138void SITargetLowering::LowerSI_INTERP_CONST(MachineInstr *MI,
139    MachineBasicBlock &BB, MachineBasicBlock::iterator I) const
140{
141  MachineOperand dst = MI->getOperand(0);
142  MachineOperand attr_chan = MI->getOperand(1);
143  MachineOperand attr = MI->getOperand(2);
144  MachineOperand params = MI->getOperand(3);
145
146  BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_MOV_B32))
147          .addReg(AMDIL::M0)
148          .addOperand(params);
149
150  BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_MOV_F32))
151          .addOperand(dst)
152          .addOperand(attr_chan)
153          .addOperand(attr);
154
155  MI->eraseFromParent();
156}
157
158void SITargetLowering::LowerSI_V_CNDLT(MachineInstr *MI, MachineBasicBlock &BB,
159    MachineBasicBlock::iterator I, MachineRegisterInfo & MRI) const
160{
161  BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_CMP_LT_F32_e32))
162          .addOperand(MI->getOperand(1))
163          .addReg(AMDIL::SREG_LIT_0);
164
165  BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_CNDMASK_B32))
166          .addOperand(MI->getOperand(0))
167          .addOperand(MI->getOperand(2))
168          .addOperand(MI->getOperand(3));
169
170  MI->eraseFromParent();
171}
172
173void SITargetLowering::lowerUSE_SGPR(MachineInstr *MI,
174    MachineFunction * MF, MachineRegisterInfo & MRI) const
175{
176  const TargetInstrInfo * TII = getTargetMachine().getInstrInfo();
177  unsigned dstReg = MI->getOperand(0).getReg();
178  int64_t newIndex = MI->getOperand(1).getImm();
179  const TargetRegisterClass * dstClass = MRI.getRegClass(dstReg);
180
181  unsigned newReg = dstClass->getRegister(newIndex);
182  addLiveIn(MI, MF, MRI, TII, newReg);
183}
184
185