LLVM 23.0.0git
SPIRVInstrInfo.cpp
Go to the documentation of this file.
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 "SPIRVSubtarget.h"
19#include "llvm/IR/DebugLoc.h"
20
21#define GET_INSTRINFO_CTOR_DTOR
22#include "SPIRVGenInstrInfo.inc"
23
24using namespace llvm;
25
28
30 switch (MI.getOpcode()) {
31 case SPIRV::OpConstantTrue:
32 case SPIRV::OpConstantFalse:
33 case SPIRV::OpConstantI:
34 case SPIRV::OpConstantF:
35 case SPIRV::OpConstantComposite:
36 case SPIRV::OpConstantCompositeContinuedINTEL:
37 case SPIRV::OpConstantSampler:
38 case SPIRV::OpConstantNull:
39 case SPIRV::OpSpecConstantTrue:
40 case SPIRV::OpSpecConstantFalse:
41 case SPIRV::OpSpecConstant:
42 case SPIRV::OpSpecConstantComposite:
43 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
44 case SPIRV::OpSpecConstantOp:
45 case SPIRV::OpUndef:
46 case SPIRV::OpPoisonKHR:
47 case SPIRV::OpConstantFunctionPointerINTEL:
48 return true;
49 default:
50 return false;
51 }
52}
53
55 switch (MI.getOpcode()) {
56 case SPIRV::OpSpecConstantTrue:
57 case SPIRV::OpSpecConstantFalse:
58 case SPIRV::OpSpecConstant:
59 case SPIRV::OpSpecConstantComposite:
60 case SPIRV::OpSpecConstantCompositeContinuedINTEL:
61 case SPIRV::OpSpecConstantOp:
62 return true;
63 default:
64 return false;
65 }
66}
67
69 switch (MI.getOpcode()) {
70 case SPIRV::OpAsmTargetINTEL:
71 case SPIRV::OpAsmINTEL:
72 return true;
73 default:
74 return false;
75 }
76}
77
79 auto &MRI = MI.getMF()->getRegInfo();
80 if (MI.getNumDefs() >= 1 && MI.getOperand(0).isReg()) {
81 auto DefRegClass = MRI.getRegClassOrNull(MI.getOperand(0).getReg());
82 return DefRegClass && DefRegClass->getID() == SPIRV::TYPERegClass.getID();
83 } else {
84 return MI.getOpcode() == SPIRV::OpTypeForwardPointer ||
85 MI.getOpcode() == SPIRV::OpTypeStructContinuedINTEL;
86 }
87}
88
90 switch (MI.getOpcode()) {
91 case SPIRV::OpDecorate:
92 case SPIRV::OpDecorateId:
93 case SPIRV::OpDecorateString:
94 case SPIRV::OpMemberDecorate:
95 case SPIRV::OpMemberDecorateString:
96 return true;
97 default:
98 return false;
99 }
100}
101
103 switch (MI.getOpcode()) {
104 case SPIRV::OpAliasDomainDeclINTEL:
105 case SPIRV::OpAliasScopeDeclINTEL:
106 case SPIRV::OpAliasScopeListDeclINTEL:
107 return true;
108 default:
109 return false;
110 }
111}
112
114 switch (MI.getOpcode()) {
115 case SPIRV::OpCapability:
116 case SPIRV::OpExtension:
117 case SPIRV::OpExtInstImport:
118 case SPIRV::OpMemoryModel:
119 case SPIRV::OpEntryPoint:
120 case SPIRV::OpExecutionMode:
121 case SPIRV::OpExecutionModeId:
122 case SPIRV::OpString:
123 case SPIRV::OpSourceExtension:
124 case SPIRV::OpSource:
125 case SPIRV::OpSourceContinued:
126 case SPIRV::OpName:
127 case SPIRV::OpMemberName:
128 case SPIRV::OpModuleProcessed:
129 return true;
130 default:
131 return isTypeDeclInstr(MI) || isConstantInstr(MI) ||
133 }
134}
135
137 bool KHRFloatControls2) const {
138 switch (MI.getOpcode()) {
139 case SPIRV::OpFAddS:
140 case SPIRV::OpFSubS:
141 case SPIRV::OpFMulS:
142 case SPIRV::OpFDivS:
143 case SPIRV::OpFRemS:
144 case SPIRV::OpFAddV:
145 case SPIRV::OpFSubV:
146 case SPIRV::OpFMulV:
147 case SPIRV::OpFDivV:
148 case SPIRV::OpFRemV:
149 case SPIRV::OpFMod:
150 return true;
151 case SPIRV::OpFNegateV:
152 case SPIRV::OpFNegate:
153 case SPIRV::OpOrdered:
154 case SPIRV::OpUnordered:
155 case SPIRV::OpFOrdEqual:
156 case SPIRV::OpFOrdNotEqual:
157 case SPIRV::OpFOrdLessThan:
158 case SPIRV::OpFOrdLessThanEqual:
159 case SPIRV::OpFOrdGreaterThan:
160 case SPIRV::OpFOrdGreaterThanEqual:
161 case SPIRV::OpFUnordEqual:
162 case SPIRV::OpFUnordNotEqual:
163 case SPIRV::OpFUnordLessThan:
164 case SPIRV::OpFUnordLessThanEqual:
165 case SPIRV::OpFUnordGreaterThan:
166 case SPIRV::OpFUnordGreaterThanEqual:
167 case SPIRV::OpExtInst:
168 return KHRFloatControls2 ? true : false;
169 default:
170 return false;
171 }
172}
173
175 switch (MI.getOpcode()) {
176 case SPIRV::OpIAddS:
177 case SPIRV::OpIAddV:
178 case SPIRV::OpISubS:
179 case SPIRV::OpISubV:
180 case SPIRV::OpIMulS:
181 case SPIRV::OpIMulV:
182 case SPIRV::OpShiftLeftLogicalS:
183 case SPIRV::OpShiftLeftLogicalV:
184 case SPIRV::OpSNegate:
185 return true;
186 default:
187 return false;
188 }
189}
190
192 switch (MI.getOpcode()) {
193 case SPIRV::OpIAddS:
194 case SPIRV::OpIAddV:
195 case SPIRV::OpISubS:
196 case SPIRV::OpISubV:
197 case SPIRV::OpIMulS:
198 case SPIRV::OpIMulV:
199 return true;
200 default:
201 return false;
202 }
203}
204
205// Analyze the branching code at the end of MBB, returning
206// true if it cannot be understood (e.g. it's a switch dispatch or isn't
207// implemented for a target). Upon success, this returns false and returns
208// with the following information in various cases:
209//
210// 1. If this block ends with no branches (it just falls through to its succ)
211// just return false, leaving TBB/FBB null.
212// 2. If this block ends with only an unconditional branch, it sets TBB to be
213// the destination block.
214// 3. If this block ends with a conditional branch and it falls through to a
215// successor block, it sets TBB to be the branch destination block and a
216// list of operands that evaluate the condition. These operands can be
217// passed to other TargetInstrInfo methods to create new branches.
218// 4. If this block ends with a conditional branch followed by an
219// unconditional branch, it returns the 'true' destination in TBB, the
220// 'false' destination in FBB, and a list of operands that evaluate the
221// condition. These operands can be passed to other TargetInstrInfo
222// methods to create new branches.
223//
224// Note that removeBranch and insertBranch must be implemented to support
225// cases where this method returns success.
226//
227// If AllowModify is true, then this routine is allowed to modify the basic
228// block (e.g. delete instructions after the unconditional branch).
229//
230// The CFG information in MBB.Predecessors and MBB.Successors must be valid
231// before calling this function.
234 MachineBasicBlock *&FBB,
236 bool AllowModify) const {
237 // We do not allow to restructure blocks by results of analyzeBranch(),
238 // because it may potentially break structured control flow and anyway
239 // doubtedly may be useful in SPIRV, including such reasons as, e.g.:
240 // 1) there is no way to encode `if (Cond) then Stmt` logic, only full
241 // if-then-else is supported by OpBranchConditional, so if we supported
242 // splitting of blocks ending with OpBranchConditional MachineBasicBlock.cpp
243 // would expect successfull implementation of calls to insertBranch() setting
244 // FBB to null that is not feasible; 2) it's not possible to delete
245 // instructions after the unconditional branch, because this instruction must
246 // be the last instruction in a block.
247 return true;
248}
249
250// Remove the branching code at the end of the specific MBB.
251// This is only invoked in cases where analyzeBranch returns success. It
252// returns the number of instructions that were removed.
253// If \p BytesRemoved is non-null, report the change in code size from the
254// removed instructions.
256 int * /*BytesRemoved*/) const {
257 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
258 if (I == MBB.end())
259 return 0;
260
261 if (I->getOpcode() == SPIRV::OpBranch) {
262 I->eraseFromParent();
263 return 1;
264 }
265 return 0;
266}
267
268// Insert branch code into the end of the specified MachineBasicBlock. The
269// operands to this method are the same as those returned by analyzeBranch.
270// This is only invoked in cases where analyzeBranch returns success. It
271// returns the number of instructions inserted. If \p BytesAdded is non-null,
272// report the change in code size from the added instructions.
273//
274// It is also invoked by tail merging to add unconditional branches in
275// cases where analyzeBranch doesn't apply because there was no original
276// branch to analyze. At least this much must be implemented, else tail
277// merging needs to be disabled.
278//
279// The CFG information in MBB.Predecessors and MBB.Successors must be valid
280// before calling this function.
285 const DebugLoc &DL,
286 int * /*BytesAdded*/) const {
287 if (!TBB)
288 return 0;
289 BuildMI(&MBB, DL, get(SPIRV::OpBranch)).addMBB(TBB);
290 return 1;
291}
292
295 const DebugLoc &DL, Register DestReg,
296 Register SrcReg, bool KillSrc,
297 bool RenamableDest, bool RenamableSrc) const {
298 // Actually we don't need this COPY instruction. However if we do nothing with
299 // it, post RA pseudo instrs expansion just removes it and we get the code
300 // with undef registers. Therefore, we need to replace all uses of dst with
301 // the src register. COPY instr itself will be safely removed later.
302 assert(I->isCopy() && "Copy instruction is expected");
303 auto DstOp = I->getOperand(0);
304 auto SrcOp = I->getOperand(1);
305 assert(DstOp.isReg() && SrcOp.isReg() &&
306 "Register operands are expected in COPY");
307 auto &MRI = I->getMF()->getRegInfo();
308 MRI.replaceRegWith(DstOp.getReg(), SrcOp.getReg());
309}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
This file declares the MachineIRBuilder class.
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallVector class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
A debug info location.
Definition DebugLoc.h:124
Register getReg() const
MachineInstrBundleIterator< MachineInstr > iterator
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
bool isConstantInstr(const MachineInstr &MI) const
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
bool isInlineAsmDefInstr(const MachineInstr &MI) const
SPIRVInstrInfo(const SPIRVSubtarget &STI)
bool isTypeDeclInstr(const MachineInstr &MI) const
bool isDecorationInstr(const MachineInstr &MI) const
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool isAliasingInstr(const MachineInstr &MI) const
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool canUseFastMathFlags(const MachineInstr &MI, bool KHRFloatControls2) const
bool isHeaderInstr(const MachineInstr &MI) const
bool canUseNUW(const MachineInstr &MI) const
bool isSpecConstantInstr(const MachineInstr &MI) const
bool canUseNSW(const MachineInstr &MI) const
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Register getReg() const
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)