[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