[llvm] [InstSimplify] Forbid undef folds in foldOrCommuteConstant when undef cannot be used. (PR #170670)

via llvm-commits llvm-commits at lists.llvm.org
Sat Dec 6 06:16:27 PST 2025


https://github.com/dianqk updated https://github.com/llvm/llvm-project/pull/170670

>From 812ca4ae42f7cf5fb7553e3339621c3286523cdf Mon Sep 17 00:00:00 2001
From: dianqk <dianqk at dianqk.net>
Date: Thu, 4 Dec 2025 22:10:07 +0800
Subject: [PATCH 1/2] Pre-commit test cases

---
 .../InstCombine/expand-undef-const.ll         | 43 +++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/expand-undef-const.ll

diff --git a/llvm/test/Transforms/InstCombine/expand-undef-const.ll b/llvm/test/Transforms/InstCombine/expand-undef-const.ll
new file mode 100644
index 0000000000000..aaf32e495e840
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/expand-undef-const.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+; Checks that the return value is 0.
+
+; `%i8` can be folded to -1, so `%arg1` can be folded to undef.
+; First, we can try to expand `%i13 = and i8 %i9, %i12` to `%i13 = L1(%arg1(undef) and %i12) or (-1 and %i12)`.
+; Then, we can try to expand `L1(%arg1(undef) and %i12)` to `(%arg1(undef) and %i7) xor (%arg1(undef) and -1)`.
+; However, for `%arg1(undef) and %i7`, `%arg1(undef)` is be folded to 0, while for `%arg1(undef) and -1`, it cannot be folded to undef.
+
+define i8 @foo(i1 %arg, i8 %arg1) {
+; CHECK-LABEL: define i8 @foo(
+; CHECK-SAME: i1 [[ARG:%.*]], i8 [[ARG1:%.*]]) {
+; CHECK-NEXT:  [[BB:.*:]]
+; CHECK-NEXT:    br label %[[BB2:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br i1 true, label %[[BB15:.*]], label %[[BB2]]
+; CHECK:       [[BB15]]:
+; CHECK-NEXT:    ret i8 -128
+;
+bb:
+  br label %bb2
+
+bb2:
+  %i = phi i8 [ -128, %bb ], [ %arg1, %bb2 ] ; #x80 (128, -128)
+  %i3 = phi i8 [ 0, %bb ], [ 1, %bb2 ] ; #x00 (0)
+  %i4 = phi i8 [ 1, %bb ], [ %arg1, %bb2 ] ; #x01 (1)
+  %i5 = xor i8 %i3, 1 ; #x01 (1)
+  %i6 = ashr i8 %i4, %i5 ; #x00 (0)
+  %i7 = and i8 %i, -128 ; #x80 (128, -128)
+  %i8 = xor i8 %i6, -1 ; #xff (255, -1)
+  %i9 = or i8 %i8, %arg1 ; #xff (255, -1)
+  %i10 = and i8 %i8, 7 ; #x07 (7)
+  %i11 = shl i8 %i9, %i10 ; #x80 (128, -128)
+  %i12 = xor i8 %i7, -1 ; #x7f (127)
+  %i13 = and i8 %i9, %i12 ; #x7f (127) ; Cannot be -1.
+  %i14 = or i1 %arg, true ; #x1 (1)
+  br i1 %i14, label %bb15, label %bb2
+
+bb15:
+  %i16 = and i8 %i13, %i11 ; #x00 (0)
+  ret i8 %i16
+}

>From bdfe96a2591f7175a1a188fe656d7cb863c18aab Mon Sep 17 00:00:00 2001
From: dianqk <dianqk at dianqk.net>
Date: Thu, 4 Dec 2025 22:13:06 +0800
Subject: [PATCH 2/2] [InstSimplify] Forbid undef folds in
 foldOrCommuteConstant when undef cannot be used.

Following d110d4aaff31198cd455b68617978019a8339773,
we must also prevent an undef from being folded to two different values with constants.
---
 llvm/lib/Analysis/InstructionSimplify.cpp                     | 3 +++
 llvm/test/Transforms/InstCombine/expand-undef-const.ll        | 2 +-
 llvm/test/Transforms/NewGVN/pr37121-seens-this-value-a-lot.ll | 2 ++
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index bd85444d7d2b0..e42f955edf83c 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -568,6 +568,9 @@ static Constant *foldOrCommuteConstant(Instruction::BinaryOps Opcode,
                                        const SimplifyQuery &Q) {
   if (auto *CLHS = dyn_cast<Constant>(Op0)) {
     if (auto *CRHS = dyn_cast<Constant>(Op1)) {
+      if (!Q.CanUseUndef && (isa<UndefValue>(CLHS) || isa<UndefValue>(CRHS)))
+        return nullptr;
+
       switch (Opcode) {
       default:
         break;
diff --git a/llvm/test/Transforms/InstCombine/expand-undef-const.ll b/llvm/test/Transforms/InstCombine/expand-undef-const.ll
index aaf32e495e840..9abcdace8b216 100644
--- a/llvm/test/Transforms/InstCombine/expand-undef-const.ll
+++ b/llvm/test/Transforms/InstCombine/expand-undef-const.ll
@@ -16,7 +16,7 @@ define i8 @foo(i1 %arg, i8 %arg1) {
 ; CHECK:       [[BB2]]:
 ; CHECK-NEXT:    br i1 true, label %[[BB15:.*]], label %[[BB2]]
 ; CHECK:       [[BB15]]:
-; CHECK-NEXT:    ret i8 -128
+; CHECK-NEXT:    ret i8 0
 ;
 bb:
   br label %bb2
diff --git a/llvm/test/Transforms/NewGVN/pr37121-seens-this-value-a-lot.ll b/llvm/test/Transforms/NewGVN/pr37121-seens-this-value-a-lot.ll
index 1fc484437212e..b76c55b49d97f 100644
--- a/llvm/test/Transforms/NewGVN/pr37121-seens-this-value-a-lot.ll
+++ b/llvm/test/Transforms/NewGVN/pr37121-seens-this-value-a-lot.ll
@@ -6,6 +6,8 @@ define hidden void @foo() {
 ; CHECK-NEXT:  top:
 ; CHECK-NEXT:    br label [[IF:%.*]]
 ; CHECK:       if:
+; CHECK-NEXT:    [[TMP0:%.*]] = phi i8 [ [[TMP1:%.*]], [[IF]] ], [ poison, [[TOP:%.*]] ]
+; CHECK-NEXT:    [[TMP1]] = xor i8 [[TMP0]], undef
 ; CHECK-NEXT:    br i1 false, label [[L50:%.*]], label [[IF]]
 ; CHECK:       L50:
 ; CHECK-NEXT:    store i8 poison, ptr null, align 1



More information about the llvm-commits mailing list