xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ADT/GenericConvergenceVerifier.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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