[PredicateInfo] Extract information from assume operand bundles#177349
Merged
philnik777 merged 3 commits intollvm:mainfrom Jan 23, 2026
Merged
[PredicateInfo] Extract information from assume operand bundles#177349philnik777 merged 3 commits intollvm:mainfrom
philnik777 merged 3 commits intollvm:mainfrom
Conversation
Member
|
@llvm/pr-subscribers-llvm-transforms Author: Nikolas Klauser (philnik777) Changes3 Files Affected:
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
+}
|
nikic
reviewed
Jan 22, 2026
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
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));
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.