1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
//===-- SIInstrInfo.cpp - SI Instruction Information ---------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// SI Implementation of TargetInstrInfo.
//
//===----------------------------------------------------------------------===//
#include "SIInstrInfo.h"
#include "AMDGPUTargetMachine.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/MC/MCInstrDesc.h"
#include <stdio.h>
using namespace llvm;
SIInstrInfo::SIInstrInfo(AMDGPUTargetMachine &tm)
: AMDGPUInstrInfo(tm),
RI(tm, *this),
TM(tm)
{ }
const SIRegisterInfo &SIInstrInfo::getRegisterInfo() const
{
return RI;
}
void
SIInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, DebugLoc DL,
unsigned DestReg, unsigned SrcReg,
bool KillSrc) const
{
BuildMI(MBB, MI, DL, get(AMDIL::V_MOV_B32_e32), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
}
unsigned SIInstrInfo::getEncodingType(const MachineInstr &MI) const
{
return get(MI.getOpcode()).TSFlags & SI_INSTR_FLAGS_ENCODING_MASK;
}
unsigned SIInstrInfo::getEncodingBytes(const MachineInstr &MI) const
{
/* Instructions with literal constants are expanded to 64-bits, and
* the constant is stored in bits [63:32] */
for (unsigned i = 0; i < MI.getNumOperands(); i++) {
if (MI.getOperand(i).getType() == MachineOperand::MO_FPImmediate) {
return 8;
}
}
/* This instruction always has a literal */
if (MI.getOpcode() == AMDIL::S_MOV_IMM_I32) {
return 8;
}
unsigned encoding_type = getEncodingType(MI);
switch (encoding_type) {
case SIInstrEncodingType::EXP:
case SIInstrEncodingType::LDS:
case SIInstrEncodingType::MUBUF:
case SIInstrEncodingType::MTBUF:
case SIInstrEncodingType::MIMG:
case SIInstrEncodingType::VOP3:
return 8;
default:
return 4;
}
}
MachineInstr * SIInstrInfo::convertToISA(MachineInstr & MI, MachineFunction &MF,
DebugLoc DL) const
{
switch (MI.getOpcode()) {
default: break;
case AMDIL::ABS_f32: return convertABS_f32(MI, MF, DL);
case AMDIL::CLAMP_f32: return convertCLAMP_f32(MI, MF, DL);
}
MachineInstr * newMI = AMDGPUInstrInfo::convertToISA(MI, MF, DL);
const MCInstrDesc &newDesc = get(newMI->getOpcode());
/* If this instruction was converted to a VOP3, we need to add the extra
* operands for abs, clamp, omod, and negate. */
if (getEncodingType(*newMI) == SIInstrEncodingType::VOP3
&& newMI->getNumOperands() < newDesc.getNumOperands()) {
MachineInstrBuilder builder(newMI);
for (unsigned op_idx = newMI->getNumOperands();
op_idx < newDesc.getNumOperands(); op_idx++) {
builder.addImm(0);
}
}
return newMI;
}
unsigned SIInstrInfo::getISAOpcode(unsigned AMDILopcode) const
{
switch (AMDILopcode) {
//XXX We need a better way of detecting end of program
case AMDIL::RETURN: return AMDIL::S_ENDPGM;
default: return AMDGPUInstrInfo::getISAOpcode(AMDILopcode);
}
}
MachineInstr * SIInstrInfo::convertABS_f32(MachineInstr & absInstr,
MachineFunction &MF, DebugLoc DL) const
{
MachineRegisterInfo &MRI = MF.getRegInfo();
MachineOperand &dst = absInstr.getOperand(0);
/* Convert the desination register to the VReg_32 class */
if (TargetRegisterInfo::isVirtualRegister(dst.getReg())) {
MRI.setRegClass(dst.getReg(), AMDIL::VReg_32RegisterClass);
}
return BuildMI(MF, DL, get(AMDIL::V_MOV_B32_e64))
.addOperand(absInstr.getOperand(0))
.addOperand(absInstr.getOperand(1))
/* VSRC1-2 are unused, but we still need to fill all the
* operand slots, so we just reuse the VSRC0 operand */
.addOperand(absInstr.getOperand(1))
.addOperand(absInstr.getOperand(1))
.addImm(1) // ABS
.addImm(0) // CLAMP
.addImm(0) // OMOD
.addImm(0); // NEG
}
MachineInstr * SIInstrInfo::convertCLAMP_f32(MachineInstr & clampInstr,
MachineFunction &MF, DebugLoc DL) const
{
MachineRegisterInfo &MRI = MF.getRegInfo();
/* XXX: HACK assume that low == zero and high == one for now until
* we have a way to propogate the immediates. */
/*
uint32_t zero = (uint32_t)APFloat(0.0f).bitcastToAPInt().getZExtValue();
uint32_t one = (uint32_t)APFloat(1.0f).bitcastToAPInt().getZExtValue();
uint32_t low = clampInstr.getOperand(2).getImm();
uint32_t high = clampInstr.getOperand(3).getImm();
*/
// if (low == zero && high == one) {
/* Convert the desination register to the VReg_32 class */
if (TargetRegisterInfo::isVirtualRegister(clampInstr.getOperand(0).getReg())) {
MRI.setRegClass(clampInstr.getOperand(0).getReg(),
AMDIL::VReg_32RegisterClass);
}
return BuildMI(MF, DL, get(AMDIL::V_MOV_B32_e64))
.addOperand(clampInstr.getOperand(0))
.addOperand(clampInstr.getOperand(1))
/* VSRC1-2 are unused, but we still need to fill all the
* operand slots, so we just reuse the VSRC0 operand */
.addOperand(clampInstr.getOperand(1))
.addOperand(clampInstr.getOperand(1))
.addImm(0) // ABS
.addImm(1) // CLAMP
.addImm(0) // OMOD
.addImm(0); // NEG
// } else {
/* XXX: Handle other cases */
// abort();
// }
}
|