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