[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