1 //===- GenericConvergenceVerifier.h ---------------------------*- 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 /// \file 10 /// 11 /// A verifier for the static rules of convergence control tokens that works 12 /// with both LLVM IR and MIR. 13 /// 14 //===----------------------------------------------------------------------===// 15 16 #ifndef LLVM_ADT_GENERICCONVERGENCEVERIFIER_H 17 #define LLVM_ADT_GENERICCONVERGENCEVERIFIER_H 18 19 #include "llvm/ADT/GenericCycleInfo.h" 20 21 namespace llvm { 22 23 template <typename ContextT> class GenericConvergenceVerifier { 24 public: 25 using BlockT = typename ContextT::BlockT; 26 using FunctionT = typename ContextT::FunctionT; 27 using ValueRefT = typename ContextT::ValueRefT; 28 using InstructionT = typename ContextT::InstructionT; 29 using DominatorTreeT = typename ContextT::DominatorTreeT; 30 using CycleInfoT = GenericCycleInfo<ContextT>; 31 using CycleT = typename CycleInfoT::CycleT; 32 initialize(raw_ostream * OS,function_ref<void (const Twine & Message)> FailureCB,const FunctionT & F)33 void initialize(raw_ostream *OS, 34 function_ref<void(const Twine &Message)> FailureCB, 35 const FunctionT &F) { 36 clear(); 37 this->OS = OS; 38 this->FailureCB = FailureCB; 39 Context = ContextT(&F); 40 } 41 42 void clear(); 43 void visit(const BlockT &BB); 44 void visit(const InstructionT &I); 45 void verify(const DominatorTreeT &DT); 46 sawTokens()47 bool sawTokens() const { return ConvergenceKind == ControlledConvergence; } 48 49 private: 50 raw_ostream *OS; 51 std::function<void(const Twine &Message)> FailureCB; 52 DominatorTreeT *DT; 53 CycleInfoT CI; 54 ContextT Context; 55 56 /// Whether the current function has convergencectrl operand bundles. 57 enum { 58 ControlledConvergence, 59 UncontrolledConvergence, 60 NoConvergence 61 } ConvergenceKind = NoConvergence; 62 63 /// The control token operation performed by a convergence control Intrinsic 64 /// in LLVM IR, or by a CONVERGENCECTRL* instruction in MIR 65 enum ConvOpKind { CONV_ANCHOR, CONV_ENTRY, CONV_LOOP, CONV_NONE }; 66 67 // Cache token uses found so far. Note that we track the unique definitions 68 // and not the token values. 69 DenseMap<const InstructionT *, const InstructionT *> Tokens; 70 71 bool SeenFirstConvOp = false; 72 73 static bool isInsideConvergentFunction(const InstructionT &I); 74 static bool isConvergent(const InstructionT &I); 75 static ConvOpKind getConvOp(const InstructionT &I); 76 void checkConvergenceTokenProduced(const InstructionT &I); 77 const InstructionT *findAndCheckConvergenceTokenUsed(const InstructionT &I); 78 79 void reportFailure(const Twine &Message, ArrayRef<Printable> Values); 80 }; 81 82 } // end namespace llvm 83 84 #endif // LLVM_ADT_GENERICCONVERGENCEVERIFIER_H 85