[llvm] [InstCombine] Always fold nonnull assumptions into operand bundles (PR #169923)
Nikolas Klauser via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 9 04:18:56 PST 2026
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/169923
>From f758b9c1ffc8e96ae84f039b1d757cffda0ddb23 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Fri, 28 Nov 2025 15:19:48 +0100
Subject: [PATCH] [InstCombine] Always fold assumes to use operand bundles
---
.../InstCombine/InstCombineCalls.cpp | 3 +-
.../InstCombine/assume-icmp-null-select.ll | 3 +-
.../InstCombine/assume-loop-align.ll | 1 -
llvm/test/Transforms/InstCombine/assume.ll | 93 ++++++-------------
.../pr98799-inline-simplifycfg-ub.ll | 6 +-
5 files changed, 32 insertions(+), 74 deletions(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 90bbd102868c5..67fc61f2e7fe8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3688,8 +3688,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// call void @llvm.assume(i1 %A)
// into
// call void @llvm.assume(i1 true) [ "nonnull"(i32* %PTR) ]
- if (EnableKnowledgeRetention &&
- match(IIOperand,
+ if (match(IIOperand,
m_SpecificICmp(ICmpInst::ICMP_NE, m_Value(A), m_Zero())) &&
A->getType()->isPointerTy()) {
if (auto *Replacement = buildAssumeFromKnowledge(
diff --git a/llvm/test/Transforms/InstCombine/assume-icmp-null-select.ll b/llvm/test/Transforms/InstCombine/assume-icmp-null-select.ll
index 108ee8cf80755..38475816f17f7 100644
--- a/llvm/test/Transforms/InstCombine/assume-icmp-null-select.ll
+++ b/llvm/test/Transforms/InstCombine/assume-icmp-null-select.ll
@@ -24,8 +24,7 @@ define ptr @example2(ptr %x) {
; CHECK-NEXT: [[Y:%.*]] = load ptr, ptr [[X:%.*]], align 8
; CHECK-NEXT: [[Y_IS_NULL:%.*]] = icmp eq ptr [[Y]], null
; CHECK-NEXT: [[RES:%.*]] = select i1 [[Y_IS_NULL]], ptr null, ptr [[X]]
-; CHECK-NEXT: [[NONNULL:%.*]] = icmp ne ptr [[RES]], null
-; CHECK-NEXT: call void @llvm.assume(i1 [[NONNULL]])
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[RES]]) ]
; CHECK-NEXT: ret ptr [[RES]]
;
%y = load ptr, ptr %x, align 8
diff --git a/llvm/test/Transforms/InstCombine/assume-loop-align.ll b/llvm/test/Transforms/InstCombine/assume-loop-align.ll
index 7669d5bae5b08..f6805ba4894f0 100644
--- a/llvm/test/Transforms/InstCombine/assume-loop-align.ll
+++ b/llvm/test/Transforms/InstCombine/assume-loop-align.ll
@@ -60,4 +60,3 @@ declare void @llvm.assume(i1) #1
attributes #0 = { nounwind uwtable }
attributes #1 = { nounwind }
-
diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll
index c3a193b9fc6c4..ebff4fec11ab5 100644
--- a/llvm/test/Transforms/InstCombine/assume.ll
+++ b/llvm/test/Transforms/InstCombine/assume.ll
@@ -339,28 +339,16 @@ define i1 @nonnull2(ptr %a) {
; if the assume is control dependent on something else
define i1 @nonnull3(ptr %a, i1 %control) {
-; FIXME: in the BUNDLES version we could duplicate the load and keep the assume nonnull.
-; DEFAULT-LABEL: @nonnull3(
-; DEFAULT-NEXT: entry:
-; DEFAULT-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
-; DEFAULT-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
-; DEFAULT-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
-; DEFAULT: taken:
-; DEFAULT-NEXT: tail call void @llvm.assume(i1 [[CMP]])
-; DEFAULT-NEXT: ret i1 false
-; DEFAULT: not_taken:
-; DEFAULT-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
-; DEFAULT-NEXT: ret i1 [[RVAL_2]]
-;
-; BUNDLES-LABEL: @nonnull3(
-; BUNDLES-NEXT: entry:
-; BUNDLES-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
-; BUNDLES: taken:
-; BUNDLES-NEXT: ret i1 false
-; BUNDLES: not_taken:
-; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
-; BUNDLES-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
-; BUNDLES-NEXT: ret i1 [[RVAL_2]]
+; FIXME: we could duplicate the load and keep the assume nonnull.
+; CHECK-LABEL: @nonnull3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
+; CHECK: taken:
+; CHECK-NEXT: ret i1 false
+; CHECK: not_taken:
+; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
+; CHECK-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
+; CHECK-NEXT: ret i1 [[RVAL_2]]
;
entry:
%load = load ptr, ptr %a
@@ -380,18 +368,11 @@ not_taken:
; interrupted by an exception being thrown
define i1 @nonnull4(ptr %a) {
-; DEFAULT-LABEL: @nonnull4(
-; DEFAULT-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
-; DEFAULT-NEXT: tail call void @escape(ptr [[LOAD]])
-; DEFAULT-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
-; DEFAULT-NEXT: tail call void @llvm.assume(i1 [[CMP]])
-; DEFAULT-NEXT: ret i1 false
-;
-; BUNDLES-LABEL: @nonnull4(
-; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
-; BUNDLES-NEXT: tail call void @escape(ptr [[LOAD]])
-; BUNDLES-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[LOAD]]) ]
-; BUNDLES-NEXT: ret i1 false
+; CHECK-LABEL: @nonnull4(
+; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
+; CHECK-NEXT: tail call void @escape(ptr [[LOAD]])
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[LOAD]]) ]
+; CHECK-NEXT: ret i1 false
;
%load = load ptr, ptr %a
;; This call may throw!
@@ -515,27 +496,15 @@ define i32 @PR40940(<4 x i8> %x) {
}
define i1 @nonnull3A(ptr %a, i1 %control) {
-; DEFAULT-LABEL: @nonnull3A(
-; DEFAULT-NEXT: entry:
-; DEFAULT-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
-; DEFAULT-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
-; DEFAULT: taken:
-; DEFAULT-NEXT: [[CMP:%.*]] = icmp ne ptr [[LOAD]], null
-; DEFAULT-NEXT: call void @llvm.assume(i1 [[CMP]])
-; DEFAULT-NEXT: ret i1 [[CMP]]
-; DEFAULT: not_taken:
-; DEFAULT-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
-; DEFAULT-NEXT: ret i1 [[RVAL_2]]
-;
-; BUNDLES-LABEL: @nonnull3A(
-; BUNDLES-NEXT: entry:
-; BUNDLES-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
-; BUNDLES: taken:
-; BUNDLES-NEXT: ret i1 true
-; BUNDLES: not_taken:
-; BUNDLES-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
-; BUNDLES-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
-; BUNDLES-NEXT: ret i1 [[RVAL_2]]
+; CHECK-LABEL: @nonnull3A(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 [[CONTROL:%.*]], label [[TAKEN:%.*]], label [[NOT_TAKEN:%.*]]
+; CHECK: taken:
+; CHECK-NEXT: ret i1 true
+; CHECK: not_taken:
+; CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[A:%.*]], align 8
+; CHECK-NEXT: [[RVAL_2:%.*]] = icmp sgt ptr [[LOAD]], null
+; CHECK-NEXT: ret i1 [[RVAL_2]]
;
entry:
%load = load ptr, ptr %a
@@ -635,16 +604,10 @@ not_taken:
}
define void @nonnull_only_ephemeral_use(ptr %p) {
-; DEFAULT-LABEL: @nonnull_only_ephemeral_use(
-; DEFAULT-NEXT: [[A:%.*]] = load ptr, ptr [[P:%.*]], align 8
-; DEFAULT-NEXT: [[CMP:%.*]] = icmp ne ptr [[A]], null
-; DEFAULT-NEXT: tail call void @llvm.assume(i1 [[CMP]])
-; DEFAULT-NEXT: ret void
-;
-; BUNDLES-LABEL: @nonnull_only_ephemeral_use(
-; BUNDLES-NEXT: [[A:%.*]] = load ptr, ptr [[P:%.*]], align 8
-; BUNDLES-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[A]]) ]
-; BUNDLES-NEXT: ret void
+; CHECK-LABEL: @nonnull_only_ephemeral_use(
+; CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[P:%.*]], align 8
+; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[A]]) ]
+; CHECK-NEXT: ret void
;
%a = load ptr, ptr %p
%cmp = icmp ne ptr %a, null
diff --git a/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll b/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll
index 5c4ada38bd302..793a2006330fc 100644
--- a/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll
+++ b/llvm/test/Transforms/PhaseOrdering/pr98799-inline-simplifycfg-ub.ll
@@ -34,9 +34,10 @@ define i32 @foo(ptr %arg, i1 %arg1) {
; O2-LABEL: define i32 @foo(
; O2-SAME: ptr captures(none) [[ARG:%.*]], i1 [[ARG1:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
; O2-NEXT: [[BB:.*:]]
-; O2-NEXT: [[I_I:%.*]] = load ptr, ptr [[ARG]], align 8, !nonnull [[META0:![0-9]+]], !noundef [[META0]]
+; O2-NEXT: [[I_I:%.*]] = load ptr, ptr [[ARG]], align 8
; O2-NEXT: [[I3_I:%.*]] = getelementptr inbounds nuw i8, ptr [[I_I]], i64 1
; O2-NEXT: store ptr [[I3_I]], ptr [[ARG]], align 8
+; O2-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[I_I]]) ]
; O2-NEXT: [[I3:%.*]] = load i32, ptr [[I_I]], align 4
; O2-NEXT: ret i32 [[I3]]
;
@@ -49,6 +50,3 @@ bb:
}
declare void @llvm.assume(i1)
-;.
-; O2: [[META0]] = !{}
-;.
More information about the llvm-commits
mailing list