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