xref: /freebsd/contrib/llvm-project/llvm/lib/IR/ConvergenceVerifier.cpp (revision 1342eb5a832fa10e689a29faab3acb6054e4778c)
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 #include "llvm/IR/ConvergenceVerifier.h"
10 #include "llvm/IR/Dominators.h"
11 #include "llvm/IR/GenericConvergenceVerifierImpl.h"
12 #include "llvm/IR/Instructions.h"
13 #include "llvm/IR/SSAContext.h"
14 
15 using namespace llvm;
16 
17 template <>
18 auto GenericConvergenceVerifier<SSAContext>::getConvOp(const Instruction &I)
19     -> ConvOpKind {
20   const auto *CB = dyn_cast<CallBase>(&I);
21   if (!CB)
22     return CONV_NONE;
23   switch (CB->getIntrinsicID()) {
24   default:
25     return CONV_NONE;
26   case Intrinsic::experimental_convergence_anchor:
27     return CONV_ANCHOR;
28   case Intrinsic::experimental_convergence_entry:
29     return CONV_ENTRY;
30   case Intrinsic::experimental_convergence_loop:
31     return CONV_LOOP;
32   }
33 }
34 
35 template <>
36 void GenericConvergenceVerifier<SSAContext>::checkConvergenceTokenProduced(
37     const Instruction &I) {}
38 
39 template <>
40 const Instruction *
41 GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed(
42     const Instruction &I) {
43   auto *CB = dyn_cast<CallBase>(&I);
44   if (!CB)
45     return nullptr;
46 
47   unsigned Count =
48       CB->countOperandBundlesOfType(LLVMContext::OB_convergencectrl);
49   CheckOrNull(Count <= 1,
50               "The 'convergencectrl' bundle can occur at most once on a call",
51               {Context.print(CB)});
52   if (!Count)
53     return nullptr;
54 
55   auto Bundle = CB->getOperandBundle(LLVMContext::OB_convergencectrl);
56   CheckOrNull(Bundle->Inputs.size() == 1 &&
57                   Bundle->Inputs[0]->getType()->isTokenTy(),
58               "The 'convergencectrl' bundle requires exactly one token use.",
59               {Context.print(CB)});
60   auto *Token = Bundle->Inputs[0].get();
61   auto *Def = dyn_cast<Instruction>(Token);
62 
63   CheckOrNull(Def && getConvOp(*Def) != CONV_NONE,
64               "Convergence control tokens can only be produced by calls to the "
65               "convergence control intrinsics.",
66               {Context.print(Token), Context.print(&I)});
67 
68   if (Def)
69     Tokens[&I] = Def;
70 
71   return Def;
72 }
73 
74 template <>
75 bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction(
76     const Instruction &I) {
77   auto *F = I.getFunction();
78   return F->isConvergent();
79 }
80 
81 template <>
82 bool GenericConvergenceVerifier<SSAContext>::isConvergent(
83     const Instruction &I) {
84   if (auto *CB = dyn_cast<CallBase>(&I)) {
85     return CB->isConvergent();
86   }
87   return false;
88 }
89 
90 template class llvm::GenericConvergenceVerifier<SSAContext>;
91