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 Sahasrabuddheauto 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 Sahasrabuddhevoid 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 SahasrabuddheGenericConvergenceVerifier<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 Sahasrabuddhebool 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 Sahasrabuddhebool 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