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