xref: /freebsd/contrib/llvm-project/llvm/lib/IR/ConvergenceVerifier.cpp (revision db33c6f3ae9d1231087710068ee4ea5398aacca7)
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   return;
39 }
40 
41 template <>
42 const Instruction *
43 GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed(
44     const Instruction &I) {
45   auto *CB = dyn_cast<CallBase>(&I);
46   if (!CB)
47     return nullptr;
48 
49   unsigned Count =
50       CB->countOperandBundlesOfType(LLVMContext::OB_convergencectrl);
51   CheckOrNull(Count <= 1,
52               "The 'convergencectrl' bundle can occur at most once on a call",
53               {Context.print(CB)});
54   if (!Count)
55     return nullptr;
56 
57   auto Bundle = CB->getOperandBundle(LLVMContext::OB_convergencectrl);
58   CheckOrNull(Bundle->Inputs.size() == 1 &&
59                   Bundle->Inputs[0]->getType()->isTokenTy(),
60               "The 'convergencectrl' bundle requires exactly one token use.",
61               {Context.print(CB)});
62   auto *Token = Bundle->Inputs[0].get();
63   auto *Def = dyn_cast<Instruction>(Token);
64 
65   CheckOrNull(Def && getConvOp(*Def) != CONV_NONE,
66               "Convergence control tokens can only be produced by calls to the "
67               "convergence control intrinsics.",
68               {Context.print(Token), Context.print(&I)});
69 
70   if (Def)
71     Tokens[&I] = Def;
72 
73   return Def;
74 }
75 
76 template <>
77 bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction(
78     const Instruction &I) {
79   auto *F = I.getFunction();
80   return F->isConvergent();
81 }
82 
83 template <>
84 bool GenericConvergenceVerifier<SSAContext>::isConvergent(
85     const Instruction &I) {
86   if (auto *CB = dyn_cast<CallBase>(&I)) {
87     return CB->isConvergent();
88   }
89   return false;
90 }
91 
92 template class llvm::GenericConvergenceVerifier<SSAContext>;
93