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