Skip to content

[PredicateInfo] Extract information from assume operand bundles#177349

Merged
philnik777 merged 3 commits intollvm:mainfrom
philnik777:predicate_info_operand_bundles
Jan 23, 2026
Merged

[PredicateInfo] Extract information from assume operand bundles#177349
philnik777 merged 3 commits intollvm:mainfrom
philnik777:predicate_info_operand_bundles

Conversation

@philnik777
Copy link
Copy Markdown
Contributor

No description provided.

@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Jan 22, 2026

@llvm/pr-subscribers-llvm-transforms

Author: Nikolas Klauser (philnik777)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/177349.diff

3 Files Affected:

  • (modified) llvm/include/llvm/Transforms/Utils/PredicateInfo.h (+20-2)
  • (modified) llvm/lib/Transforms/Utils/PredicateInfo.cpp (+24-3)
  • (added) llvm/test/Transforms/SCCP/assume-operand-bundles.ll (+128)
diff --git a/llvm/include/llvm/Transforms/Utils/PredicateInfo.h b/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
index 3df3495f84470..4cabfdd167203 100644
--- a/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
+++ b/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
@@ -67,7 +67,7 @@ class Value;
 class IntrinsicInst;
 class raw_ostream;
 
-enum PredicateType { PT_Branch, PT_Assume, PT_Switch };
+enum PredicateType { PT_Branch, PT_Assume, PT_BundleAssume, PT_Switch };
 
 /// Constraint for a predicate of the form "cmp Pred Op, OtherOp", where Op
 /// is the value the constraint applies to (the bitcast result).
@@ -118,7 +118,25 @@ class PredicateAssume : public PredicateBase {
       : PredicateBase(PT_Assume, Op, Condition), AssumeInst(AssumeInst) {}
   PredicateAssume() = delete;
   static bool classof(const PredicateBase *PB) {
-    return PB->Type == PT_Assume;
+    return PB->Type == PT_Assume || PB->Type == PT_BundleAssume;
+  }
+
+protected:
+  PredicateAssume(PredicateType PT, Value *Op, IntrinsicInst *AssumeInst,
+                  Value *Condition)
+      : PredicateBase(PT, Op, Condition), AssumeInst(AssumeInst) {}
+};
+
+class PredicateBundleAssume : public PredicateAssume {
+public:
+  Attribute::AttrKind AttrKind;
+  PredicateBundleAssume(Value *Op, IntrinsicInst *AssumeInst,
+                        Attribute::AttrKind AttrKind)
+      : PredicateAssume(PT_BundleAssume, Op, AssumeInst, nullptr),
+        AttrKind(AttrKind) {}
+
+  static bool classof(const PredicateBase *PB) {
+    return PB->Type == PT_BundleAssume;
   }
 };
 
diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
index 27fed7340411b..1fa3195695fd6 100644
--- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp
+++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/AssumeBundleQueries.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/IR/AssemblyAnnotationWriter.h"
 #include "llvm/IR/Dominators.h"
@@ -217,7 +218,7 @@ class PredicateInfoBuilder {
   ValueInfo &getOrCreateValueInfo(Value *);
   const ValueInfo &getValueInfo(Value *) const;
 
-  void processAssume(IntrinsicInst *, BasicBlock *,
+  void processAssume(AssumeInst *, BasicBlock *,
                      SmallVectorImpl<Value *> &OpsToRename);
   void processBranch(BranchInst *, BasicBlock *,
                      SmallVectorImpl<Value *> &OpsToRename);
@@ -359,8 +360,20 @@ void PredicateInfoBuilder::addInfoFor(SmallVectorImpl<Value *> &OpsToRename,
 // Process an assume instruction and place relevant operations we want to rename
 // into OpsToRename.
 void PredicateInfoBuilder::processAssume(
-    IntrinsicInst *II, BasicBlock *AssumeBB,
+    AssumeInst *II, BasicBlock *AssumeBB,
     SmallVectorImpl<Value *> &OpsToRename) {
+  if (II->hasOperandBundles()) {
+    for (auto BOI : II->bundle_op_infos()) {
+      if (RetainedKnowledge RK = getKnowledgeFromBundle(*II, BOI)) {
+        if (RK.AttrKind == Attribute::NonNull)
+          addInfoFor(OpsToRename, RK.WasOn,
+                     new (Allocator) PredicateBundleAssume(RK.WasOn, II,
+                                                           Attribute::NonNull));
+      }
+    }
+    return;
+  }
+
   SmallVector<Value *, 4> Worklist;
   SmallPtrSet<Value *, 4> Visited;
   Worklist.push_back(II->getOperand(0));
@@ -489,7 +502,7 @@ void PredicateInfoBuilder::buildPredicateInfo() {
     }
   }
   for (auto &Assume : AC.assumptions()) {
-    if (auto *II = dyn_cast_or_null<IntrinsicInst>(Assume))
+    if (auto *II = cast_or_null<AssumeInst>(Assume))
       if (DT.isReachableFromEntry(II->getParent()))
         processAssume(II, II->getParent(), OpsToRename);
   }
@@ -712,6 +725,14 @@ PredicateInfo::PredicateInfo(Function &F, DominatorTree &DT,
 
 std::optional<PredicateConstraint> PredicateBase::getConstraint() const {
   switch (Type) {
+  case PT_BundleAssume: {
+    auto *BA = cast<PredicateBundleAssume>(this);
+    assert(BA->AttrKind == Attribute::NonNull &&
+           "Cannot handle anything other than NonNull");
+    return {{CmpInst::ICMP_NE, ConstantPointerNull::get(
+                                   cast<PointerType>(OriginalOp->getType()))}};
+  }
+
   case PT_Assume:
   case PT_Branch: {
     bool TrueEdge = true;
diff --git a/llvm/test/Transforms/SCCP/assume-operand-bundles.ll b/llvm/test/Transforms/SCCP/assume-operand-bundles.ll
new file mode 100644
index 0000000000000..6f86fc331422d
--- /dev/null
+++ b/llvm/test/Transforms/SCCP/assume-operand-bundles.ll
@@ -0,0 +1,128 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt %s -passes=sccp -S | FileCheck %s
+
+declare void @use(i1)
+declare void @llvm.assume(i1)
+
+define void @nonnull(ptr %v) {
+; CHECK-LABEL: define void @nonnull(
+; CHECK-SAME: ptr [[V:%.*]]) {
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[V]]) ]
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.assume(i1 true) [ "nonnull"(ptr %v) ]
+  %c1 = icmp eq ptr %v, null
+  call void @use(i1 %c1)
+  %c2 = icmp ne ptr %v, null
+  call void @use(i1 %c2)
+  %c3 = icmp eq ptr null, %v
+  call void @use(i1 %c3)
+  %c4 = icmp ne ptr null, %v
+  call void @use(i1 %c4)
+  ret void
+}
+
+define void @nonnull_after_branch(i1 %cond1, i1 %cond2, ptr %v) {
+; CHECK-LABEL: define void @nonnull_after_branch(
+; CHECK-SAME: i1 [[COND1:%.*]], i1 [[COND2:%.*]], ptr [[V:%.*]]) {
+; CHECK-NEXT:    [[C1:%.*]] = icmp eq ptr [[V]], null
+; CHECK-NEXT:    call void @use(i1 [[C1]])
+; CHECK-NEXT:    [[C2:%.*]] = icmp ne ptr [[V]], null
+; CHECK-NEXT:    call void @use(i1 [[C2]])
+; CHECK-NEXT:    [[C3:%.*]] = icmp eq ptr null, [[V]]
+; CHECK-NEXT:    call void @use(i1 [[C3]])
+; CHECK-NEXT:    [[C4:%.*]] = icmp ne ptr null, [[V]]
+; CHECK-NEXT:    call void @use(i1 [[C4]])
+; CHECK-NEXT:    br i1 [[COND1]], label %[[TRUE:.*]], label %[[FALSE1:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[V]]) ]
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    br i1 [[COND2]], label %[[TRUE2:.*]], label %[[FALSE:.*]]
+; CHECK:       [[TRUE2]]:
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
+; CHECK:       [[FALSE]]:
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    call void @use(i1 false)
+; CHECK-NEXT:    call void @use(i1 true)
+; CHECK-NEXT:    ret void
+; CHECK:       [[FALSE1]]:
+; CHECK-NEXT:    [[CF1:%.*]] = icmp eq ptr [[V]], null
+; CHECK-NEXT:    call void @use(i1 [[CF1]])
+; CHECK-NEXT:    [[CF2:%.*]] = icmp ne ptr [[V]], null
+; CHECK-NEXT:    call void @use(i1 [[CF2]])
+; CHECK-NEXT:    [[CF3:%.*]] = icmp eq ptr null, [[V]]
+; CHECK-NEXT:    call void @use(i1 [[CF3]])
+; CHECK-NEXT:    [[CF4:%.*]] = icmp ne ptr null, [[V]]
+; CHECK-NEXT:    call void @use(i1 [[CF4]])
+; CHECK-NEXT:    ret void
+;
+
+  %c1 = icmp eq ptr %v, null
+  call void @use(i1 %c1)
+  %c2 = icmp ne ptr %v, null
+  call void @use(i1 %c2)
+  %c3 = icmp eq ptr null, %v
+  call void @use(i1 %c3)
+  %c4 = icmp ne ptr null, %v
+  call void @use(i1 %c4)
+  br i1 %cond1, label %true1, label %false1
+
+true1:
+  call void @llvm.assume(i1 true) [ "nonnull"(ptr %v) ]
+  %ct1 = icmp eq ptr %v, null
+  call void @use(i1 %ct1)
+  %ct2 = icmp ne ptr %v, null
+  call void @use(i1 %ct2)
+  %ct3 = icmp eq ptr null, %v
+  call void @use(i1 %ct3)
+  %ct4 = icmp ne ptr null, %v
+  call void @use(i1 %ct4)
+  br i1 %cond2, label %true2, label %false2
+
+true2:
+  %ctt1 = icmp eq ptr %v, null
+  call void @use(i1 %ctt1)
+  %ctt2 = icmp ne ptr %v, null
+  call void @use(i1 %ctt2)
+  %ctt3 = icmp eq ptr null, %v
+  call void @use(i1 %ctt3)
+  %ctt4 = icmp ne ptr null, %v
+  call void @use(i1 %ctt4)
+  ret void
+
+false2:
+  %ctf1 = icmp eq ptr %v, null
+  call void @use(i1 %ctf1)
+  %ctf2 = icmp ne ptr %v, null
+  call void @use(i1 %ctf2)
+  %ctf3 = icmp eq ptr null, %v
+  call void @use(i1 %ctf3)
+  %ctf4 = icmp ne ptr null, %v
+  call void @use(i1 %ctf4)
+  ret void
+
+
+false1:
+  %cf1 = icmp eq ptr %v, null
+  call void @use(i1 %cf1)
+  %cf2 = icmp ne ptr %v, null
+  call void @use(i1 %cf2)
+  %cf3 = icmp eq ptr null, %v
+  call void @use(i1 %cf3)
+  %cf4 = icmp ne ptr null, %v
+  call void @use(i1 %cf4)
+  ret void
+  ret void
+}

@philnik777 philnik777 requested a review from nikic January 22, 2026 12:37
Comment thread llvm/test/Transforms/SCCP/assume-operand-bundles.ll
Comment thread llvm/include/llvm/Transforms/Utils/PredicateInfo.h
@github-actions
Copy link
Copy Markdown

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff origin/main HEAD --extensions cpp,h -- llvm/include/llvm/Transforms/Utils/PredicateInfo.h llvm/lib/Transforms/Scalar/NewGVN.cpp llvm/lib/Transforms/Utils/PredicateInfo.cpp --diff_from_common_commit

⚠️
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing origin/main to the base branch/commit you want to compare against.
⚠️

View the diff from clang-format here.
diff --git a/llvm/include/llvm/Transforms/Utils/PredicateInfo.h b/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
index 306f512cd..986a64e91 100644
--- a/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
+++ b/llvm/include/llvm/Transforms/Utils/PredicateInfo.h
@@ -67,7 +67,12 @@ class Value;
 class IntrinsicInst;
 class raw_ostream;
 
-enum PredicateType { PT_Branch, PT_ConditionAssume, PT_BundleAssume, PT_Switch };
+enum PredicateType {
+  PT_Branch,
+  PT_ConditionAssume,
+  PT_BundleAssume,
+  PT_Switch
+};
 
 /// Constraint for a predicate of the form "cmp Pred Op, OtherOp", where Op
 /// is the value the constraint applies to (the bitcast result).
diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
index d500708d1..df32482f9 100644
--- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp
+++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp
@@ -846,7 +846,7 @@ public:
         OS << "]";
       } else if (const auto *PA = dyn_cast<PredicateAssume>(PI)) {
         OS << "; assume predicate info {";
-        if (auto * PBA = dyn_cast<PredicateBundleAssume>(PA)) {
+        if (auto *PBA = dyn_cast<PredicateBundleAssume>(PA)) {
           OS << " Attribute: " << Attribute::getNameFromAttrKind(PBA->AttrKind);
         } else {
           assert(isa<PredicateConditionAssume>(PA));

Copy link
Copy Markdown
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@philnik777 philnik777 merged commit 17a17fa into llvm:main Jan 23, 2026
8 of 11 checks passed
@philnik777 philnik777 deleted the predicate_info_operand_bundles branch January 23, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants