LLVM 19.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 auto &MRI = MI.getMF()->getRegInfo();
52 if (MI.getNumDefs() >= 1 && MI.getOperand(0).isReg()) {
53 auto DefRegClass = MRI.getRegClassOrNull(MI.getOperand(0).getReg());
54 return DefRegClass && DefRegClass->getID() == SPIRV::TYPERegClass.getID();
55 } else {
56 return MI.getOpcode() == SPIRV::OpTypeForwardPointer;
57 }
58}
59
61 switch (MI.getOpcode()) {
62 case SPIRV::OpDecorate:
63 case SPIRV::OpDecorateId:
64 case SPIRV::OpDecorateString:
65 case SPIRV::OpMemberDecorate:
66 case SPIRV::OpMemberDecorateString:
67 return true;
68 default:
69 return false;
70 }
71}
72
74 switch (MI.getOpcode()) {
75 case SPIRV::OpCapability:
76 case SPIRV::OpExtension:
77 case SPIRV::OpExtInstImport:
78 case SPIRV::OpMemoryModel:
79 case SPIRV::OpEntryPoint:
80 case SPIRV::OpExecutionMode:
81 case SPIRV::OpExecutionModeId:
82 case SPIRV::OpString:
83 case SPIRV::OpSourceExtension:
84 case SPIRV::OpSource:
85 case SPIRV::OpSourceContinued:
86 case SPIRV::OpName:
87 case SPIRV::OpMemberName:
88 case SPIRV::OpModuleProcessed:
89 return true;
90 default:
92 }
93}
94
96 switch (MI.getOpcode()) {
97 case SPIRV::OpFAddS:
98 case SPIRV::OpFSubS:
99 case SPIRV::OpFMulS:
100 case SPIRV::OpFDivS:
101 case SPIRV::OpFRemS:
102 case SPIRV::OpFAddV:
103 case SPIRV::OpFSubV:
104 case SPIRV::OpFMulV:
105 case SPIRV::OpFDivV:
106 case SPIRV::OpFRemV:
107 case SPIRV::OpFMod:
108 return true;
109 default:
110 return false;
111 }
112}
113
115 switch (MI.getOpcode()) {
116 case SPIRV::OpIAddS:
117 case SPIRV::OpIAddV:
118 case SPIRV::OpISubS:
119 case SPIRV::OpISubV:
120 case SPIRV::OpIMulS:
121 case SPIRV::OpIMulV:
122 case SPIRV::OpShiftLeftLogicalS:
123 case SPIRV::OpShiftLeftLogicalV:
124 case SPIRV::OpSNegate:
125 return true;
126 default:
127 return false;
128 }
129}
130
132 switch (MI.getOpcode()) {
133 case SPIRV::OpIAddS:
134 case SPIRV::OpIAddV:
135 case SPIRV::OpISubS:
136 case SPIRV::OpISubV:
137 case SPIRV::OpIMulS:
138 case SPIRV::OpIMulV:
139 return true;
140 default:
141 return false;
142 }
143}
144
145// Analyze the branching code at the end of MBB, returning
146// true if it cannot be understood (e.g. it's a switch dispatch or isn't
147// implemented for a target). Upon success, this returns false and returns
148// with the following information in various cases:
149//
150// 1. If this block ends with no branches (it just falls through to its succ)
151// just return false, leaving TBB/FBB null.
152// 2. If this block ends with only an unconditional branch, it sets TBB to be
153// the destination block.
154// 3. If this block ends with a conditional branch and it falls through to a
155// successor block, it sets TBB to be the branch destination block and a
156// list of operands that evaluate the condition. These operands can be
157// passed to other TargetInstrInfo methods to create new branches.
158// 4. If this block ends with a conditional branch followed by an
159// unconditional branch, it returns the 'true' destination in TBB, the
160// 'false' destination in FBB, and a list of operands that evaluate the
161// condition. These operands can be passed to other TargetInstrInfo
162// methods to create new branches.
163//
164// Note that removeBranch and insertBranch must be implemented to support
165// cases where this method returns success.
166//
167// If AllowModify is true, then this routine is allowed to modify the basic
168// block (e.g. delete instructions after the unconditional branch).
169//
170// The CFG information in MBB.Predecessors and MBB.Successors must be valid
171// before calling this function.
174 MachineBasicBlock *&FBB,
176 bool AllowModify) const {
177 TBB = nullptr;
178 FBB = nullptr;
179 if (MBB.empty())
180 return false;
181 auto MI = MBB.getLastNonDebugInstr();
182 if (!MI.isValid())
183 return false;
184 if (MI->getOpcode() == SPIRV::OpBranch) {
185 TBB = MI->getOperand(0).getMBB();
186 return false;
187 } else if (MI->getOpcode() == SPIRV::OpBranchConditional) {
188 Cond.push_back(MI->getOperand(0));
189 TBB = MI->getOperand(1).getMBB();
190 if (MI->getNumOperands() == 3) {
191 FBB = MI->getOperand(2).getMBB();
192 }
193 return false;
194 } else {
195 return true;
196 }
197}
198
199// Remove the branching code at the end of the specific MBB.
200// This is only invoked in cases where analyzeBranch returns success. It
201// returns the number of instructions that were removed.
202// If \p BytesRemoved is non-null, report the change in code size from the
203// removed instructions.
205 int *BytesRemoved) const {
206 report_fatal_error("Branch removal not supported, as MBB info not propagated"
207 " to OpPhi instructions. Try using -O0 instead.");
208}
209
210// Insert branch code into the end of the specified MachineBasicBlock. The
211// operands to this method are the same as those returned by analyzeBranch.
212// This is only invoked in cases where analyzeBranch returns success. It
213// returns the number of instructions inserted. If \p BytesAdded is non-null,
214// report the change in code size from the added instructions.
215//
216// It is also invoked by tail merging to add unconditional branches in
217// cases where analyzeBranch doesn't apply because there was no original
218// branch to analyze. At least this much must be implemented, else tail
219// merging needs to be disabled.
220//
221// The CFG information in MBB.Predecessors and MBB.Successors must be valid
222// before calling this function.
225 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
226 report_fatal_error("Branch insertion not supported, as MBB info not "
227 "propagated to OpPhi instructions. Try using "
228 "-O0 instead.");
229}
230
233 const DebugLoc &DL, MCRegister DestReg,
234 MCRegister SrcReg, bool KillSrc) const {
235 // Actually we don't need this COPY instruction. However if we do nothing with
236 // it, post RA pseudo instrs expansion just removes it and we get the code
237 // with undef registers. Therefore, we need to replace all uses of dst with
238 // the src register. COPY instr itself will be safely removed later.
239 assert(I->isCopy() && "Copy instruction is expected");
240 auto DstOp = I->getOperand(0);
241 auto SrcOp = I->getOperand(1);
242 assert(DstOp.isReg() && SrcOp.isReg() &&
243 "Register operands are expected in COPY");
244 auto &MRI = I->getMF()->getRegInfo();
245 MRI.replaceRegWith(DstOp.getReg(), SrcOp.getReg());
246}
247
249 if (MI.getOpcode() == SPIRV::GET_ID || MI.getOpcode() == SPIRV::GET_fID ||
250 MI.getOpcode() == SPIRV::GET_pID || MI.getOpcode() == SPIRV::GET_vfID ||
251 MI.getOpcode() == SPIRV::GET_vID) {
252 auto &MRI = MI.getMF()->getRegInfo();
253 MRI.replaceRegWith(MI.getOperand(0).getReg(), MI.getOperand(1).getReg());
254 MI.eraseFromParent();
255 return true;
256 }
257 return false;
258}
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().
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 isTypeDeclInstr(const MachineInstr &MI) const
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
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc) const override
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:586
Register getReg() const
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156