[llvm] 0cb6d2f - [LLVM][Convergence] further refactor convergence verifier
Sameer Sahasrabuddhe via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 22 23:32:48 PDT 2023
Author: Sameer Sahasrabuddhe
Date: 2023-08-23T12:02:30+05:30
New Revision: 0cb6d2f643b21c084c4659d4edf41e57ca7fdd5f
URL: https://github.com/llvm/llvm-project/commit/0cb6d2f643b21c084c4659d4edf41e57ca7fdd5f
DIFF: https://github.com/llvm/llvm-project/commit/0cb6d2f643b21c084c4659d4edf41e57ca7fdd5f.diff
LOG: [LLVM][Convergence] further refactor convergence verifier
This is in preparation for using the same convergence verifier for both LLVM IR
and Machine IR.
Reviewed By: yassingh
Differential Revision: https://reviews.llvm.org/D158394
Added:
Modified:
llvm/include/llvm/ADT/GenericConvergenceVerifier.h
llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h
llvm/lib/IR/ConvergenceVerifier.cpp
llvm/lib/IR/Verifier.cpp
llvm/test/Verifier/convergencectrl-invalid.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/ADT/GenericConvergenceVerifier.h b/llvm/include/llvm/ADT/GenericConvergenceVerifier.h
index 5dcb59fa6de6a5..e35fac7f2e99c2 100644
--- a/llvm/include/llvm/ADT/GenericConvergenceVerifier.h
+++ b/llvm/include/llvm/ADT/GenericConvergenceVerifier.h
@@ -63,9 +63,9 @@ template <typename ContextT> class GenericConvergenceVerifier {
// and not the token values.
DenseMap<const InstructionT *, const InstructionT *> Tokens;
+ static bool isInsideConvergentFunction(const InstructionT &I);
+ static bool isConvergent(const InstructionT &I);
const InstructionT *findAndCheckConvergenceTokenUsed(const InstructionT &I);
- bool isControlledConvergent(const InstructionT &I);
- bool isConvergent(const InstructionT &I) const;
void reportFailure(const Twine &Message, ArrayRef<Printable> Values);
};
diff --git a/llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h b/llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h
index 25dbc6eada3ef1..165896ad9aa646 100644
--- a/llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h
+++ b/llvm/include/llvm/IR/GenericConvergenceVerifierImpl.h
@@ -69,9 +69,44 @@ template <class ContextT> void GenericConvergenceVerifier<ContextT>::clear() {
template <class ContextT>
void GenericConvergenceVerifier<ContextT>::visit(const InstructionT &I) {
- if (isControlledConvergent(I)) {
+ auto ID = ContextT::getIntrinsicID(I);
+ auto *TokenDef = findAndCheckConvergenceTokenUsed(I);
+
+ bool IsCtrlIntrinsic = true;
+
+ switch (ID) {
+ case Intrinsic::experimental_convergence_entry:
+ Check(isInsideConvergentFunction(I),
+ "Entry intrinsic can occur only in a convergent function.",
+ {Context.print(&I)});
+ Check(I.getParent()->isEntryBlock(),
+ "Entry intrinsic can occur only in the entry block.",
+ {Context.print(&I)});
+ Check(I.getParent()->getFirstNonPHI() == &I,
+ "Entry intrinsic can occur only at the start of the basic block.",
+ {Context.print(&I)});
+ LLVM_FALLTHROUGH;
+ case Intrinsic::experimental_convergence_anchor:
+ Check(!TokenDef,
+ "Entry or anchor intrinsic cannot have a convergencectrl token "
+ "operand.",
+ {Context.print(&I)});
+ break;
+ case Intrinsic::experimental_convergence_loop:
+ Check(TokenDef, "Loop intrinsic must have a convergencectrl token operand.",
+ {Context.print(&I)});
+ Check(I.getParent()->getFirstNonPHI() == &I,
+ "Loop intrinsic can occur only at the start of the basic block.",
+ {Context.print(&I)});
+ break;
+ default:
+ IsCtrlIntrinsic = false;
+ break;
+ }
+
+ if (TokenDef || IsCtrlIntrinsic) {
Check(isConvergent(I),
- "Expected convergent attribute on a controlled convergent call.",
+ "Convergence control token can only be used in a convergent call.",
{Context.print(&I)});
Check(ConvergenceKind != UncontrolledConvergence,
"Cannot mix controlled and uncontrolled convergence in the same "
diff --git a/llvm/lib/IR/ConvergenceVerifier.cpp b/llvm/lib/IR/ConvergenceVerifier.cpp
index d7a699ebdba82a..336c202b6f94ce 100644
--- a/llvm/lib/IR/ConvergenceVerifier.cpp
+++ b/llvm/lib/IR/ConvergenceVerifier.cpp
@@ -51,26 +51,18 @@ GenericConvergenceVerifier<SSAContext>::findAndCheckConvergenceTokenUsed(
}
template <>
-bool GenericConvergenceVerifier<SSAContext>::isConvergent(
- const InstructionT &I) const {
- if (auto *CB = dyn_cast<CallBase>(&I)) {
- return CB->isConvergent();
- }
- return false;
+bool GenericConvergenceVerifier<SSAContext>::isInsideConvergentFunction(
+ const InstructionT &I) {
+ auto *F = I.getFunction();
+ return F->isConvergent();
}
template <>
-bool GenericConvergenceVerifier<SSAContext>::isControlledConvergent(
+bool GenericConvergenceVerifier<SSAContext>::isConvergent(
const InstructionT &I) {
- // First find a token and place it in the map.
- if (findAndCheckConvergenceTokenUsed(I))
- return true;
-
- // The entry and anchor intrinsics do not use a token, so we do a broad check
- // here. The loop intrinsic will be checked separately for a missing token.
- if (isConvergenceControlIntrinsic(SSAContext::getIntrinsicID(I)))
- return true;
-
+ if (auto *CB = dyn_cast<CallBase>(&I)) {
+ return CB->isConvergent();
+ }
return false;
}
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 116651c8365e8e..a855b7c8fa6577 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5927,23 +5927,10 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
break;
}
case Intrinsic::experimental_convergence_entry:
- Check(Call.getFunction()->isConvergent(),
- "Entry intrinsic can occur only in a convergent function.", &Call);
- Check(Call.getParent()->isEntryBlock(),
- "Entry intrinsic must occur in the entry block.", &Call);
- Check(Call.getParent()->getFirstNonPHI() == &Call,
- "Entry intrinsic must occur at the start of the basic block.", &Call);
LLVM_FALLTHROUGH;
case Intrinsic::experimental_convergence_anchor:
- Check(!Call.getOperandBundle(LLVMContext::OB_convergencectrl),
- "Entry or anchor intrinsic must not have a convergencectrl bundle.",
- &Call);
break;
case Intrinsic::experimental_convergence_loop:
- Check(Call.getOperandBundle(LLVMContext::OB_convergencectrl),
- "Loop intrinsic must have a convergencectrl bundle.", &Call);
- Check(Call.getParent()->getFirstNonPHI() == &Call,
- "Loop intrinsic must occur at the start of the basic block.", &Call);
break;
};
diff --git a/llvm/test/Verifier/convergencectrl-invalid.ll b/llvm/test/Verifier/convergencectrl-invalid.ll
index d488067e9d09a7..63591e0316208a 100644
--- a/llvm/test/Verifier/convergencectrl-invalid.ll
+++ b/llvm/test/Verifier/convergencectrl-invalid.ll
@@ -1,8 +1,8 @@
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
-; CHECK: Entry or anchor intrinsic must not have a convergencectrl bundle.
+; CHECK: Entry or anchor intrinsic cannot have a convergencectrl token operand.
; CHECK-NEXT: %t04_tok2 = call token
-; CHECK: Loop intrinsic must have a convergencectrl bundle.
+; CHECK: Loop intrinsic must have a convergencectrl token operand.
; CHECK-NEXT: %t04_tok3 = call token
define void @basic_syntax() {
%t04_tok1 = call token @llvm.experimental.convergence.anchor()
@@ -20,7 +20,7 @@ define void @wrong_token() {
ret void
}
-; CHECK: Expected convergent attribute on a controlled convergent call.
+; CHECK: Convergence control token can only be used in a convergent call.
; CHECK-NEXT call void @g(){{.*}}%t05_tok1
define void @missing.attribute() {
%t05_tok1 = call token @llvm.experimental.convergence.anchor()
@@ -109,7 +109,7 @@ B:
br label %B
}
-; CHECK: Entry intrinsic must occur at the start of the basic block.
+; CHECK: Entry intrinsic can occur only at the start of the basic block.
; CHECK: %t60_tok1
define void @entry_at_start(i32 %x, i32 %y) convergent {
%z = add i32 %x, %y
@@ -124,7 +124,7 @@ define void @entry_in_convergent(i32 %x, i32 %y) {
ret void
}
-; CHECK: Loop intrinsic must occur at the start of the basic block.
+; CHECK: Loop intrinsic can occur only at the start of the basic block.
; CHECK: %t60_tok3
define void @loop_at_start(i32 %x, i32 %y) convergent {
A:
@@ -136,7 +136,7 @@ B:
ret void
}
-; CHECK: Entry intrinsic must occur in the entry block.
+; CHECK: Entry intrinsic can occur only in the entry block.
; CHECK: %t60_tok4
define void @entry_at_entry(i32 %x, i32 %y) convergent {
A:
More information about the llvm-commits
mailing list