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 <> getConvOp(const Instruction & I)18auto 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 <> checkConvergenceTokenProduced(const Instruction & I)36void GenericConvergenceVerifier<SSAContext>::checkConvergenceTokenProduced( 37 const Instruction &I) {} 38 39 template <> 40 const Instruction * findAndCheckConvergenceTokenUsed(const Instruction & I)41GenericConvergenceVerifier<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 <> isInsideConvergentFunction(const Instruction & I)75bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction( 76 const Instruction &I) { 77 auto *F = I.getFunction(); 78 return F->isConvergent(); 79 } 80 81 template <> isConvergent(const Instruction & I)82bool 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