Merge branch 'gallium-userbuf'
[mesa.git] / src / gallium / drivers / radeon / 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 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
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, &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
33 MachineBasicBlock * SITargetLowering::EmitInstrWithCustomInserter(
34 MachineInstr * MI, MachineBasicBlock * BB) const
35 {
36 const struct 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 }
43
44 switch (MI->getOpcode()) {
45 default:
46 return AMDGPUTargetLowering::EmitInstrWithCustomInserter(MI, BB);
47 case AMDIL::SI_INTERP:
48 LowerSI_INTERP(MI, *BB, I, MRI);
49 break;
50 case AMDIL::SI_INTERP_CONST:
51 LowerSI_INTERP_CONST(MI, *BB, I);
52 break;
53 case AMDIL::SI_V_CNDLT:
54 LowerSI_V_CNDLT(MI, *BB, I, MRI);
55 break;
56 case AMDIL::USE_SGPR_32:
57 case AMDIL::USE_SGPR_64:
58 lowerUSE_SGPR(MI, BB->getParent(), MRI);
59 MI->eraseFromParent();
60 break;
61 case AMDIL::VS_LOAD_BUFFER_INDEX:
62 addLiveIn(MI, BB->getParent(), MRI, TII, AMDIL::VGPR0);
63 MI->eraseFromParent();
64 break;
65 }
66 return BB;
67 }
68
69 void SITargetLowering::AppendS_WAITCNT(MachineInstr *MI, MachineBasicBlock &BB,
70 MachineBasicBlock::iterator I) const
71 {
72 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_WAITCNT))
73 .addImm(0);
74 }
75
76 void SITargetLowering::LowerSI_INTERP(MachineInstr *MI, MachineBasicBlock &BB,
77 MachineBasicBlock::iterator I, MachineRegisterInfo & MRI) const
78 {
79 unsigned tmp = MRI.createVirtualRegister(&AMDIL::VReg_32RegClass);
80 MachineOperand dst = MI->getOperand(0);
81 MachineOperand iReg = MI->getOperand(1);
82 MachineOperand jReg = MI->getOperand(2);
83 MachineOperand attr_chan = MI->getOperand(3);
84 MachineOperand attr = MI->getOperand(4);
85 MachineOperand params = MI->getOperand(5);
86
87 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_MOV_B32))
88 .addReg(AMDIL::M0)
89 .addOperand(params);
90
91 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_P1_F32), tmp)
92 .addOperand(iReg)
93 .addOperand(attr_chan)
94 .addOperand(attr);
95
96 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_P2_F32))
97 .addOperand(dst)
98 .addReg(tmp)
99 .addOperand(jReg)
100 .addOperand(attr_chan)
101 .addOperand(attr);
102
103 MI->eraseFromParent();
104 }
105
106 void SITargetLowering::LowerSI_INTERP_CONST(MachineInstr *MI,
107 MachineBasicBlock &BB, MachineBasicBlock::iterator I) const
108 {
109 MachineOperand dst = MI->getOperand(0);
110 MachineOperand attr_chan = MI->getOperand(1);
111 MachineOperand attr = MI->getOperand(2);
112 MachineOperand params = MI->getOperand(3);
113
114 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_MOV_B32))
115 .addReg(AMDIL::M0)
116 .addOperand(params);
117
118 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_MOV_F32))
119 .addOperand(dst)
120 .addOperand(attr_chan)
121 .addOperand(attr);
122
123 MI->eraseFromParent();
124 }
125
126 void SITargetLowering::LowerSI_V_CNDLT(MachineInstr *MI, MachineBasicBlock &BB,
127 MachineBasicBlock::iterator I, MachineRegisterInfo & MRI) const
128 {
129 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_CMP_LT_F32_e32))
130 .addOperand(MI->getOperand(1))
131 .addReg(AMDIL::SREG_LIT_0);
132
133 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_CNDMASK_B32))
134 .addOperand(MI->getOperand(0))
135 .addOperand(MI->getOperand(2))
136 .addOperand(MI->getOperand(3));
137
138 MI->eraseFromParent();
139 }
140
141 void SITargetLowering::lowerUSE_SGPR(MachineInstr *MI,
142 MachineFunction * MF, MachineRegisterInfo & MRI) const
143 {
144 const struct TargetInstrInfo * TII = getTargetMachine().getInstrInfo();
145 unsigned dstReg = MI->getOperand(0).getReg();
146 int64_t newIndex = MI->getOperand(1).getImm();
147 const TargetRegisterClass * dstClass = MRI.getRegClass(dstReg);
148
149 unsigned newReg = dstClass->getRegister(newIndex);
150 addLiveIn(MI, MF, MRI, TII, newReg);
151 }
152