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 <>
getConvOp(const MachineInstr & MI)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<
checkConvergenceTokenProduced(const MachineInstr & MI)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 *
findAndCheckConvergenceTokenUsed(const MachineInstr & MI)49 GenericConvergenceVerifier<MachineSSAContext>::findAndCheckConvergenceTokenUsed(
50 const MachineInstr &MI) {
51 const MachineRegisterInfo &MRI = Context.getFunction()->getRegInfo();
52 const MachineInstr *TokenDef = nullptr;
53
54 for (const MachineOperand &MO : MI.operands()) {
55 if (!MO.isReg() || !MO.isUse())
56 continue;
57 Register OpReg = MO.getReg();
58 if (!OpReg.isVirtual())
59 continue;
60
61 const MachineInstr *Def = MRI.getUniqueVRegDef(OpReg);
62 if (!Def)
63 continue;
64 if (getConvOp(*Def) == CONV_NONE)
65 continue;
66
67 CheckOrNull(
68 MI.isConvergent(),
69 "Convergence control tokens can only be used by convergent operations.",
70 {Context.print(OpReg), Context.print(&MI)});
71
72 CheckOrNull(!TokenDef,
73 "An operation can use at most one convergence control token.",
74 {Context.print(OpReg), Context.print(&MI)});
75
76 TokenDef = Def;
77 }
78
79 if (TokenDef)
80 Tokens[&MI] = TokenDef;
81
82 return TokenDef;
83 }
84
85 template <>
isInsideConvergentFunction(const MachineInstr & MI)86 bool GenericConvergenceVerifier<MachineSSAContext>::isInsideConvergentFunction(
87 const MachineInstr &MI) {
88 // The class MachineFunction does not have any property to indicate whether it
89 // is convergent. Trivially return true so that the check always passes.
90 return true;
91 }
92
93 template <>
isConvergent(const MachineInstr & MI)94 bool GenericConvergenceVerifier<MachineSSAContext>::isConvergent(
95 const MachineInstr &MI) {
96 return MI.isConvergent();
97 }
98
99 template class llvm::GenericConvergenceVerifier<MachineSSAContext>;
100