xref: /llvm-project/llvm/lib/CodeGen/MachineConvergenceVerifier.cpp (revision 60822637bf007cbaf7401a6ec25cdf2ea7b7edbd)
1 //===- MachineConvergenceVerifier.cpp - Verify convergencectrl ------------===//
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 
10 #include "llvm/CodeGen/MachineConvergenceVerifier.h"
11 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
12 #include "llvm/CodeGen/MachineDominators.h"
13 #include "llvm/CodeGen/MachineRegisterInfo.h"
14 #include "llvm/CodeGen/MachineSSAContext.h"
15 #include "llvm/IR/GenericConvergenceVerifierImpl.h"
16 
17 using namespace llvm;
18 
19 template <>
20 auto GenericConvergenceVerifier<MachineSSAContext>::getConvOp(
21     const MachineInstr &MI) -> ConvOpKind {
22   switch (MI.getOpcode()) {
23   default:
24     return CONV_NONE;
25   case TargetOpcode::CONVERGENCECTRL_ENTRY:
26     return CONV_ENTRY;
27   case TargetOpcode::CONVERGENCECTRL_ANCHOR:
28     return CONV_ANCHOR;
29   case TargetOpcode::CONVERGENCECTRL_LOOP:
30     return CONV_LOOP;
31   }
32 }
33 
34 template <>
35 void GenericConvergenceVerifier<
36     MachineSSAContext>::checkConvergenceTokenProduced(const MachineInstr &MI) {
37   Check(!MI.hasImplicitDef(),
38         "Convergence control tokens are defined explicitly.",
39         {Context.print(&MI)});
40   const MachineOperand &Def = MI.getOperand(0);
41   const MachineRegisterInfo &MRI = Context.getFunction()->getRegInfo();
42   Check(MRI.getUniqueVRegDef(Def.getReg()),
43         "Convergence control tokens must have unique definitions.",
44         {Context.print(&MI)});
45 }
46 
47 template <>
48 const MachineInstr *
49 GenericConvergenceVerifier<MachineSSAContext>::findAndCheckConvergenceTokenUsed(
50     const MachineInstr &MI) {
51   const MachineRegisterInfo &MRI = Context.getFunction()->getRegInfo();
52   const MachineInstr *TokenDef = nullptr;
53 
54   for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
55     const MachineOperand &MO = MI.getOperand(I);
56     if (!MO.isReg() || !MO.isUse())
57       continue;
58     Register OpReg = MO.getReg();
59     if (!OpReg.isVirtual())
60       continue;
61 
62     const MachineInstr *Def = MRI.getUniqueVRegDef(OpReg);
63     if (!Def)
64       continue;
65     if (getConvOp(*Def) == CONV_NONE)
66       continue;
67 
68     CheckOrNull(
69         MI.isConvergent(),
70         "Convergence control tokens can only be used by convergent operations.",
71         {Context.print(OpReg), Context.print(&MI)});
72 
73     CheckOrNull(!TokenDef,
74                 "An operation can use at most one convergence control token.",
75                 {Context.print(OpReg), Context.print(&MI)});
76 
77     TokenDef = Def;
78   }
79 
80   if (TokenDef)
81     Tokens[&MI] = TokenDef;
82 
83   return TokenDef;
84 }
85 
86 template <>
87 bool GenericConvergenceVerifier<MachineSSAContext>::isInsideConvergentFunction(
88     const MachineInstr &MI) {
89   // The class MachineFunction does not have any property to indicate whether it
90   // is convergent. Trivially return true so that the check always passes.
91   return true;
92 }
93 
94 template <>
95 bool GenericConvergenceVerifier<MachineSSAContext>::isConvergent(
96     const MachineInstr &MI) {
97   return MI.isConvergent();
98 }
99 
100 template class llvm::GenericConvergenceVerifier<MachineSSAContext>;
101