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 const Instruction *
findAndCheckConvergenceTokenUsed(const Instruction & I)19 GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed(
20     const Instruction &I) {
21   auto *CB = dyn_cast<CallBase>(&I);
22   if (!CB)
23     return nullptr;
24 
25   unsigned Count =
26       CB->countOperandBundlesOfType(LLVMContext::OB_convergencectrl);
27   CheckOrNull(Count <= 1,
28               "The 'convergencectrl' bundle can occur at most once on a call",
29               {Context.print(CB)});
30   if (!Count)
31     return nullptr;
32 
33   auto Bundle = CB->getOperandBundle(LLVMContext::OB_convergencectrl);
34   CheckOrNull(Bundle->Inputs.size() == 1 &&
35                   Bundle->Inputs[0]->getType()->isTokenTy(),
36               "The 'convergencectrl' bundle requires exactly one token use.",
37               {Context.print(CB)});
38   auto *Token = Bundle->Inputs[0].get();
39   auto *Def = dyn_cast<Instruction>(Token);
40 
41   CheckOrNull(
42       Def && isConvergenceControlIntrinsic(SSAContext::getIntrinsicID(*Def)),
43       "Convergence control tokens can only be produced by calls to the "
44       "convergence control intrinsics.",
45       {Context.print(Token), Context.print(&I)});
46 
47   if (Def)
48     Tokens[&I] = Def;
49 
50   return Def;
51 }
52 
53 template <>
isInsideConvergentFunction(const InstructionT & I)54 bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction(
55     const InstructionT &I) {
56   auto *F = I.getFunction();
57   return F->isConvergent();
58 }
59 
60 template <>
isConvergent(const InstructionT & I)61 bool GenericConvergenceVerifier<SSAContext>::isConvergent(
62     const InstructionT &I) {
63   if (auto *CB = dyn_cast<CallBase>(&I)) {
64     return CB->isConvergent();
65   }
66   return false;
67 }
68 
69 template class llvm::GenericConvergenceVerifier<SSAContext>;
70