xref: /llvm-project/llvm/lib/IR/ConvergenceVerifier.cpp (revision ec34699f750efc5292db503c6700ddeede59ff03)
1bd7a4d7bSSameer Sahasrabuddhe //===- ConvergenceVerifier.cpp - Verify convergence control -----*- C++ -*-===//
2bd7a4d7bSSameer Sahasrabuddhe //
3bd7a4d7bSSameer Sahasrabuddhe // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bd7a4d7bSSameer Sahasrabuddhe // See https://llvm.org/LICENSE.txt for license information.
5bd7a4d7bSSameer Sahasrabuddhe // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bd7a4d7bSSameer Sahasrabuddhe //
7bd7a4d7bSSameer Sahasrabuddhe //===----------------------------------------------------------------------===//
8bd7a4d7bSSameer Sahasrabuddhe 
9bd7a4d7bSSameer Sahasrabuddhe #include "llvm/IR/ConvergenceVerifier.h"
10bd7a4d7bSSameer Sahasrabuddhe #include "llvm/IR/Dominators.h"
11bd7a4d7bSSameer Sahasrabuddhe #include "llvm/IR/GenericConvergenceVerifierImpl.h"
12bd7a4d7bSSameer Sahasrabuddhe #include "llvm/IR/Instructions.h"
13bd7a4d7bSSameer Sahasrabuddhe #include "llvm/IR/SSAContext.h"
14bd7a4d7bSSameer Sahasrabuddhe 
15bd7a4d7bSSameer Sahasrabuddhe using namespace llvm;
16bd7a4d7bSSameer Sahasrabuddhe 
17bd7a4d7bSSameer Sahasrabuddhe template <>
getConvOp(const Instruction & I)1860822637SSameer Sahasrabuddhe auto GenericConvergenceVerifier<SSAContext>::getConvOp(const Instruction &I)
1960822637SSameer Sahasrabuddhe     -> ConvOpKind {
2060822637SSameer Sahasrabuddhe   const auto *CB = dyn_cast<CallBase>(&I);
2160822637SSameer Sahasrabuddhe   if (!CB)
2260822637SSameer Sahasrabuddhe     return CONV_NONE;
2360822637SSameer Sahasrabuddhe   switch (CB->getIntrinsicID()) {
2460822637SSameer Sahasrabuddhe   default:
2560822637SSameer Sahasrabuddhe     return CONV_NONE;
2660822637SSameer Sahasrabuddhe   case Intrinsic::experimental_convergence_anchor:
2760822637SSameer Sahasrabuddhe     return CONV_ANCHOR;
2860822637SSameer Sahasrabuddhe   case Intrinsic::experimental_convergence_entry:
2960822637SSameer Sahasrabuddhe     return CONV_ENTRY;
3060822637SSameer Sahasrabuddhe   case Intrinsic::experimental_convergence_loop:
3160822637SSameer Sahasrabuddhe     return CONV_LOOP;
3260822637SSameer Sahasrabuddhe   }
3360822637SSameer Sahasrabuddhe }
3460822637SSameer Sahasrabuddhe 
3560822637SSameer Sahasrabuddhe template <>
checkConvergenceTokenProduced(const Instruction & I)3660822637SSameer Sahasrabuddhe void GenericConvergenceVerifier<SSAContext>::checkConvergenceTokenProduced(
3760822637SSameer Sahasrabuddhe     const Instruction &I) {
3860822637SSameer Sahasrabuddhe   return;
3960822637SSameer Sahasrabuddhe }
4060822637SSameer Sahasrabuddhe 
4160822637SSameer Sahasrabuddhe template <>
42bd7a4d7bSSameer Sahasrabuddhe const Instruction *
findAndCheckConvergenceTokenUsed(const Instruction & I)43bd7a4d7bSSameer Sahasrabuddhe GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed(
44bd7a4d7bSSameer Sahasrabuddhe     const Instruction &I) {
45bd7a4d7bSSameer Sahasrabuddhe   auto *CB = dyn_cast<CallBase>(&I);
46bd7a4d7bSSameer Sahasrabuddhe   if (!CB)
47bd7a4d7bSSameer Sahasrabuddhe     return nullptr;
48bd7a4d7bSSameer Sahasrabuddhe 
49bd7a4d7bSSameer Sahasrabuddhe   unsigned Count =
50bd7a4d7bSSameer Sahasrabuddhe       CB->countOperandBundlesOfType(LLVMContext::OB_convergencectrl);
51bd7a4d7bSSameer Sahasrabuddhe   CheckOrNull(Count <= 1,
52bd7a4d7bSSameer Sahasrabuddhe               "The 'convergencectrl' bundle can occur at most once on a call",
53bd7a4d7bSSameer Sahasrabuddhe               {Context.print(CB)});
54bd7a4d7bSSameer Sahasrabuddhe   if (!Count)
55bd7a4d7bSSameer Sahasrabuddhe     return nullptr;
56bd7a4d7bSSameer Sahasrabuddhe 
57bd7a4d7bSSameer Sahasrabuddhe   auto Bundle = CB->getOperandBundle(LLVMContext::OB_convergencectrl);
58bd7a4d7bSSameer Sahasrabuddhe   CheckOrNull(Bundle->Inputs.size() == 1 &&
59bd7a4d7bSSameer Sahasrabuddhe                   Bundle->Inputs[0]->getType()->isTokenTy(),
60bd7a4d7bSSameer Sahasrabuddhe               "The 'convergencectrl' bundle requires exactly one token use.",
61bd7a4d7bSSameer Sahasrabuddhe               {Context.print(CB)});
62bd7a4d7bSSameer Sahasrabuddhe   auto *Token = Bundle->Inputs[0].get();
63bd7a4d7bSSameer Sahasrabuddhe   auto *Def = dyn_cast<Instruction>(Token);
64bd7a4d7bSSameer Sahasrabuddhe 
6560822637SSameer Sahasrabuddhe   CheckOrNull(Def && getConvOp(*Def) != CONV_NONE,
66bd7a4d7bSSameer Sahasrabuddhe               "Convergence control tokens can only be produced by calls to the "
67bd7a4d7bSSameer Sahasrabuddhe               "convergence control intrinsics.",
68bd7a4d7bSSameer Sahasrabuddhe               {Context.print(Token), Context.print(&I)});
69bd7a4d7bSSameer Sahasrabuddhe 
70bd7a4d7bSSameer Sahasrabuddhe   if (Def)
71bd7a4d7bSSameer Sahasrabuddhe     Tokens[&I] = Def;
72bd7a4d7bSSameer Sahasrabuddhe 
73bd7a4d7bSSameer Sahasrabuddhe   return Def;
74bd7a4d7bSSameer Sahasrabuddhe }
75bd7a4d7bSSameer Sahasrabuddhe 
76bd7a4d7bSSameer Sahasrabuddhe template <>
isInsideConvergentFunction(const Instruction & I)770cb6d2f6SSameer Sahasrabuddhe bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction(
78*ec34699fSSameer Sahasrabuddhe     const Instruction &I) {
790cb6d2f6SSameer Sahasrabuddhe   auto *F = I.getFunction();
800cb6d2f6SSameer Sahasrabuddhe   return F->isConvergent();
81bd7a4d7bSSameer Sahasrabuddhe }
82bd7a4d7bSSameer Sahasrabuddhe 
83bd7a4d7bSSameer Sahasrabuddhe template <>
isConvergent(const Instruction & I)840cb6d2f6SSameer Sahasrabuddhe bool GenericConvergenceVerifier<SSAContext>::isConvergent(
85*ec34699fSSameer Sahasrabuddhe     const Instruction &I) {
860cb6d2f6SSameer Sahasrabuddhe   if (auto *CB = dyn_cast<CallBase>(&I)) {
870cb6d2f6SSameer Sahasrabuddhe     return CB->isConvergent();
880cb6d2f6SSameer Sahasrabuddhe   }
89bd7a4d7bSSameer Sahasrabuddhe   return false;
90bd7a4d7bSSameer Sahasrabuddhe }
91bd7a4d7bSSameer Sahasrabuddhe 
92bd7a4d7bSSameer Sahasrabuddhe template class llvm::GenericConvergenceVerifier<SSAContext>;
93