15f757f3fSDimitry Andric //===- ConvergenceVerifier.cpp - Verify convergence control -----*- C++ -*-===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric 95f757f3fSDimitry Andric #include "llvm/IR/ConvergenceVerifier.h" 105f757f3fSDimitry Andric #include "llvm/IR/Dominators.h" 115f757f3fSDimitry Andric #include "llvm/IR/GenericConvergenceVerifierImpl.h" 125f757f3fSDimitry Andric #include "llvm/IR/Instructions.h" 135f757f3fSDimitry Andric #include "llvm/IR/SSAContext.h" 145f757f3fSDimitry Andric 155f757f3fSDimitry Andric using namespace llvm; 165f757f3fSDimitry Andric 175f757f3fSDimitry Andric template <> 18*0fca6ea1SDimitry Andric auto GenericConvergenceVerifier<SSAContext>::getConvOp(const Instruction &I) 19*0fca6ea1SDimitry Andric -> ConvOpKind { 20*0fca6ea1SDimitry Andric const auto *CB = dyn_cast<CallBase>(&I); 21*0fca6ea1SDimitry Andric if (!CB) 22*0fca6ea1SDimitry Andric return CONV_NONE; 23*0fca6ea1SDimitry Andric switch (CB->getIntrinsicID()) { 24*0fca6ea1SDimitry Andric default: 25*0fca6ea1SDimitry Andric return CONV_NONE; 26*0fca6ea1SDimitry Andric case Intrinsic::experimental_convergence_anchor: 27*0fca6ea1SDimitry Andric return CONV_ANCHOR; 28*0fca6ea1SDimitry Andric case Intrinsic::experimental_convergence_entry: 29*0fca6ea1SDimitry Andric return CONV_ENTRY; 30*0fca6ea1SDimitry Andric case Intrinsic::experimental_convergence_loop: 31*0fca6ea1SDimitry Andric return CONV_LOOP; 32*0fca6ea1SDimitry Andric } 33*0fca6ea1SDimitry Andric } 34*0fca6ea1SDimitry Andric 35*0fca6ea1SDimitry Andric template <> 36*0fca6ea1SDimitry Andric void GenericConvergenceVerifier<SSAContext>::checkConvergenceTokenProduced( 37*0fca6ea1SDimitry Andric const Instruction &I) { 38*0fca6ea1SDimitry Andric return; 39*0fca6ea1SDimitry Andric } 40*0fca6ea1SDimitry Andric 41*0fca6ea1SDimitry Andric template <> 425f757f3fSDimitry Andric const Instruction * 435f757f3fSDimitry Andric GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed( 445f757f3fSDimitry Andric const Instruction &I) { 455f757f3fSDimitry Andric auto *CB = dyn_cast<CallBase>(&I); 465f757f3fSDimitry Andric if (!CB) 475f757f3fSDimitry Andric return nullptr; 485f757f3fSDimitry Andric 495f757f3fSDimitry Andric unsigned Count = 505f757f3fSDimitry Andric CB->countOperandBundlesOfType(LLVMContext::OB_convergencectrl); 515f757f3fSDimitry Andric CheckOrNull(Count <= 1, 525f757f3fSDimitry Andric "The 'convergencectrl' bundle can occur at most once on a call", 535f757f3fSDimitry Andric {Context.print(CB)}); 545f757f3fSDimitry Andric if (!Count) 555f757f3fSDimitry Andric return nullptr; 565f757f3fSDimitry Andric 575f757f3fSDimitry Andric auto Bundle = CB->getOperandBundle(LLVMContext::OB_convergencectrl); 585f757f3fSDimitry Andric CheckOrNull(Bundle->Inputs.size() == 1 && 595f757f3fSDimitry Andric Bundle->Inputs[0]->getType()->isTokenTy(), 605f757f3fSDimitry Andric "The 'convergencectrl' bundle requires exactly one token use.", 615f757f3fSDimitry Andric {Context.print(CB)}); 625f757f3fSDimitry Andric auto *Token = Bundle->Inputs[0].get(); 635f757f3fSDimitry Andric auto *Def = dyn_cast<Instruction>(Token); 645f757f3fSDimitry Andric 65*0fca6ea1SDimitry Andric CheckOrNull(Def && getConvOp(*Def) != CONV_NONE, 665f757f3fSDimitry Andric "Convergence control tokens can only be produced by calls to the " 675f757f3fSDimitry Andric "convergence control intrinsics.", 685f757f3fSDimitry Andric {Context.print(Token), Context.print(&I)}); 695f757f3fSDimitry Andric 705f757f3fSDimitry Andric if (Def) 715f757f3fSDimitry Andric Tokens[&I] = Def; 725f757f3fSDimitry Andric 735f757f3fSDimitry Andric return Def; 745f757f3fSDimitry Andric } 755f757f3fSDimitry Andric 765f757f3fSDimitry Andric template <> 775f757f3fSDimitry Andric bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction( 78*0fca6ea1SDimitry Andric const Instruction &I) { 795f757f3fSDimitry Andric auto *F = I.getFunction(); 805f757f3fSDimitry Andric return F->isConvergent(); 815f757f3fSDimitry Andric } 825f757f3fSDimitry Andric 835f757f3fSDimitry Andric template <> 845f757f3fSDimitry Andric bool GenericConvergenceVerifier<SSAContext>::isConvergent( 85*0fca6ea1SDimitry Andric const Instruction &I) { 865f757f3fSDimitry Andric if (auto *CB = dyn_cast<CallBase>(&I)) { 875f757f3fSDimitry Andric return CB->isConvergent(); 885f757f3fSDimitry Andric } 895f757f3fSDimitry Andric return false; 905f757f3fSDimitry Andric } 915f757f3fSDimitry Andric 925f757f3fSDimitry Andric template class llvm::GenericConvergenceVerifier<SSAContext>; 93