[llvm] [SDAG] Add freeze when simplifying select with undef arms (PR #175199)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 9 08:42:10 PST 2026


https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/175199

Consider the following pattern:
```
%trunc = trunc nuw i64 %x to i48
%sel = select i1 %cmp, i48 %trunc, i48 undef
```
We cannot simplify `%sel` to `%trunc` as `%trunc` may be poison, which cannot be refined into undef.

This patch checks whether the replacement may be poison. If so, it will insert a freeze.
We may need SDAG's version of `impliesPoison` if it causes significant regressions.

Closes https://github.com/llvm/llvm-project/issues/175018.


>From 2ad6cfb83980e0549acd55d98ba12da7ad99c4fa Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 10 Jan 2026 00:26:32 +0800
Subject: [PATCH 1/2] [X86] Add pre-commit tests. NFC.

---
 llvm/test/CodeGen/X86/select.ll | 64 +++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/llvm/test/CodeGen/X86/select.ll b/llvm/test/CodeGen/X86/select.ll
index 4e31b48ec5cec..6384b35745783 100644
--- a/llvm/test/CodeGen/X86/select.ll
+++ b/llvm/test/CodeGen/X86/select.ll
@@ -2198,3 +2198,67 @@ define i32 @select_uaddo_common_op1(i32 %a, i32 %b, i32 %c, i1 %cond) {
   %sel = select i1 %cond, i32 %ab0, i32 %cb0
   ret i32 %sel
 }
+
+define i56 @select_undef_rhs(i64 %x, i1 %cmp) {
+; GENERIC-LABEL: select_undef_rhs:
+; GENERIC:       ## %bb.0:
+; GENERIC-NEXT:    movq %rdi, %rax
+; GENERIC-NEXT:    retq
+;
+; ATOM-LABEL: select_undef_rhs:
+; ATOM:       ## %bb.0:
+; ATOM-NEXT:    movq %rdi, %rax
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    retq
+;
+; ATHLON-LABEL: select_undef_rhs:
+; ATHLON:       ## %bb.0:
+; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; ATHLON-NEXT:    retl
+;
+; MCU-LABEL: select_undef_rhs:
+; MCU:       # %bb.0:
+; MCU-NEXT:    retl
+  %trunc = trunc nuw i64 %x to i48
+  %sel = select i1 %cmp, i48 %trunc, i48 undef
+  %zext = zext i48 %sel to i56
+  ret i56 %zext
+}
+
+define i56 @select_undef_lhs(i64 %x, i1 %cmp) {
+; GENERIC-LABEL: select_undef_lhs:
+; GENERIC:       ## %bb.0:
+; GENERIC-NEXT:    movq %rdi, %rax
+; GENERIC-NEXT:    retq
+;
+; ATOM-LABEL: select_undef_lhs:
+; ATOM:       ## %bb.0:
+; ATOM-NEXT:    movq %rdi, %rax
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    nop
+; ATOM-NEXT:    retq
+;
+; ATHLON-LABEL: select_undef_lhs:
+; ATHLON:       ## %bb.0:
+; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; ATHLON-NEXT:    retl
+;
+; MCU-LABEL: select_undef_lhs:
+; MCU:       # %bb.0:
+; MCU-NEXT:    retl
+  %trunc = trunc nuw i64 %x to i48
+  %sel = select i1 %cmp, i48 undef, i48 %trunc
+  %zext = zext i48 %sel to i56
+  ret i56 %zext
+}

>From c357f223878bd528c2dbdfac767af5d43c918d90 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 10 Jan 2026 00:30:35 +0800
Subject: [PATCH 2/2] [SDAG] Add freeze when simplifying select with undef arms

---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp |  4 ++--
 llvm/test/CodeGen/X86/fshl.ll                 | 12 +++++-----
 llvm/test/CodeGen/X86/funnel-shift.ll         |  4 ++--
 llvm/test/CodeGen/X86/select.ll               | 24 +++++++++++--------
 4 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 35e443b40c41f..8eeb456a95dd1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -10820,9 +10820,9 @@ SDValue SelectionDAG::simplifySelect(SDValue Cond, SDValue T, SDValue F) {
   if (Cond.isUndef())
     return isConstantValueOfAnyType(T) ? T : F;
   if (T.isUndef())
-    return F;
+    return isGuaranteedNotToBePoison(F) ? F : getFreeze(F);
   if (F.isUndef())
-    return T;
+    return isGuaranteedNotToBePoison(T) ? T : getFreeze(T);
 
   // select true, T, F --> T
   // select false, T, F --> F
diff --git a/llvm/test/CodeGen/X86/fshl.ll b/llvm/test/CodeGen/X86/fshl.ll
index f998128af95f8..9da2640ea8392 100644
--- a/llvm/test/CodeGen/X86/fshl.ll
+++ b/llvm/test/CodeGen/X86/fshl.ll
@@ -571,16 +571,16 @@ define i64 @const_shift_i64(i64 %x, i64 %y) nounwind {
 ; X86-SLOW-LABEL: const_shift_i64:
 ; X86-SLOW:       # %bb.0:
 ; X86-SLOW-NEXT:    pushl %esi
+; X86-SLOW-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X86-SLOW-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 ; X86-SLOW-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-SLOW-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X86-SLOW-NEXT:    movl %ecx, %esi
 ; X86-SLOW-NEXT:    shrl $25, %esi
-; X86-SLOW-NEXT:    movl %ecx, %eax
-; X86-SLOW-NEXT:    shll $7, %eax
-; X86-SLOW-NEXT:    orl %esi, %eax
-; X86-SLOW-NEXT:    shrl $25, %ecx
 ; X86-SLOW-NEXT:    shll $7, %edx
-; X86-SLOW-NEXT:    orl %ecx, %edx
+; X86-SLOW-NEXT:    orl %esi, %edx
+; X86-SLOW-NEXT:    shll $7, %ecx
+; X86-SLOW-NEXT:    shrl $25, %eax
+; X86-SLOW-NEXT:    orl %ecx, %eax
 ; X86-SLOW-NEXT:    popl %esi
 ; X86-SLOW-NEXT:    retl
 ;
diff --git a/llvm/test/CodeGen/X86/funnel-shift.ll b/llvm/test/CodeGen/X86/funnel-shift.ll
index 252cb3333f1d1..78d7e7eb3c136 100644
--- a/llvm/test/CodeGen/X86/funnel-shift.ll
+++ b/llvm/test/CodeGen/X86/funnel-shift.ll
@@ -262,9 +262,9 @@ define i32 @fshl_i32_const_overshift(i32 %x, i32 %y) nounwind {
 define i64 @fshl_i64_const_overshift(i64 %x, i64 %y) nounwind {
 ; X86-SSE2-LABEL: fshl_i64_const_overshift:
 ; X86-SSE2:       # %bb.0:
+; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %edx
 ; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %edx
 ; X86-SSE2-NEXT:    shldl $9, %ecx, %edx
 ; X86-SSE2-NEXT:    shrdl $23, %ecx, %eax
 ; X86-SSE2-NEXT:    retl
@@ -1004,9 +1004,9 @@ define i32 @fshr_i32_const_overshift(i32 %x, i32 %y) nounwind {
 define i64 @fshr_i64_const_overshift(i64 %x, i64 %y) nounwind {
 ; X86-SSE2-LABEL: fshr_i64_const_overshift:
 ; X86-SSE2:       # %bb.0:
+; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %ecx
 ; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %edx
-; X86-SSE2-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X86-SSE2-NEXT:    shrdl $9, %ecx, %eax
 ; X86-SSE2-NEXT:    shldl $23, %ecx, %edx
 ; X86-SSE2-NEXT:    retl
diff --git a/llvm/test/CodeGen/X86/select.ll b/llvm/test/CodeGen/X86/select.ll
index 6384b35745783..fe90028aa6aff 100644
--- a/llvm/test/CodeGen/X86/select.ll
+++ b/llvm/test/CodeGen/X86/select.ll
@@ -2202,14 +2202,14 @@ define i32 @select_uaddo_common_op1(i32 %a, i32 %b, i32 %c, i1 %cond) {
 define i56 @select_undef_rhs(i64 %x, i1 %cmp) {
 ; GENERIC-LABEL: select_undef_rhs:
 ; GENERIC:       ## %bb.0:
-; GENERIC-NEXT:    movq %rdi, %rax
+; GENERIC-NEXT:    movabsq $281474976710655, %rax ## imm = 0xFFFFFFFFFFFF
+; GENERIC-NEXT:    andq %rdi, %rax
 ; GENERIC-NEXT:    retq
 ;
 ; ATOM-LABEL: select_undef_rhs:
 ; ATOM:       ## %bb.0:
-; ATOM-NEXT:    movq %rdi, %rax
-; ATOM-NEXT:    nop
-; ATOM-NEXT:    nop
+; ATOM-NEXT:    movabsq $281474976710655, %rax ## imm = 0xFFFFFFFFFFFF
+; ATOM-NEXT:    andq %rdi, %rax
 ; ATOM-NEXT:    nop
 ; ATOM-NEXT:    nop
 ; ATOM-NEXT:    nop
@@ -2219,11 +2219,13 @@ define i56 @select_undef_rhs(i64 %x, i1 %cmp) {
 ; ATHLON-LABEL: select_undef_rhs:
 ; ATHLON:       ## %bb.0:
 ; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; ATHLON-NEXT:    movzwl %cx, %edx
 ; ATHLON-NEXT:    retl
 ;
 ; MCU-LABEL: select_undef_rhs:
 ; MCU:       # %bb.0:
+; MCU-NEXT:    movzwl %dx, %edx
 ; MCU-NEXT:    retl
   %trunc = trunc nuw i64 %x to i48
   %sel = select i1 %cmp, i48 %trunc, i48 undef
@@ -2234,14 +2236,14 @@ define i56 @select_undef_rhs(i64 %x, i1 %cmp) {
 define i56 @select_undef_lhs(i64 %x, i1 %cmp) {
 ; GENERIC-LABEL: select_undef_lhs:
 ; GENERIC:       ## %bb.0:
-; GENERIC-NEXT:    movq %rdi, %rax
+; GENERIC-NEXT:    movabsq $281474976710655, %rax ## imm = 0xFFFFFFFFFFFF
+; GENERIC-NEXT:    andq %rdi, %rax
 ; GENERIC-NEXT:    retq
 ;
 ; ATOM-LABEL: select_undef_lhs:
 ; ATOM:       ## %bb.0:
-; ATOM-NEXT:    movq %rdi, %rax
-; ATOM-NEXT:    nop
-; ATOM-NEXT:    nop
+; ATOM-NEXT:    movabsq $281474976710655, %rax ## imm = 0xFFFFFFFFFFFF
+; ATOM-NEXT:    andq %rdi, %rax
 ; ATOM-NEXT:    nop
 ; ATOM-NEXT:    nop
 ; ATOM-NEXT:    nop
@@ -2251,11 +2253,13 @@ define i56 @select_undef_lhs(i64 %x, i1 %cmp) {
 ; ATHLON-LABEL: select_undef_lhs:
 ; ATHLON:       ## %bb.0:
 ; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %edx
+; ATHLON-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; ATHLON-NEXT:    movzwl %cx, %edx
 ; ATHLON-NEXT:    retl
 ;
 ; MCU-LABEL: select_undef_lhs:
 ; MCU:       # %bb.0:
+; MCU-NEXT:    movzwl %dx, %edx
 ; MCU-NEXT:    retl
   %trunc = trunc nuw i64 %x to i48
   %sel = select i1 %cmp, i48 undef, i48 %trunc



More information about the llvm-commits mailing list