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
15using namespace llvm;
16
17template <>
18auto GenericConvergenceVerifier<SSAContext>::getConvOp(const Instruction &I)
19 -> ConvOpKind {
20 const auto *CB = dyn_cast<CallBase>(Val: &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
35template <>
36void GenericConvergenceVerifier<SSAContext>::checkConvergenceTokenProduced(
37 const Instruction &I) {}
38
39template <>
40const Instruction *
41GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed(
42 const Instruction &I) {
43 auto *CB = dyn_cast<CallBase>(Val: &I);
44 if (!CB)
45 return nullptr;
46
47 unsigned Count =
48 CB->countOperandBundlesOfType(ID: 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(ID: 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>(Val: 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
74template <>
75bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction(
76 const Instruction &I) {
77 auto *F = I.getFunction();
78 return F->isConvergent();
79}
80
81template <>
82bool GenericConvergenceVerifier<SSAContext>::isConvergent(
83 const Instruction &I) {
84 if (auto *CB = dyn_cast<CallBase>(Val: &I)) {
85 return CB->isConvergent();
86 }
87 return false;
88}
89
90template class llvm::GenericConvergenceVerifier<SSAContext>;
91