Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
35268 views
1
//===-- SPIRVInstrInfo.cpp - SPIR-V Instruction Information ------*- C++-*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file contains the SPIR-V implementation of the TargetInstrInfo class.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "SPIRVInstrInfo.h"
14
#include "SPIRV.h"
15
#include "llvm/ADT/SmallVector.h"
16
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
17
#include "llvm/CodeGen/MachineBasicBlock.h"
18
#include "llvm/IR/DebugLoc.h"
19
#include "llvm/Support/ErrorHandling.h"
20
21
#define GET_INSTRINFO_CTOR_DTOR
22
#include "SPIRVGenInstrInfo.inc"
23
24
using namespace llvm;
25
26
SPIRVInstrInfo::SPIRVInstrInfo() : SPIRVGenInstrInfo() {}
27
28
bool SPIRVInstrInfo::isConstantInstr(const MachineInstr &MI) const {
29
switch (MI.getOpcode()) {
30
case SPIRV::OpConstantTrue:
31
case SPIRV::OpConstantFalse:
32
case SPIRV::OpConstantI:
33
case SPIRV::OpConstantF:
34
case SPIRV::OpConstantComposite:
35
case SPIRV::OpConstantSampler:
36
case SPIRV::OpConstantNull:
37
case SPIRV::OpSpecConstantTrue:
38
case SPIRV::OpSpecConstantFalse:
39
case SPIRV::OpSpecConstant:
40
case SPIRV::OpSpecConstantComposite:
41
case SPIRV::OpSpecConstantOp:
42
case SPIRV::OpUndef:
43
case SPIRV::OpConstantFunctionPointerINTEL:
44
return true;
45
default:
46
return false;
47
}
48
}
49
50
bool SPIRVInstrInfo::isInlineAsmDefInstr(const MachineInstr &MI) const {
51
switch (MI.getOpcode()) {
52
case SPIRV::OpAsmTargetINTEL:
53
case SPIRV::OpAsmINTEL:
54
return true;
55
default:
56
return false;
57
}
58
}
59
60
bool SPIRVInstrInfo::isTypeDeclInstr(const MachineInstr &MI) const {
61
auto &MRI = MI.getMF()->getRegInfo();
62
if (MI.getNumDefs() >= 1 && MI.getOperand(0).isReg()) {
63
auto DefRegClass = MRI.getRegClassOrNull(MI.getOperand(0).getReg());
64
return DefRegClass && DefRegClass->getID() == SPIRV::TYPERegClass.getID();
65
} else {
66
return MI.getOpcode() == SPIRV::OpTypeForwardPointer;
67
}
68
}
69
70
bool SPIRVInstrInfo::isDecorationInstr(const MachineInstr &MI) const {
71
switch (MI.getOpcode()) {
72
case SPIRV::OpDecorate:
73
case SPIRV::OpDecorateId:
74
case SPIRV::OpDecorateString:
75
case SPIRV::OpMemberDecorate:
76
case SPIRV::OpMemberDecorateString:
77
return true;
78
default:
79
return false;
80
}
81
}
82
83
bool SPIRVInstrInfo::isHeaderInstr(const MachineInstr &MI) const {
84
switch (MI.getOpcode()) {
85
case SPIRV::OpCapability:
86
case SPIRV::OpExtension:
87
case SPIRV::OpExtInstImport:
88
case SPIRV::OpMemoryModel:
89
case SPIRV::OpEntryPoint:
90
case SPIRV::OpExecutionMode:
91
case SPIRV::OpExecutionModeId:
92
case SPIRV::OpString:
93
case SPIRV::OpSourceExtension:
94
case SPIRV::OpSource:
95
case SPIRV::OpSourceContinued:
96
case SPIRV::OpName:
97
case SPIRV::OpMemberName:
98
case SPIRV::OpModuleProcessed:
99
return true;
100
default:
101
return isTypeDeclInstr(MI) || isConstantInstr(MI) || isDecorationInstr(MI);
102
}
103
}
104
105
bool SPIRVInstrInfo::canUseFastMathFlags(const MachineInstr &MI) const {
106
switch (MI.getOpcode()) {
107
case SPIRV::OpFAddS:
108
case SPIRV::OpFSubS:
109
case SPIRV::OpFMulS:
110
case SPIRV::OpFDivS:
111
case SPIRV::OpFRemS:
112
case SPIRV::OpFAddV:
113
case SPIRV::OpFSubV:
114
case SPIRV::OpFMulV:
115
case SPIRV::OpFDivV:
116
case SPIRV::OpFRemV:
117
case SPIRV::OpFMod:
118
return true;
119
default:
120
return false;
121
}
122
}
123
124
bool SPIRVInstrInfo::canUseNSW(const MachineInstr &MI) const {
125
switch (MI.getOpcode()) {
126
case SPIRV::OpIAddS:
127
case SPIRV::OpIAddV:
128
case SPIRV::OpISubS:
129
case SPIRV::OpISubV:
130
case SPIRV::OpIMulS:
131
case SPIRV::OpIMulV:
132
case SPIRV::OpShiftLeftLogicalS:
133
case SPIRV::OpShiftLeftLogicalV:
134
case SPIRV::OpSNegate:
135
return true;
136
default:
137
return false;
138
}
139
}
140
141
bool SPIRVInstrInfo::canUseNUW(const MachineInstr &MI) const {
142
switch (MI.getOpcode()) {
143
case SPIRV::OpIAddS:
144
case SPIRV::OpIAddV:
145
case SPIRV::OpISubS:
146
case SPIRV::OpISubV:
147
case SPIRV::OpIMulS:
148
case SPIRV::OpIMulV:
149
return true;
150
default:
151
return false;
152
}
153
}
154
155
// Analyze the branching code at the end of MBB, returning
156
// true if it cannot be understood (e.g. it's a switch dispatch or isn't
157
// implemented for a target). Upon success, this returns false and returns
158
// with the following information in various cases:
159
//
160
// 1. If this block ends with no branches (it just falls through to its succ)
161
// just return false, leaving TBB/FBB null.
162
// 2. If this block ends with only an unconditional branch, it sets TBB to be
163
// the destination block.
164
// 3. If this block ends with a conditional branch and it falls through to a
165
// successor block, it sets TBB to be the branch destination block and a
166
// list of operands that evaluate the condition. These operands can be
167
// passed to other TargetInstrInfo methods to create new branches.
168
// 4. If this block ends with a conditional branch followed by an
169
// unconditional branch, it returns the 'true' destination in TBB, the
170
// 'false' destination in FBB, and a list of operands that evaluate the
171
// condition. These operands can be passed to other TargetInstrInfo
172
// methods to create new branches.
173
//
174
// Note that removeBranch and insertBranch must be implemented to support
175
// cases where this method returns success.
176
//
177
// If AllowModify is true, then this routine is allowed to modify the basic
178
// block (e.g. delete instructions after the unconditional branch).
179
//
180
// The CFG information in MBB.Predecessors and MBB.Successors must be valid
181
// before calling this function.
182
bool SPIRVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
183
MachineBasicBlock *&TBB,
184
MachineBasicBlock *&FBB,
185
SmallVectorImpl<MachineOperand> &Cond,
186
bool AllowModify) const {
187
TBB = nullptr;
188
FBB = nullptr;
189
if (MBB.empty())
190
return false;
191
auto MI = MBB.getLastNonDebugInstr();
192
if (!MI.isValid())
193
return false;
194
if (MI->getOpcode() == SPIRV::OpBranch) {
195
TBB = MI->getOperand(0).getMBB();
196
return false;
197
} else if (MI->getOpcode() == SPIRV::OpBranchConditional) {
198
Cond.push_back(MI->getOperand(0));
199
TBB = MI->getOperand(1).getMBB();
200
if (MI->getNumOperands() == 3) {
201
FBB = MI->getOperand(2).getMBB();
202
}
203
return false;
204
} else {
205
return true;
206
}
207
}
208
209
// Remove the branching code at the end of the specific MBB.
210
// This is only invoked in cases where analyzeBranch returns success. It
211
// returns the number of instructions that were removed.
212
// If \p BytesRemoved is non-null, report the change in code size from the
213
// removed instructions.
214
unsigned SPIRVInstrInfo::removeBranch(MachineBasicBlock &MBB,
215
int *BytesRemoved) const {
216
report_fatal_error("Branch removal not supported, as MBB info not propagated"
217
" to OpPhi instructions. Try using -O0 instead.");
218
}
219
220
// Insert branch code into the end of the specified MachineBasicBlock. The
221
// operands to this method are the same as those returned by analyzeBranch.
222
// This is only invoked in cases where analyzeBranch returns success. It
223
// returns the number of instructions inserted. If \p BytesAdded is non-null,
224
// report the change in code size from the added instructions.
225
//
226
// It is also invoked by tail merging to add unconditional branches in
227
// cases where analyzeBranch doesn't apply because there was no original
228
// branch to analyze. At least this much must be implemented, else tail
229
// merging needs to be disabled.
230
//
231
// The CFG information in MBB.Predecessors and MBB.Successors must be valid
232
// before calling this function.
233
unsigned SPIRVInstrInfo::insertBranch(
234
MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
235
ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
236
report_fatal_error("Branch insertion not supported, as MBB info not "
237
"propagated to OpPhi instructions. Try using "
238
"-O0 instead.");
239
}
240
241
void SPIRVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
242
MachineBasicBlock::iterator I,
243
const DebugLoc &DL, MCRegister DestReg,
244
MCRegister SrcReg, bool KillSrc) const {
245
// Actually we don't need this COPY instruction. However if we do nothing with
246
// it, post RA pseudo instrs expansion just removes it and we get the code
247
// with undef registers. Therefore, we need to replace all uses of dst with
248
// the src register. COPY instr itself will be safely removed later.
249
assert(I->isCopy() && "Copy instruction is expected");
250
auto DstOp = I->getOperand(0);
251
auto SrcOp = I->getOperand(1);
252
assert(DstOp.isReg() && SrcOp.isReg() &&
253
"Register operands are expected in COPY");
254
auto &MRI = I->getMF()->getRegInfo();
255
MRI.replaceRegWith(DstOp.getReg(), SrcOp.getReg());
256
}
257
258
bool SPIRVInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
259
if (MI.getOpcode() == SPIRV::GET_ID || MI.getOpcode() == SPIRV::GET_ID64 ||
260
MI.getOpcode() == SPIRV::GET_fID || MI.getOpcode() == SPIRV::GET_fID64 ||
261
MI.getOpcode() == SPIRV::GET_pID32 ||
262
MI.getOpcode() == SPIRV::GET_pID64 || MI.getOpcode() == SPIRV::GET_vfID ||
263
MI.getOpcode() == SPIRV::GET_vID || MI.getOpcode() == SPIRV::GET_vpID32 ||
264
MI.getOpcode() == SPIRV::GET_vpID64) {
265
auto &MRI = MI.getMF()->getRegInfo();
266
MRI.replaceRegWith(MI.getOperand(0).getReg(), MI.getOperand(1).getReg());
267
MI.eraseFromParent();
268
return true;
269
}
270
return false;
271
}
272
273