xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/MachineConvergenceVerifier.cpp (revision c6eb7f3fbffd9065ab75a2ed266f1b069fd97e6e)
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 <>
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<
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 *
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 <>
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 <>
94  bool GenericConvergenceVerifier<MachineSSAContext>::isConvergent(
95      const MachineInstr &MI) {
96    return MI.isConvergent();
97  }
98  
99  template class llvm::GenericConvergenceVerifier<MachineSSAContext>;
100