[llvm] [InstCombine] Simplify the pointer operand of store if writing to null is UB (PR #127979)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 20 07:50:44 PST 2025


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/127979

>From fa7fa3d33b3035b24179fe992ed302e7a75ec6b3 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 20 Feb 2025 17:21:15 +0800
Subject: [PATCH 1/3] [InstCombine] Add pre-commit tests. NFC.

---
 llvm/test/Transforms/InstCombine/store.ll | 44 +++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/store.ll b/llvm/test/Transforms/InstCombine/store.ll
index 673395464c85a..5caf43a3cd6e9 100644
--- a/llvm/test/Transforms/InstCombine/store.ll
+++ b/llvm/test/Transforms/InstCombine/store.ll
@@ -345,6 +345,50 @@ define void @store_to_readonly_noalias(ptr readonly noalias %0) {
   ret void
 }
 
+define void @store_select_with_null(i1 %cond, ptr %p) {
+; CHECK-LABEL: @store_select_with_null(
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr [[P:%.*]], ptr null
+; CHECK-NEXT:    store i32 0, ptr [[SEL]], align 4
+; CHECK-NEXT:    ret void
+;
+  %sel = select i1 %cond, ptr %p, ptr null
+  store i32 0, ptr %sel, align 4
+  ret void
+}
+
+define void @store_select_with_null_commuted(i1 %cond, ptr %p) {
+; CHECK-LABEL: @store_select_with_null_commuted(
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[P:%.*]]
+; CHECK-NEXT:    store i32 0, ptr [[SEL]], align 4
+; CHECK-NEXT:    ret void
+;
+  %sel = select i1 %cond, ptr null, ptr %p
+  store i32 0, ptr %sel, align 4
+  ret void
+}
+
+define void @store_select_with_null_null_is_valid(i1 %cond, ptr %p) null_pointer_is_valid {
+; CHECK-LABEL: @store_select_with_null_null_is_valid(
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr [[P:%.*]], ptr null
+; CHECK-NEXT:    store i32 0, ptr [[SEL]], align 4
+; CHECK-NEXT:    ret void
+;
+  %sel = select i1 %cond, ptr %p, ptr null
+  store i32 0, ptr %sel, align 4
+  ret void
+}
+
+define void @store_select_with_unknown(i1 %cond, ptr %p, ptr %p2) {
+; CHECK-LABEL: @store_select_with_unknown(
+; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr [[P:%.*]], ptr [[P2:%.*]]
+; CHECK-NEXT:    store i32 0, ptr [[SEL]], align 4
+; CHECK-NEXT:    ret void
+;
+  %sel = select i1 %cond, ptr %p, ptr %p2
+  store i32 0, ptr %sel, align 4
+  ret void
+}
+
 !0 = !{!4, !4, i64 0}
 !1 = !{!"omnipotent char", !2}
 !2 = !{!"Simple C/C++ TBAA"}

>From 2d6240eaba08e068c2dbfac051faba3cac6cb81a Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 20 Feb 2025 17:34:40 +0800
Subject: [PATCH 2/3] [InstCombine] Simplify the pointer operand of store if
 writing to null is UB

---
 .../InstCombine/InstCombineLoadStoreAlloca.cpp     | 14 ++++++++++++++
 llvm/test/Transforms/InstCombine/store.ll          |  6 ++----
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
index 4b42e86e25161..d5534c15cca76 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp
@@ -1437,6 +1437,20 @@ Instruction *InstCombinerImpl::visitStoreInst(StoreInst &SI) {
   if (isa<UndefValue>(Val))
     return eraseInstFromFunction(SI);
 
+  // TODO: Add a helper to simplify the pointer operand for all memory
+  // instructions.
+  // store val, (select (cond, null, P)) -> store val, P
+  // store val, (select (cond, P, null)) -> store val, P
+  if (!NullPointerIsDefined(SI.getFunction(), SI.getPointerAddressSpace())) {
+    if (SelectInst *Sel = dyn_cast<SelectInst>(Ptr)) {
+      if (isa<ConstantPointerNull>(Sel->getOperand(1)))
+        return replaceOperand(SI, 1, Sel->getOperand(2));
+
+      if (isa<ConstantPointerNull>(Sel->getOperand(2)))
+        return replaceOperand(SI, 1, Sel->getOperand(1));
+    }
+  }
+
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstCombine/store.ll b/llvm/test/Transforms/InstCombine/store.ll
index 5caf43a3cd6e9..0a2b0a5ee7987 100644
--- a/llvm/test/Transforms/InstCombine/store.ll
+++ b/llvm/test/Transforms/InstCombine/store.ll
@@ -347,8 +347,7 @@ define void @store_to_readonly_noalias(ptr readonly noalias %0) {
 
 define void @store_select_with_null(i1 %cond, ptr %p) {
 ; CHECK-LABEL: @store_select_with_null(
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr [[P:%.*]], ptr null
-; CHECK-NEXT:    store i32 0, ptr [[SEL]], align 4
+; CHECK-NEXT:    store i32 0, ptr [[SEL:%.*]], align 4
 ; CHECK-NEXT:    ret void
 ;
   %sel = select i1 %cond, ptr %p, ptr null
@@ -358,8 +357,7 @@ define void @store_select_with_null(i1 %cond, ptr %p) {
 
 define void @store_select_with_null_commuted(i1 %cond, ptr %p) {
 ; CHECK-LABEL: @store_select_with_null_commuted(
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND:%.*]], ptr null, ptr [[P:%.*]]
-; CHECK-NEXT:    store i32 0, ptr [[SEL]], align 4
+; CHECK-NEXT:    store i32 0, ptr [[SEL:%.*]], align 4
 ; CHECK-NEXT:    ret void
 ;
   %sel = select i1 %cond, ptr null, ptr %p

>From 71836ee205a069cc5b6d19a9f42e23bb02e94033 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 20 Feb 2025 23:50:20 +0800
Subject: [PATCH 3/3] [PhaseOrdering][NFC] Add a phase-ordering regression
 test.

---
 .../PhaseOrdering/load-store-sameval.ll       | 44 +++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 llvm/test/Transforms/PhaseOrdering/load-store-sameval.ll

diff --git a/llvm/test/Transforms/PhaseOrdering/load-store-sameval.ll b/llvm/test/Transforms/PhaseOrdering/load-store-sameval.ll
new file mode 100644
index 0000000000000..d8ef0723cf09e
--- /dev/null
+++ b/llvm/test/Transforms/PhaseOrdering/load-store-sameval.ll
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -passes='instcombine,early-cse<memssa>' -S %s | FileCheck %s
+
+; FIXME: We can remove the store instruction in the exit block
+define i32 @load_store_sameval(ptr %p, i1 %cond1, i1 %cond2) {
+; CHECK-LABEL: define i32 @load_store_sameval(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[COND1:%.*]], i1 [[COND2:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[COND1]], ptr null, ptr [[P]]
+; CHECK-NEXT:    [[PRE:%.*]] = load i32, ptr [[SPEC_SELECT]], align 4
+; CHECK-NEXT:    br label %[[BLOCK:.*]]
+; CHECK:       [[BLOCK]]:
+; CHECK-NEXT:    br label %[[BLOCK2:.*]]
+; CHECK:       [[BLOCK2]]:
+; CHECK-NEXT:    br i1 [[COND2]], label %[[BLOCK3:.*]], label %[[EXIT:.*]]
+; CHECK:       [[BLOCK3]]:
+; CHECK-NEXT:    [[LOAD:%.*]] = load double, ptr [[SPEC_SELECT]], align 8
+; CHECK-NEXT:    [[CMP:%.*]] = fcmp une double [[LOAD]], 0.000000e+00
+; CHECK-NEXT:    br i1 [[CMP]], label %[[BLOCK]], label %[[BLOCK2]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    store i32 [[PRE]], ptr [[P]], align 4
+; CHECK-NEXT:    ret i32 0
+;
+entry:
+  %spec.select = select i1 %cond1, ptr null, ptr %p
+  %pre = load i32, ptr %spec.select, align 4
+  br label %block
+
+block:
+  br label %block2
+
+block2:
+  br i1 %cond2, label %block3, label %exit
+
+block3:
+  %load = load double, ptr %spec.select, align 8
+  %cmp = fcmp une double %load, 0.000000e+00
+  br i1 %cmp, label %block, label %block2
+
+exit:
+  store i32 %pre, ptr %spec.select, align 4
+  ret i32 0
+}
+



More information about the llvm-commits mailing list