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 | |
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 | |
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 | |