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