xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/ConvergenceVerifier.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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