xref: /llvm-project/llvm/lib/CodeGen/MachineConvergenceVerifier.cpp (revision 79889734b940356ab3381423c93ae06f22e772c9)
1 //===- ConvergenceVerifier.cpp - Verify convergence control -----*- 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 
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 const MachineInstr *
36 GenericConvergenceVerifier<MachineSSAContext>::findAndCheckConvergenceTokenUsed(
37     const MachineInstr &MI) {
38   const MachineRegisterInfo &MRI = Context.getFunction()->getRegInfo();
39   const MachineInstr *TokenDef = nullptr;
40 
41   for (const MachineOperand &MO : MI.uses()) {
42     if (!MO.isReg())
43       continue;
44     Register OpReg = MO.getReg();
45     if (!OpReg.isVirtual())
46       continue;
47 
48     const MachineInstr *Def = MRI.getVRegDef(OpReg);
49     if (!Def)
50       continue;
51     if (getConvOp(*Def) == CONV_NONE)
52       continue;
53 
54     CheckOrNull(
55         MI.isConvergent(),
56         "Convergence control tokens can only be used by convergent operations.",
57         {Context.print(OpReg), Context.print(&MI)});
58 
59     CheckOrNull(!TokenDef,
60                 "An operation can use at most one convergence control token.",
61                 {Context.print(OpReg), Context.print(&MI)});
62 
63     TokenDef = Def;
64   }
65 
66   if (TokenDef)
67     Tokens[&MI] = TokenDef;
68 
69   return TokenDef;
70 }
71 
72 template <>
73 bool GenericConvergenceVerifier<MachineSSAContext>::isInsideConvergentFunction(
74     const MachineInstr &MI) {
75   // The class MachineFunction does not have any property to indicate whether it
76   // is convergent. Trivially return true so that the check always passes.
77   return true;
78 }
79 
80 template <>
81 bool GenericConvergenceVerifier<MachineSSAContext>::isConvergent(
82     const MachineInstr &MI) {
83   return MI.isConvergent();
84 }
85 
86 template class llvm::GenericConvergenceVerifier<MachineSSAContext>;
87