[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