LLVM 20.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"
18#include "llvm/IR/DebugLoc.h"
20
21#define GET_INSTRINFO_CTOR_DTOR
22#include "SPIRVGenInstrInfo.inc"
23
24using namespace llvm;
25
27
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
51 switch (MI.getOpcode()) {
52 case SPIRV::OpSpecConstantTrue:
53 case SPIRV::OpSpecConstantFalse:
54 case SPIRV::OpSpecConstant:
55 case SPIRV::OpSpecConstantComposite:
56 case SPIRV::OpSpecConstantOp:
57 return true;
58 default:
59 return false;
60 }
61}
62
64 switch (MI.getOpcode()) {
65 case SPIRV::OpAsmTargetINTEL:
66 case SPIRV::OpAsmINTEL:
67 return true;
68 default:
69 return false;
70 }
71}
72
74 auto &MRI = MI.getMF()->getRegInfo();
75 if (MI.getNumDefs() >= 1 && MI.getOperand(0).isReg()) {
76 auto DefRegClass = MRI.getRegClassOrNull(MI.getOperand(0).getReg());
77 return DefRegClass && DefRegClass->getID() == SPIRV::TYPERegClass.getID();
78 } else {
79 return MI.getOpcode() == SPIRV::OpTypeForwardPointer;
80 }
81}
82
84 switch (MI.getOpcode()) {
85 case SPIRV::OpDecorate:
86 case SPIRV::OpDecorateId:
87 case SPIRV::OpDecorateString:
88 case SPIRV::OpMemberDecorate:
89 case SPIRV::OpMemberDecorateString:
90 return true;
91 default:
92 return false;
93 }
94}
95
97 switch (MI.getOpcode()) {
98 case SPIRV::OpCapability:
99 case SPIRV::OpExtension:
100 case SPIRV::OpExtInstImport:
101 case SPIRV::OpMemoryModel:
102 case SPIRV::OpEntryPoint:
103 case SPIRV::OpExecutionMode:
104 case SPIRV::OpExecutionModeId:
105 case SPIRV::OpString:
106 case SPIRV::OpSourceExtension:
107 case SPIRV::OpSource:
108 case SPIRV::OpSourceContinued:
109 case SPIRV::OpName:
110 case SPIRV::OpMemberName:
111 case SPIRV::OpModuleProcessed:
112 return true;
113 default:
115 }
116}
117
119 switch (MI.getOpcode()) {
120 case SPIRV::OpFAddS:
121 case SPIRV::OpFSubS:
122 case SPIRV::OpFMulS:
123 case SPIRV::OpFDivS:
124 case SPIRV::OpFRemS:
125 case SPIRV::OpFAddV:
126 case SPIRV::OpFSubV:
127 case SPIRV::OpFMulV:
128 case SPIRV::OpFDivV:
129 case SPIRV::OpFRemV:
130 case SPIRV::OpFMod:
131 return true;
132 default:
133 return false;
134 }
135}
136
138 switch (MI.getOpcode()) {
139 case SPIRV::OpIAddS:
140 case SPIRV::OpIAddV:
141 case SPIRV::OpISubS:
142 case SPIRV::OpISubV:
143 case SPIRV::OpIMulS:
144 case SPIRV::OpIMulV:
145 case SPIRV::OpShiftLeftLogicalS:
146 case SPIRV::OpShiftLeftLogicalV:
147 case SPIRV::OpSNegate:
148 return true;
149 default:
150 return false;
151 }
152}
153
155 switch (MI.getOpcode()) {
156 case SPIRV::OpIAddS:
157 case SPIRV::OpIAddV:
158 case SPIRV::OpISubS:
159 case SPIRV::OpISubV:
160 case SPIRV::OpIMulS:
161 case SPIRV::OpIMulV:
162 return true;
163 default:
164 return false;
165 }
166}
167
168// Analyze the branching code at the end of MBB, returning
169// true if it cannot be understood (e.g. it's a switch dispatch or isn't
170// implemented for a target). Upon success, this returns false and returns
171// with the following information in various cases:
172//
173// 1. If this block ends with no branches (it just falls through to its succ)
174// just return false, leaving TBB/FBB null.
175// 2. If this block ends with only an unconditional branch, it sets TBB to be
176// the destination block.
177// 3. If this block ends with a conditional branch and it falls through to a
178// successor block, it sets TBB to be the branch destination block and a
179// list of operands that evaluate the condition. These operands can be
180// passed to other TargetInstrInfo methods to create new branches.
181// 4. If this block ends with a conditional branch followed by an
182// unconditional branch, it returns the 'true' destination in TBB, the
183// 'false' destination in FBB, and a list of operands that evaluate the
184// condition. These operands can be passed to other TargetInstrInfo
185// methods to create new branches.
186//
187// Note that removeBranch and insertBranch must be implemented to support
188// cases where this method returns success.
189//
190// If AllowModify is true, then this routine is allowed to modify the basic
191// block (e.g. delete instructions after the unconditional branch).
192//
193// The CFG information in MBB.Predecessors and MBB.Successors must be valid
194// before calling this function.
197 MachineBasicBlock *&FBB,
199 bool AllowModify) const {
200 // We do not allow to restructure blocks by results of analyzeBranch(),
201 // because it may potentially break structured control flow and anyway
202 // doubtedly may be useful in SPIRV, including such reasons as, e.g.:
203 // 1) there is no way to encode `if (Cond) then Stmt` logic, only full
204 // if-then-else is supported by OpBranchConditional, so if we supported
205 // splitting of blocks ending with OpBranchConditional MachineBasicBlock.cpp
206 // would expect successfull implementation of calls to insertBranch() setting
207 // FBB to null that is not feasible; 2) it's not possible to delete
208 // instructions after the unconditional branch, because this instruction must
209 // be the last instruction in a block.
210 return true;
211}
212
213// Remove the branching code at the end of the specific MBB.
214// This is only invoked in cases where analyzeBranch returns success. It
215// returns the number of instructions that were removed.
216// If \p BytesRemoved is non-null, report the change in code size from the
217// removed instructions.
219 int * /*BytesRemoved*/) const {
221 if (I == MBB.end())
222 return 0;
223
224 if (I->getOpcode() == SPIRV::OpBranch) {
225 I->eraseFromParent();
226 return 1;
227 }
228 return 0;
229}
230
231// Insert branch code into the end of the specified MachineBasicBlock. The
232// operands to this method are the same as those returned by analyzeBranch.
233// This is only invoked in cases where analyzeBranch returns success. It
234// returns the number of instructions inserted. If \p BytesAdded is non-null,
235// report the change in code size from the added instructions.
236//
237// It is also invoked by tail merging to add unconditional branches in
238// cases where analyzeBranch doesn't apply because there was no original
239// branch to analyze. At least this much must be implemented, else tail
240// merging needs to be disabled.
241//
242// The CFG information in MBB.Predecessors and MBB.Successors must be valid
243// before calling this function.
248 const DebugLoc &DL,
249 int * /*BytesAdded*/) const {
250 if (!TBB)
251 return 0;
252 BuildMI(&MBB, DL, get(SPIRV::OpBranch)).addMBB(TBB);
253 return 1;
254}
255
258 const DebugLoc &DL, MCRegister DestReg,
259 MCRegister SrcReg, bool KillSrc,
260 bool RenamableDest, bool RenamableSrc) const {
261 // Actually we don't need this COPY instruction. However if we do nothing with
262 // it, post RA pseudo instrs expansion just removes it and we get the code
263 // with undef registers. Therefore, we need to replace all uses of dst with
264 // the src register. COPY instr itself will be safely removed later.
265 assert(I->isCopy() && "Copy instruction is expected");
266 auto DstOp = I->getOperand(0);
267 auto SrcOp = I->getOperand(1);
268 assert(DstOp.isReg() && SrcOp.isReg() &&
269 "Register operands are expected in COPY");
270 auto &MRI = I->getMF()->getRegInfo();
271 MRI.replaceRegWith(DstOp.getReg(), SrcOp.getReg());
272}
273
275 if (MI.getOpcode() == SPIRV::GET_ID || MI.getOpcode() == SPIRV::GET_fID ||
276 MI.getOpcode() == SPIRV::GET_pID || MI.getOpcode() == SPIRV::GET_vfID ||
277 MI.getOpcode() == SPIRV::GET_vID || MI.getOpcode() == SPIRV::GET_vpID) {
278 auto &MRI = MI.getMF()->getRegInfo();
279 MRI.replaceRegWith(MI.getOperand(0).getReg(), MI.getOperand(1).getReg());
280 MI.eraseFromParent();
281 return true;
282 }
283 return false;
284}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineIRBuilder class.
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
A debug info location.
Definition: DebugLoc.h:33
Register getReg() const
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
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
bool isTypeDeclInstr(const MachineInstr &MI) const
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool canUseFastMathFlags(const MachineInstr &MI) const
bool isDecorationInstr(const MachineInstr &MI) const
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool expandPostRAPseudo(MachineInstr &MI) const override
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...
Definition: SmallVector.h:573
Register getReg() const
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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)