26#ifndef LLVM_IR_GENERICCONVERGENCEVERIFIERIMPL_H
27#define LLVM_IR_GENERICCONVERGENCEVERIFIERIMPL_H
34#define Check(C, ...) \
37 reportFailure(__VA_ARGS__); \
42#define CheckOrNull(C, ...) \
45 reportFailure(__VA_ARGS__); \
57template <
class ContextT>
59 SeenFirstConvOp =
false;
62template <
class ContextT>
64 ConvOpKind ConvOp = getConvOp(
I);
66 auto *TokenDef = findAndCheckConvergenceTokenUsed(
I);
69 Check(isInsideConvergentFunction(
I),
70 "Entry intrinsic can occur only in a convergent function.",
72 Check(
I.getParent()->isEntryBlock(),
73 "Entry intrinsic can occur only in the entry block.",
75 Check(!SeenFirstConvOp,
76 "Entry intrinsic cannot be preceded by a convergent operation in the "
82 "Entry or anchor intrinsic cannot have a convergencectrl token "
87 Check(TokenDef,
"Loop intrinsic must have a convergencectrl token operand.",
89 Check(!SeenFirstConvOp,
90 "Loop intrinsic cannot be preceded by a convergent operation in the "
98 if (ConvOp != CONV_NONE)
99 checkConvergenceTokenProduced(
I);
102 SeenFirstConvOp =
true;
104 if (TokenDef || ConvOp != CONV_NONE) {
106 "Cannot mix controlled and uncontrolled convergence in the same "
110 }
else if (isConvergent(
I)) {
112 "Cannot mix controlled and uncontrolled convergence in the same "
119template <
class ContextT>
124 for (
auto V : DumpedValues)
129template <
class ContextT>
132 const auto &
F = *
Context.getFunction();
145 "Convergence control token must dominate all its uses.",
146 {Context.print(Token), Context.print(User)});
149 "Convergence region is not well-nested.",
151 while (LiveTokens.back() != Token)
152 LiveTokens.pop_back();
155 auto *BB =
User->getParent();
156 auto *BBCycle = CI.getCycle(BB);
160 auto *DefBB = Token->getParent();
161 if (DefBB == BB || BBCycle->contains(DefBB)) {
167 "Convergence token used by an instruction other than "
168 "llvm.experimental.convergence.loop in a cycle that does "
169 "not contain the token's definition.",
173 auto *Parent = BBCycle->getParentCycle();
174 if (!Parent || Parent->contains(DefBB))
179 Check(BBCycle->isReducible() && BB == BBCycle->getHeader(),
180 "Cycle heart must dominate all blocks in the cycle.",
181 {Context.print(User), Context.printAsOperand(BB), CI.print(BBCycle)});
183 "Two static convergence token uses in a cycle that does "
184 "not contain either token's definition.",
185 {Context.print(User), Context.print(CycleHearts[BBCycle]),
187 CycleHearts[BBCycle] =
User;
192 for (
auto *BB : RPOT) {
194 auto LTIt = LiveTokenMap.
find(BB);
195 if (LTIt != LiveTokenMap.
end()) {
196 LiveTokens = std::move(LTIt->second);
197 LiveTokenMap.
erase(LTIt);
200 for (
auto &
I : *BB) {
201 if (
auto *Token = Tokens.lookup(&
I))
202 checkToken(Token, &
I, LiveTokens);
203 if (getConvOp(
I) != CONV_NONE)
209 auto *SuccNode = DT.
getNode(Succ);
210 auto [LTIt, Inserted] = LiveTokenMap.
try_emplace(Succ);
214 for (
auto LiveToken : LiveTokens) {
217 LTIt->second.push_back(LiveToken);
222 LTIt->second, [&LiveTokens](
const InstructionT *Token) {
223 return llvm::is_contained(LiveTokens, Token);
225 LTIt->second.erase(It, LTIt->second.end());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
A verifier for the static rules of convergence control tokens that works with both LLVM IR and MIR.
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool erase(const KeyT &Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
typename ContextT::InstructionT InstructionT
typename ContextT::DominatorTreeT DominatorTreeT
typename ContextT::BlockT BlockT
typename ContextT::FunctionT FunctionT
void verify(const DominatorTreeT &DT)
void visit(const BlockT &BB)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
This is an optimization pass for GlobalISel generic memory operations.
auto successors(const MachineBasicBlock *BB)
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.