xref: /llvm-project/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp (revision 83c1d003118a2cb8136fe49e2ec43958c93d9d6b)
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::isSpecConstantInstr(const MachineInstr &MI) const {
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 
63 bool SPIRVInstrInfo::isInlineAsmDefInstr(const MachineInstr &MI) const {
64   switch (MI.getOpcode()) {
65   case SPIRV::OpAsmTargetINTEL:
66   case SPIRV::OpAsmINTEL:
67     return true;
68   default:
69     return false;
70   }
71 }
72 
73 bool SPIRVInstrInfo::isTypeDeclInstr(const MachineInstr &MI) const {
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 
83 bool SPIRVInstrInfo::isDecorationInstr(const MachineInstr &MI) const {
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 
96 bool SPIRVInstrInfo::isHeaderInstr(const MachineInstr &MI) const {
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:
114     return isTypeDeclInstr(MI) || isConstantInstr(MI) || isDecorationInstr(MI);
115   }
116 }
117 
118 bool SPIRVInstrInfo::canUseFastMathFlags(const MachineInstr &MI) const {
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 
137 bool SPIRVInstrInfo::canUseNSW(const MachineInstr &MI) const {
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 
154 bool SPIRVInstrInfo::canUseNUW(const MachineInstr &MI) const {
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.
195 bool SPIRVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
196                                    MachineBasicBlock *&TBB,
197                                    MachineBasicBlock *&FBB,
198                                    SmallVectorImpl<MachineOperand> &Cond,
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.
218 unsigned SPIRVInstrInfo::removeBranch(MachineBasicBlock &MBB,
219                                       int * /*BytesRemoved*/) const {
220   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
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.
244 unsigned SPIRVInstrInfo::insertBranch(MachineBasicBlock &MBB,
245                                       MachineBasicBlock *TBB,
246                                       MachineBasicBlock *FBB,
247                                       ArrayRef<MachineOperand> Cond,
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 
256 void SPIRVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
257                                  MachineBasicBlock::iterator I,
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 
274 bool SPIRVInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
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 }
285