[llvm] [InstCombine] Drop nonnull assumes if the pointer is already known to be nonnull (PR #180434)

Nikolas Klauser via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 9 03:25:55 PST 2026


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/180434

>From 547222c44ef5746d8693f79c347690ab64ac3730 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sun, 8 Feb 2026 20:30:05 +0100
Subject: [PATCH] [InstCombine] Drop nonnull assumes if the pointer is already
 known to be nonnull

---
 .../InstCombine/InstCombineCalls.cpp          | 10 +++++
 .../ValueTracking/assume-queries-counter.ll   | 11 +++---
 llvm/test/Transforms/InstCombine/assume.ll    | 37 +++++++++++++++++++
 .../d83507-knowledge-retention-bug.ll         |  1 -
 4 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 7be083c2ebbd7..90bbd102868c5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -3671,6 +3671,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
           continue;
         return CallBase::removeOperandBundle(II, OBU.getTagID());
       }
+
+      if (OBU.getTagName() == "nonnull" && OBU.Inputs.size() == 1) {
+        RetainedKnowledge RK = getKnowledgeFromOperandInAssume(
+            *cast<AssumeInst>(II), II->arg_size() + Idx);
+        if (!RK || RK.AttrKind != Attribute::NonNull ||
+            !isKnownNonZero(RK.WasOn,
+                            getSimplifyQuery().getWithInstruction(II)))
+          continue;
+        return CallBase::removeOperandBundle(II, OBU.getTagID());
+      }
     }
 
     // Convert nonnull assume like:
diff --git a/llvm/test/Analysis/ValueTracking/assume-queries-counter.ll b/llvm/test/Analysis/ValueTracking/assume-queries-counter.ll
index 754e43d327f50..0cb8279f3db38 100644
--- a/llvm/test/Analysis/ValueTracking/assume-queries-counter.ll
+++ b/llvm/test/Analysis/ValueTracking/assume-queries-counter.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
 
-; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=0 -S | FileCheck %s --check-prefixes=COUNTER1
-; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=1-2 -S | FileCheck %s --check-prefixes=COUNTER2
-; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=2-6 -S | FileCheck %s --check-prefixes=COUNTER3
+; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=1 -S | FileCheck %s --check-prefixes=COUNTER1
+; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=2-3 -S | FileCheck %s --check-prefixes=COUNTER2
+; RUN: opt < %s -passes=instcombine --debug-counter=assume-queries-counter=4-7 -S | FileCheck %s --check-prefixes=COUNTER3
 
 declare i1 @get_val()
 declare void @llvm.assume(i1)
@@ -38,8 +38,9 @@ define dso_local i1 @test2(ptr readonly %0) {
 ; COUNTER2-NEXT:    ret i1 false
 ;
 ; COUNTER3-LABEL: @test2(
-; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0:%.*]]) ]
-; COUNTER3-NEXT:    ret i1 false
+; COUNTER3-NEXT:    [[TMP2:%.*]] = icmp eq ptr [[TMP0:%.*]], null
+; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[TMP0]]) ]
+; COUNTER3-NEXT:    ret i1 [[TMP2]]
 ;
   %2 = icmp eq ptr %0, null
   call void @llvm.assume(i1 true) ["nonnull"(ptr %0)]
diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll
index a4c7963df1783..c3a193b9fc6c4 100644
--- a/llvm/test/Transforms/InstCombine/assume.ll
+++ b/llvm/test/Transforms/InstCombine/assume.ll
@@ -419,6 +419,43 @@ define i1 @nonnull5(ptr %a) {
   ret i1 %rval
 }
 
+define void @redundant_nonnull1(ptr nonnull %ptr) {
+; CHECK-LABEL: @redundant_nonnull1(
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr) ]
+  ret void
+}
+
+define void @redundant_nonnull2(ptr %ptr) {
+; CHECK-LABEL: @redundant_nonnull2(
+; CHECK-NEXT:    [[NULL_CMP_NOT:%.*]] = icmp eq ptr [[PTR:%.*]], null
+; CHECK-NEXT:    br i1 [[NULL_CMP_NOT]], label [[FALSE:%.*]], label [[TRUE:%.*]]
+; CHECK:       true:
+; CHECK-NEXT:    ret void
+; CHECK:       false:
+; CHECK-NEXT:    ret void
+;
+  %cmp = icmp ne ptr %ptr, null
+  br i1 %cmp, label %true, label %false
+true:
+  call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr) ]
+  ret void
+
+false:
+  ret void
+}
+
+define void @redundant_nonnull3(ptr %ptr) {
+; CHECK-LABEL: @redundant_nonnull3(
+; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[PTR:%.*]]) ]
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr) ]
+  call void @llvm.assume(i1 true) [ "nonnull"(ptr %ptr) ]
+  ret void
+}
+
 ; PR35846 - https://bugs.llvm.org/show_bug.cgi?id=35846
 
 define i32 @assumption_conflicts_with_known_bits(i32 %a, i32 %b) {
diff --git a/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll b/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll
index e903004461728..61380d5a78c90 100644
--- a/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll
+++ b/llvm/test/Transforms/PhaseOrdering/d83507-knowledge-retention-bug.ll
@@ -13,7 +13,6 @@ define ptr @f1(ptr %i0) {
 ; CHECK-NEXT:    br label %[[LOOP_LATCH:.*]]
 ; CHECK:       [[LOOP_LATCH]]:
 ; CHECK-NEXT:    [[I3:%.*]] = phi ptr [ [[I0]], %[[LOOP_LATCH_LR_PH]] ], [ [[I5:%.*]], %[[LOOP_LATCH]] ]
-; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[I3]]) ]
 ; CHECK-NEXT:    [[I5]] = load ptr, ptr [[I3]], align 8
 ; CHECK-NEXT:    [[I2:%.*]] = icmp eq ptr [[I5]], null
 ; CHECK-NEXT:    br i1 [[I2]], label %[[LOOP_EXIT_CRIT_EDGE:.*]], label %[[LOOP_LATCH]]



More information about the llvm-commits mailing list