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