radeonsi: initial WIP SI code
[mesa.git] / src / gallium / drivers / radeon / SIISelLowering.cpp
1 //===-- SIISelLowering.cpp - TODO: Add brief description -------===//
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 // TODO: Add full description
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "SIISelLowering.h"
15 #include "SIInstrInfo.h"
16 #include "SIRegisterInfo.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18
19 using namespace llvm;
20
21 SITargetLowering::SITargetLowering(TargetMachine &TM) :
22 AMDGPUTargetLowering(TM),
23 TII(static_cast<const SIInstrInfo*>(TM.getInstrInfo()))
24 {
25 addRegisterClass(MVT::v4f32, &AMDIL::VReg_128RegClass);
26 addRegisterClass(MVT::f32, &AMDIL::VReg_32RegClass);
27
28 setOperationAction(ISD::EXTRACT_VECTOR_ELT, MVT::v4f32, Legal);
29 setOperationAction(ISD::INSERT_VECTOR_ELT, MVT::v4f32, Legal);
30 }
31
32 MachineBasicBlock * SITargetLowering::EmitInstrWithCustomInserter(
33 MachineInstr * MI, MachineBasicBlock * BB) const
34 {
35 const struct TargetInstrInfo * TII = getTargetMachine().getInstrInfo();
36 MachineRegisterInfo & MRI = BB->getParent()->getRegInfo();
37 MachineBasicBlock::iterator I = MI;
38
39 if (TII->get(MI->getOpcode()).TSFlags & SIInstrFlags::NEED_WAIT) {
40 AppendS_WAITCNT(MI, *BB, llvm::next(I));
41 }
42
43 switch (MI->getOpcode()) {
44 default:
45 return AMDGPUTargetLowering::EmitInstrWithCustomInserter(MI, BB);
46 case AMDIL::SI_INTERP:
47 LowerSI_INTERP(MI, *BB, I, MRI);
48 break;
49 case AMDIL::SI_INTERP_CONST:
50 LowerSI_INTERP_CONST(MI, *BB, I);
51 break;
52 case AMDIL::SI_V_CNDLT:
53 LowerSI_V_CNDLT(MI, *BB, I, MRI);
54 break;
55 case AMDIL::USE_SGPR_32:
56 case AMDIL::USE_SGPR_64:
57 lowerUSE_SGPR(MI, BB->getParent(), MRI);
58 MI->eraseFromParent();
59 break;
60 case AMDIL::VS_LOAD_BUFFER_INDEX:
61 addLiveIn(MI, BB->getParent(), MRI, TII, AMDIL::VGPR0);
62 MI->eraseFromParent();
63 break;
64 }
65 return BB;
66 }
67
68 void SITargetLowering::AppendS_WAITCNT(MachineInstr *MI, MachineBasicBlock &BB,
69 MachineBasicBlock::iterator I) const
70 {
71 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_WAITCNT))
72 .addImm(0);
73 }
74
75 void SITargetLowering::LowerSI_INTERP(MachineInstr *MI, MachineBasicBlock &BB,
76 MachineBasicBlock::iterator I, MachineRegisterInfo & MRI) const
77 {
78 unsigned tmp = MRI.createVirtualRegister(&AMDIL::VReg_32RegClass);
79 MachineOperand dst = MI->getOperand(0);
80 MachineOperand iReg = MI->getOperand(1);
81 MachineOperand jReg = MI->getOperand(2);
82 MachineOperand attr_chan = MI->getOperand(3);
83 MachineOperand attr = MI->getOperand(4);
84 MachineOperand params = MI->getOperand(5);
85
86 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_MOV_B32))
87 .addReg(AMDIL::M0)
88 .addOperand(params);
89
90 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_P1_F32), tmp)
91 .addOperand(iReg)
92 .addOperand(attr_chan)
93 .addOperand(attr);
94
95 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_P2_F32))
96 .addOperand(dst)
97 .addReg(tmp)
98 .addOperand(jReg)
99 .addOperand(attr_chan)
100 .addOperand(attr);
101
102 MI->eraseFromParent();
103 }
104
105 void SITargetLowering::LowerSI_INTERP_CONST(MachineInstr *MI,
106 MachineBasicBlock &BB, MachineBasicBlock::iterator I) const
107 {
108 MachineOperand dst = MI->getOperand(0);
109 MachineOperand attr_chan = MI->getOperand(1);
110 MachineOperand attr = MI->getOperand(2);
111 MachineOperand params = MI->getOperand(3);
112
113 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::S_MOV_B32))
114 .addReg(AMDIL::M0)
115 .addOperand(params);
116
117 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_INTERP_MOV_F32))
118 .addOperand(dst)
119 .addOperand(attr_chan)
120 .addOperand(attr);
121
122 MI->eraseFromParent();
123 }
124
125 void SITargetLowering::LowerSI_V_CNDLT(MachineInstr *MI, MachineBasicBlock &BB,
126 MachineBasicBlock::iterator I, MachineRegisterInfo & MRI) const
127 {
128 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_CMP_LT_F32_e32))
129 .addOperand(MI->getOperand(1))
130 .addReg(AMDIL::SREG_LIT_0);
131
132 BuildMI(BB, I, BB.findDebugLoc(I), TII->get(AMDIL::V_CNDMASK_B32))
133 .addOperand(MI->getOperand(0))
134 .addOperand(MI->getOperand(2))
135 .addOperand(MI->getOperand(3));
136
137 MI->eraseFromParent();
138 }
139
140 void SITargetLowering::lowerUSE_SGPR(MachineInstr *MI,
141 MachineFunction * MF, MachineRegisterInfo & MRI) const
142 {
143 const struct TargetInstrInfo * TII = getTargetMachine().getInstrInfo();
144 unsigned dstReg = MI->getOperand(0).getReg();
145 int64_t newIndex = MI->getOperand(1).getImm();
146 const TargetRegisterClass * dstClass = MRI.getRegClass(dstReg);
147
148 unsigned newReg = dstClass->getRegister(newIndex);
149 addLiveIn(MI, MF, MRI, TII, newReg);
150 }
151