LLVM 24.0.0git
AMDGPUCoExecInfo.h
Go to the documentation of this file.
1//===-- AMDGPUCoExecInfo.h - Co-execution info ------------------*- 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/// \file
10/// Shared types for co-execution modeling used by GCNHazardRecognizer and the
11/// schedulers.
12///
13/// Multi-cycle instructions (WMMA, TRANS, etc.) have execution windows where
14/// other instruction types can co-execute. For WMMA, slot patterns depend on
15/// the variant:
16///
17/// E0 (Issue): Control instructions only (s_delay_alu, s_set_vgpr_msb)
18/// E (External): Memory and SALU can co-execute, no VALU
19/// I (Internal): VALU, TRANS, memory, and SALU can all co-execute
20/// V (Vacant): Memory/SALU/next-WMMA ok, NO VALU/TRANS
21///
22//===----------------------------------------------------------------------===//
23
24#ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUCOEXECINFO_H
25#define LLVM_LIB_TARGET_AMDGPU_AMDGPUCOEXECINFO_H
26
27#include "SIDefines.h"
28#include "SIInstrInfo.h"
30#include "llvm/ADT/StringRef.h"
31#include <cassert>
32#include <cstdint>
33#include <optional>
34
35namespace llvm {
36
37namespace AMDGPU {
38
39//===----------------------------------------------------------------------===//
40// Co-execution Bitmasks
41//===----------------------------------------------------------------------===//
42
43/// Bitmask for instruction types allowed to co-execute at a stage.
44enum class CoExecMask : uint16_t {
45 None = 0,
46 CTRL = 1 << 0, // Control: s_delay_alu, s_set_vgpr_msb
47 VALU = 1 << 1, // Vector ALU
48 TRANS = 1 << 2, // Transcendentals (V_EXP etc)
49 SALU = 1 << 3, // Scalar ALU
50 DS = 1 << 4, // LDS read/write
51 VMEM = 1 << 5, // Global memory
52 SMEM = 1 << 6, // Scalar memory
53 WMMA = 1 << 7, // Next WMMA (V stages only), or MFMA
54 All = 0xFFFF,
55
56 MEM = DS | VMEM | SMEM,
57 StageE0 = CTRL, // Issue: control only
58 StageE = CTRL | SALU | MEM, // External: mem/salu
59 StageI = CTRL | SALU | MEM | VALU | TRANS, // Internal: all ALU
60 // Internal + scaled-WMMA absorb: same as StageI but the next scaled
61 // WMMA may issue here - its LD_SCALE consumes the I cycle and the matrix
62 // multiply lands in the V slot that follows. Used for the last I before
63 // V of scaled patterns.
65 StageV = CTRL | SALU | MEM | WMMA, // Vacant: no valu/trans
66 StageTR = All & ~TRANS, // TRANS co-exec: no TRANS
67
68 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/All)
69};
70
72
73//===----------------------------------------------------------------------===//
74// Instruction Flavor Classification
75//===----------------------------------------------------------------------===//
76
77/// Classification of instructions by execution characteristics.
78/// Used for scheduling decisions and co-execution slot preferences.
80 WMMA, // WMMA/MFMA matrix operations
81 SingleCycleVALU, // Single-cycle VALU (not TRANS, not multi-cycle CVT)
82 TRANS, // Transcendental ops (v_exp, v_log, etc.)
83 MultiCycleVALU, // VALU instructions with repeat rate > 1
84 VMEM, // FLAT/GLOBAL memory operations
85 SMEM, // Scalar memory operations
86 DS, // LDS/GDS operations
87 SALU, // Scalar ALU
88 DMA, // Tensor DMA operations
89 Fence, // Fences and waits
90 Other, // Everything else
92};
93
95 switch (F) {
97 return "WMMA";
99 return "VALU(1c)";
101 return "TRANS";
103 return "VALU(Nc)";
105 return "VMEM";
107 return "SMEM";
109 return "DS";
111 return "SALU";
113 return "DMA";
115 return "Fence";
117 return "Other";
119 return "???";
120 }
121 llvm_unreachable("Unknown InstructionFlavor");
122}
123
124/// Classify \p MI into the execution flavor that drives both the scheduler's
125/// slot preferences and the hazard recognizer's co-execution masks.
126InstructionFlavor classifyFlavor(const MachineInstr &MI,
127 const SIInstrInfo &SII);
128
129/// Map a flavor to the co-execution class it occupies in a window slot.
131 switch (F) {
133 return CoExecMask::WMMA;
135 return CoExecMask::TRANS;
138 // LDS DMA and tensor DMA issue on the VALU pipe.
140 return CoExecMask::VALU;
142 return CoExecMask::DS;
144 return CoExecMask::VMEM;
146 return CoExecMask::SMEM;
148 // Fences are s_barrier_*/s_wait_*, which issue on the scalar pipe.
150 return CoExecMask::SALU;
152 return CoExecMask::CTRL;
154 break;
155 }
156 llvm_unreachable("Unknown InstructionFlavor");
157}
158
159//===----------------------------------------------------------------------===//
160// Co-execution Stage Type
161//===----------------------------------------------------------------------===//
162
163/// Stage type for co-execution (for annotation/display).
165 NONE = 0, // Not in co-exec window
166 E0, // Issue cycle - control only
167 E, // External - MEM/SALU allowed
168 I, // Internal - MEM/SALU/VALU allowed
169 IS, // Internal + scaled-WMMA absorb (I plus next-WMMA issue)
170 V, // Vacant - MEM/SALU/WMMA allowed, no VALU
171 TR // TRANS co-exec - everything except TRANS
172};
173
174inline const char *getStageTypeName(CoExecStageType T) {
175 switch (T) {
177 return "--";
179 return "E0";
181 return "E";
183 return "I";
185 return "IS";
187 return "V";
189 return "TR";
190 }
191 llvm_unreachable("Unknown CoExecStageType");
192}
193
194/// Return a human-readable name for a mask holding a single instruction class,
195/// as produced by getCoExecMask().
196inline const char *getCoExecMaskName(CoExecMaskT Mask) {
197 switch (Mask) {
198 case CoExecMask::CTRL:
199 return "CTRL";
200 case CoExecMask::VALU:
201 return "VALU";
203 return "TRANS";
204 case CoExecMask::SALU:
205 return "SALU";
206 case CoExecMask::DS:
207 return "DS";
208 case CoExecMask::VMEM:
209 return "VMEM";
210 case CoExecMask::SMEM:
211 return "SMEM";
212 case CoExecMask::WMMA:
213 return "WMMA";
214 default:
215 llvm_unreachable("Not a single instruction class");
216 }
217}
218
219/// Max stages: INT8 16x16x64 = 17 cycles, round up for safety.
220constexpr unsigned MaxCoExecStages = 32;
221
222//===----------------------------------------------------------------------===//
223// Co-execution Slot Info
224//===----------------------------------------------------------------------===//
225
226/// Per-slot info: which instruction classes may co-execute here.
228 CoExecMaskT Mask = CoExecMask::All; // What CAN execute (correctness)
229};
230
231//===----------------------------------------------------------------------===//
232// Co-execution Info
233//===----------------------------------------------------------------------===//
234
235/// Co-execution characteristics for a multi-cycle instruction.
237 /// Number of cycles in the co-execution window, counting any trailing
238 /// vacant stages.
239 unsigned TotalWindow = 0;
240 /// Per-stage slot info (capability mask).
242 /// Pattern string for display (e.g., "0EIIEEIIV").
244
245 /// Default constructor - initialize to safe defaults.
247 for (unsigned I = 0; I < MaxCoExecStages; ++I)
248 Slots[I].Mask = CoExecMask::All; // Default: permissive
249 }
250
251 /// Get capability mask for a stage.
252 CoExecMaskT getMask(unsigned Stage) const {
253 return Stage < TotalWindow ? Slots[Stage].Mask : CoExecMask::All;
254 }
255
256 /// Check if an instruction class mask can co-execute at a given stage.
257 bool canCoExec(CoExecMaskT InstMask, unsigned Stage) const {
258 if (Stage >= TotalWindow)
259 return true;
260 return any(Slots[Stage].Mask & InstMask);
261 }
262
263 /// Find next stage where the instruction class is allowed.
264 std::optional<unsigned> findNextAllowedStage(CoExecMaskT InstMask,
265 unsigned FromStage) const {
266 for (unsigned I = FromStage; I < TotalWindow; ++I) {
267 if (any(Slots[I].Mask & InstMask))
268 return I;
269 }
270 return std::nullopt;
271 }
272
273 /// Return the number of cycles an instruction matching \p InstMask must wait
274 /// at \p Stage. Returns zero when no stall is required.
275 unsigned getStallCycles(CoExecMaskT InstMask, unsigned Stage) const {
276 if (canCoExec(InstMask, Stage))
277 return 0;
278
279 // Stall until the next stage that accepts the instruction.
280 if (std::optional<unsigned> Next =
281 findNextAllowedStage(InstMask, Stage + 1))
282 return *Next - Stage;
283
284 // Stall until the window ends if no later stage accepts the instruction.
285 return TotalWindow - Stage;
286 }
287
288 /// Get stage type from mask for display.
290 if (Mask == CoExecMask::StageE0)
291 return CoExecStageType::E0;
292 if (Mask == CoExecMask::StageE)
293 return CoExecStageType::E;
294 if (Mask == CoExecMask::StageIS)
295 return CoExecStageType::IS;
296 if (Mask == CoExecMask::StageI)
297 return CoExecStageType::I;
298 if (Mask == CoExecMask::StageV)
299 return CoExecStageType::V;
300 if (Mask == CoExecMask::StageTR)
301 return CoExecStageType::TR;
302 // For 'All' or unknown, return based on what's allowed.
303 if (any(Mask & CoExecMask::VALU))
304 return CoExecStageType::I; // If VALU allowed, it's I-like
305 if (any(Mask & CoExecMask::WMMA))
306 return CoExecStageType::V; // If WMMA allowed (not VALU), V-like
307 return CoExecStageType::E; // Default to E
308 }
309
310 /// Get stage type for a specific stage.
311 CoExecStageType getType(unsigned Stage) const {
312 return getStageType(getMask(Stage));
313 }
314
315 /// Build a CoExecInfo from a pattern string.
316 static CoExecInfo build(unsigned TotalWindow, const char *Pattern);
317};
318
319//===----------------------------------------------------------------------===//
320// Co-execution Info Construction
321//===----------------------------------------------------------------------===//
322
323/// Build CoExecInfo from a pattern string.
324/// Pattern chars: '0'=E0, 'E'=External, 'I'=Internal, 'V'=Vacant,
325/// 'S'=Internal+ScaleWMMAAbsorb (I plus next scaled WMMA),
326/// 'T'=TRANS co-exec (all except TRANS), 'A'=Any
327inline CoExecInfo CoExecInfo::build(unsigned TotalWindow, const char *Pattern) {
328 CoExecInfo Info;
329 Info.TotalWindow = TotalWindow;
330 Info.Pattern = Pattern;
331 assert(Info.Pattern.size() == TotalWindow &&
332 "Pattern must describe every cycle of the co-execution window");
333 assert(TotalWindow <= MaxCoExecStages && "Co-execution window is too long");
334
335 for (unsigned I = 0; I < Info.TotalWindow; ++I) {
336 switch (Pattern[I]) {
337 case '0':
338 Info.Slots[I].Mask = CoExecMask::StageE0;
339 break;
340 case 'E':
341 Info.Slots[I].Mask = CoExecMask::StageE;
342 break;
343 case 'I':
344 Info.Slots[I].Mask = CoExecMask::StageI;
345 break;
346 case 'S':
347 Info.Slots[I].Mask = CoExecMask::StageIS;
348 break;
349 case 'V':
350 Info.Slots[I].Mask = CoExecMask::StageV;
351 break;
352 case 'T':
353 Info.Slots[I].Mask = CoExecMask::StageTR;
354 break;
355 case 'A':
356 default:
357 Info.Slots[I].Mask = CoExecMask::All;
358 break;
359 }
360 }
361 return Info;
362}
363
364/// Get co-execution info for a gfx950 MFMA instruction.
365CoExecInfo getMFMACoExecInfo(unsigned Opcode);
366
367/// Get co-execution info for a WMMA instruction, selecting the per-cycle slot
368/// pattern from the opcode (and operand formats for the F8F6F4 variants).
370 const SIInstrInfo &TII) {
371 unsigned Opc = MI.getOpcode();
372
373 if (TII.isMFMA(Opc))
374 return getMFMACoExecInfo(Opc);
375
376 // Scaled variants (LD_SCALE rule) absorb the next WMMA in the last I slot.
377 bool HasScaling = AMDGPU::getHasMatrixScale(Opc);
378
379 // The F8F6F4 family is the only WMMA carrying matrix format operands, and its
380 // window depends on them: both inputs f4 issue in 4 cycles, anything wider in
381 // 8. This matches the PredIsNotBothF4_WMMA_SCALE latency variant.
382 if (const MachineOperand *FmtA =
383 TII.getNamedOperand(MI, AMDGPU::OpName::matrix_a_fmt)) {
384 const MachineOperand *FmtB =
385 TII.getNamedOperand(MI, AMDGPU::OpName::matrix_b_fmt);
386 bool BothF4 = FmtB && FmtA->getImm() == AMDGPU::WMMA::MATRIX_FMT_FP4 &&
388 if (BothF4)
389 return CoExecInfo::build(6, HasScaling ? "0EESVV" : "0EEIVV");
390 return CoExecInfo::build(10, HasScaling ? "0EEIEEISVV" : "0EEIEEIIVV");
391 }
392
393 switch (Opc) {
394 // 16x16x64 IU8: 16-cycle occupancy, 17-cycle window.
395 case AMDGPU::V_WMMA_I32_16X16X64_IU8_w32_threeaddr:
396 case AMDGPU::V_WMMA_I32_16X16X64_IU8_w32_twoaddr:
397 return CoExecInfo::build(17, "0EIIEEIIEEIIEEIIV");
398
399 // 16x16x64 FP8/BF8: 4-cycle occupancy, 6-cycle window.
400 case AMDGPU::V_WMMA_F16_16X16X64_BF8_BF8_w32_threeaddr:
401 case AMDGPU::V_WMMA_F16_16X16X64_BF8_BF8_w32_twoaddr:
402 case AMDGPU::V_WMMA_F16_16X16X64_BF8_FP8_w32_threeaddr:
403 case AMDGPU::V_WMMA_F16_16X16X64_BF8_FP8_w32_twoaddr:
404 case AMDGPU::V_WMMA_F16_16X16X64_FP8_BF8_w32_threeaddr:
405 case AMDGPU::V_WMMA_F16_16X16X64_FP8_BF8_w32_twoaddr:
406 case AMDGPU::V_WMMA_F16_16X16X64_FP8_FP8_w32_threeaddr:
407 case AMDGPU::V_WMMA_F16_16X16X64_FP8_FP8_w32_twoaddr:
408 case AMDGPU::V_WMMA_F32_16X16X64_BF8_BF8_w32_threeaddr:
409 case AMDGPU::V_WMMA_F32_16X16X64_BF8_BF8_w32_twoaddr:
410 case AMDGPU::V_WMMA_F32_16X16X64_BF8_FP8_w32_threeaddr:
411 case AMDGPU::V_WMMA_F32_16X16X64_BF8_FP8_w32_twoaddr:
412 case AMDGPU::V_WMMA_F32_16X16X64_FP8_BF8_w32_threeaddr:
413 case AMDGPU::V_WMMA_F32_16X16X64_FP8_BF8_w32_twoaddr:
414 case AMDGPU::V_WMMA_F32_16X16X64_FP8_FP8_w32_threeaddr:
415 case AMDGPU::V_WMMA_F32_16X16X64_FP8_FP8_w32_twoaddr:
416 return CoExecInfo::build(6, "0EEIVV");
417
418 // 16x16x32 F16/BF16: 8-cycle occupancy, 9-cycle window.
419 case AMDGPU::V_SWMMAC_BF16_16X16X32_BF16_w32_twoaddr:
420 case AMDGPU::V_SWMMAC_BF16_16X16X32_BF16_w64_twoaddr:
421 case AMDGPU::V_SWMMAC_F16_16X16X32_F16_w32_twoaddr:
422 case AMDGPU::V_SWMMAC_F16_16X16X32_F16_w64_twoaddr:
423 case AMDGPU::V_SWMMAC_F32_16X16X32_BF16_w32_twoaddr:
424 case AMDGPU::V_SWMMAC_F32_16X16X32_BF16_w64_twoaddr:
425 case AMDGPU::V_SWMMAC_F32_16X16X32_F16_w32_twoaddr:
426 case AMDGPU::V_SWMMAC_F32_16X16X32_F16_w64_twoaddr:
427 case AMDGPU::V_WMMA_BF16F32_16X16X32_BF16_w32_threeaddr:
428 case AMDGPU::V_WMMA_BF16F32_16X16X32_BF16_w32_twoaddr:
429 case AMDGPU::V_WMMA_BF16_16X16X32_BF16_w32_threeaddr:
430 case AMDGPU::V_WMMA_BF16_16X16X32_BF16_w32_twoaddr:
431 case AMDGPU::V_WMMA_F16_16X16X32_F16_w32_threeaddr:
432 case AMDGPU::V_WMMA_F16_16X16X32_F16_w32_twoaddr:
433 case AMDGPU::V_WMMA_F32_16X16X32_BF16_w32_threeaddr:
434 case AMDGPU::V_WMMA_F32_16X16X32_BF16_w32_twoaddr:
435 case AMDGPU::V_WMMA_F32_16X16X32_F16_w32_threeaddr:
436 case AMDGPU::V_WMMA_F32_16X16X32_F16_w32_twoaddr:
437 return CoExecInfo::build(9, "0EIIEEIIV");
438
439 // 16x16x128 FP8/BF8: 8-cycle occupancy, 10-cycle window.
440 case AMDGPU::V_SWMMAC_F16_16X16X128_BF8_BF8_w32_twoaddr:
441 case AMDGPU::V_SWMMAC_F16_16X16X128_BF8_FP8_w32_twoaddr:
442 case AMDGPU::V_SWMMAC_F16_16X16X128_FP8_BF8_w32_twoaddr:
443 case AMDGPU::V_SWMMAC_F16_16X16X128_FP8_FP8_w32_twoaddr:
444 case AMDGPU::V_SWMMAC_F32_16X16X128_BF8_BF8_w32_twoaddr:
445 case AMDGPU::V_SWMMAC_F32_16X16X128_BF8_FP8_w32_twoaddr:
446 case AMDGPU::V_SWMMAC_F32_16X16X128_FP8_BF8_w32_twoaddr:
447 case AMDGPU::V_SWMMAC_F32_16X16X128_FP8_FP8_w32_twoaddr:
448 case AMDGPU::V_WMMA_F16_16X16X128_BF8_BF8_w32_threeaddr:
449 case AMDGPU::V_WMMA_F16_16X16X128_BF8_BF8_w32_twoaddr:
450 case AMDGPU::V_WMMA_F16_16X16X128_BF8_FP8_w32_threeaddr:
451 case AMDGPU::V_WMMA_F16_16X16X128_BF8_FP8_w32_twoaddr:
452 case AMDGPU::V_WMMA_F16_16X16X128_FP8_BF8_w32_threeaddr:
453 case AMDGPU::V_WMMA_F16_16X16X128_FP8_BF8_w32_twoaddr:
454 case AMDGPU::V_WMMA_F16_16X16X128_FP8_FP8_w32_threeaddr:
455 case AMDGPU::V_WMMA_F16_16X16X128_FP8_FP8_w32_twoaddr:
456 case AMDGPU::V_WMMA_F32_16X16X128_BF8_BF8_w32_threeaddr:
457 case AMDGPU::V_WMMA_F32_16X16X128_BF8_BF8_w32_twoaddr:
458 case AMDGPU::V_WMMA_F32_16X16X128_BF8_FP8_w32_threeaddr:
459 case AMDGPU::V_WMMA_F32_16X16X128_BF8_FP8_w32_twoaddr:
460 case AMDGPU::V_WMMA_F32_16X16X128_FP8_BF8_w32_threeaddr:
461 case AMDGPU::V_WMMA_F32_16X16X128_FP8_BF8_w32_twoaddr:
462 case AMDGPU::V_WMMA_F32_16X16X128_FP8_FP8_w32_threeaddr:
463 case AMDGPU::V_WMMA_F32_16X16X128_FP8_FP8_w32_twoaddr:
464 return CoExecInfo::build(10, "0EEIEEIIVV");
465
466 // 32x16x128 F4: 8-cycle occupancy, 10-cycle window.
467 case AMDGPU::V_WMMA_F32_32X16X128_F4_w32_threeaddr:
468 case AMDGPU::V_WMMA_F32_32X16X128_F4_w32_twoaddr:
469 case AMDGPU::V_WMMA_SCALE16_F32_32X16X128_F4_w32_threeaddr:
470 case AMDGPU::V_WMMA_SCALE16_F32_32X16X128_F4_w32_twoaddr:
471 case AMDGPU::V_WMMA_SCALE_F32_32X16X128_F4_w32_threeaddr:
472 case AMDGPU::V_WMMA_SCALE_F32_32X16X128_F4_w32_twoaddr:
473 return CoExecInfo::build(10, HasScaling ? "0EEIEIESVV" : "0EEIEIEIVV");
474
475 default:
476 // Permissive window for variants without a modeled slot pattern.
477 return CoExecInfo::build(9, "AAAAAAAAA");
478 }
479}
480
481} // namespace AMDGPU
482} // namespace llvm
483
484#endif // LLVM_LIB_TARGET_AMDGPU_AMDGPUCOEXECINFO_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define T
Interface definition for SIInstrInfo.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
CoExecMask
Bitmask for instruction types allowed to co-execute at a stage.
const char * getCoExecMaskName(CoExecMaskT Mask)
Return a human-readable name for a mask holding a single instruction class, as produced by getCoExecM...
InstructionFlavor
Classification of instructions by execution characteristics.
constexpr unsigned MaxCoExecStages
Max stages: INT8 16x16x64 = 17 cycles, round up for safety.
bool getHasMatrixScale(unsigned Opc)
const char * getStageTypeName(CoExecStageType T)
CoExecInfo getMFMACoExecInfo(unsigned Opcode)
Get co-execution info for a gfx950 MFMA instruction.
CoExecMask CoExecMaskT
constexpr StringRef getFlavorName(InstructionFlavor F)
CoExecStageType
Stage type for co-execution (for annotation/display).
CoExecInfo getCoExecInfo(const MachineInstr &MI, const SIInstrInfo &TII)
Get co-execution info for a WMMA instruction, selecting the per-cycle slot pattern from the opcode (a...
InstructionFlavor classifyFlavor(const MachineInstr &MI, const SIInstrInfo &SII)
Classify MI into the execution flavor that drives both the scheduler's slot preferences and the hazar...
constexpr CoExecMaskT getCoExecMask(InstructionFlavor F)
Map a flavor to the co-execution class it occupies in a window slot.
This is an optimization pass for GlobalISel generic memory operations.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
Co-execution characteristics for a multi-cycle instruction.
CoExecStageType getType(unsigned Stage) const
Get stage type for a specific stage.
static CoExecInfo build(unsigned TotalWindow, const char *Pattern)
Build a CoExecInfo from a pattern string.
CoExecMaskT getMask(unsigned Stage) const
Get capability mask for a stage.
unsigned TotalWindow
Number of cycles in the co-execution window, counting any trailing vacant stages.
unsigned getStallCycles(CoExecMaskT InstMask, unsigned Stage) const
Return the number of cycles an instruction matching InstMask must wait at Stage.
bool canCoExec(CoExecMaskT InstMask, unsigned Stage) const
Check if an instruction class mask can co-execute at a given stage.
StringRef Pattern
Pattern string for display (e.g., "0EIIEEIIV").
CoExecInfo()
Default constructor - initialize to safe defaults.
std::optional< unsigned > findNextAllowedStage(CoExecMaskT InstMask, unsigned FromStage) const
Find next stage where the instruction class is allowed.
static CoExecStageType getStageType(CoExecMaskT Mask)
Get stage type from mask for display.
CoExecSlotInfo Slots[MaxCoExecStages]
Per-stage slot info (capability mask).
Per-slot info: which instruction classes may co-execute here.