[llvm] f7b0951 - [LLVM] Add missing verifier checks for convergence control

Sameer Sahasrabuddhe via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 30 22:38:42 PDT 2023


Author: Sameer Sahasrabuddhe
Date: 2023-07-31T11:08:19+05:30
New Revision: f7b09516e466b5591914f520bdc45f7e0b64409f

URL: https://github.com/llvm/llvm-project/commit/f7b09516e466b5591914f520bdc45f7e0b64409f
DIFF: https://github.com/llvm/llvm-project/commit/f7b09516e466b5591914f520bdc45f7e0b64409f.diff

LOG: [LLVM] Add missing verifier checks for convergence control

Added: 
    

Modified: 
    llvm/lib/IR/Verifier.cpp
    llvm/test/Verifier/convergencectrl-invalid.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index ebd133a4aa61c2..21acb4185f7a8e 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2535,6 +2535,23 @@ void Verifier::verifySiblingFuncletUnwinds() {
   }
 }
 
+static bool isConvergenceControlIntrinsic(const CallBase &Call) {
+  switch (Call.getIntrinsicID()) {
+  case Intrinsic::experimental_convergence_anchor:
+  case Intrinsic::experimental_convergence_entry:
+  case Intrinsic::experimental_convergence_loop:
+    return true;
+  default:
+    return false;
+  }
+}
+
+static bool isControlledConvergent(const CallBase &Call) {
+  if (Call.countOperandBundlesOfType(LLVMContext::OB_convergencectrl))
+    return true;
+  return isConvergenceControlIntrinsic(Call);
+}
+
 void Verifier::verifyConvergenceControl(Function &F) {
   DenseMap<BasicBlock *, SmallVector<CallBase *, 8>> LiveTokenMap;
   DenseMap<const Cycle *, const CallBase *> CycleHearts;
@@ -2552,10 +2569,10 @@ void Verifier::verifyConvergenceControl(Function &F) {
 
     Value *Token = Bundle.Inputs[0].get();
     auto *Def = dyn_cast<CallBase>(Token);
-    Check(Def != nullptr,
-          "Convergence control tokens can only be produced by call "
-          "instructions.",
-          Token);
+    Check(Def && isConvergenceControlIntrinsic(*Def),
+          "Convergence control tokens can only be produced by calls to the "
+          "convergence control intrinsics.",
+          Token, CB);
 
     Check(llvm::is_contained(LiveTokens, Token),
           "Convergence region is not well-nested.", Token, CB);
@@ -2615,6 +2632,9 @@ void Verifier::verifyConvergenceControl(Function &F) {
       if (!CB)
         continue;
 
+      Check(CB->countOperandBundlesOfType(LLVMContext::OB_convergencectrl) <= 1,
+            "The 'convergencetrl' bundle can occur at most once on a call", CB);
+
       auto Bundle = CB->getOperandBundle(LLVMContext::OB_convergencectrl);
       if (Bundle)
         checkBundle(*Bundle, CB, LiveTokens);
@@ -3375,20 +3395,6 @@ void Verifier::visitPHINode(PHINode &PN) {
   visitInstruction(PN);
 }
 
-static bool isControlledConvergent(const CallBase &Call) {
-  if (Call.getOperandBundle(LLVMContext::OB_convergencectrl))
-    return true;
-  if (const auto *F = dyn_cast<Function>(Call.getCalledOperand())) {
-    switch (F->getIntrinsicID()) {
-    case Intrinsic::experimental_convergence_anchor:
-    case Intrinsic::experimental_convergence_entry:
-    case Intrinsic::experimental_convergence_loop:
-      return true;
-    }
-  }
-  return false;
-}
-
 void Verifier::visitCallBase(CallBase &Call) {
   Check(Call.getCalledOperand()->getType()->isPointerTy(),
         "Called function must be a pointer!", Call);

diff  --git a/llvm/test/Verifier/convergencectrl-invalid.ll b/llvm/test/Verifier/convergencectrl-invalid.ll
index a670ee1a905974..532e8d734f06e6 100644
--- a/llvm/test/Verifier/convergencectrl-invalid.ll
+++ b/llvm/test/Verifier/convergencectrl-invalid.ll
@@ -1,5 +1,14 @@
 ; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
 
+; CHECK: Convergence control tokens can only be produced by calls to the convergence control intrinsics.
+; CHECK-NEXT:  %t04_tok1 = call token @produce_token()
+; CHECK-NEXT:  call void @f() [ "convergencectrl"(token %t04_tok1) ]
+define void @wrong_token() {
+  %t04_tok1 = call token @produce_token()
+  call void @f() [ "convergencectrl"(token %t04_tok1) ]
+  ret void
+}
+
 ; CHECK: Expected convergent attribute on a controlled convergent call.
 ; CHECK-NEXT  call void @g(){{.*}}%t05_tok1
 define void @missing.attribute() {
@@ -8,6 +17,24 @@ define void @missing.attribute() {
   ret void
 }
 
+; CHECK: The 'convergencectrl' bundle requires exactly one token use.
+; CHECK-NEXT:  call void @g()
+define void @multiple_tokens() {
+  %t06_tok1 = call token @llvm.experimental.convergence.anchor()
+  %t06_tok2 = call token @llvm.experimental.convergence.anchor()
+  call void @g() [ "convergencectrl"(token %t06_tok2, token %t06_tok1) ]
+  ret void
+}
+
+; CHECK: The 'convergencetrl' bundle can occur at most once on a call
+; CHECK-NEXT:  call void @g()
+define void @multiple_bundles() {
+  %t07_tok1 = call token @llvm.experimental.convergence.anchor()
+  %t07_tok2 = call token @llvm.experimental.convergence.anchor()
+  call void @g() [ "convergencectrl"(token %t07_tok2), "convergencectrl"(token %t07_tok1) ]
+  ret void
+}
+
 ; CHECK: Cannot mix controlled and uncontrolled convergence in the same function
 ; CHECK-NEXT  call void @f()
 define void @mixed1() {
@@ -217,6 +244,8 @@ F:
   ret void
 }
 
+declare token @produce_token()
+
 declare void @f() convergent
 declare void @g()
 


        


More information about the llvm-commits mailing list