Skip to content

[DAGCombiner] Don't ignore N2's undef elements in foldVSelectOfConstants #129272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 1, 2025

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Feb 28, 2025

Since N2 will be reused in the fold, we cannot skip N2's undef elements if the corresponding element in N1 is well-defined.
For example:

t2: v4i32 = BUILD_VECTOR Constant:i32<0>, Constant:i32<0>, Constant:i32<0>, Constant:i32<0>
t24: v4i32 = BUILD_VECTOR undef:i32, undef:i32, Constant:i32<1>, undef:i32
t11: v4i32 = vselect t8, t2, t10

Before this patch, we fold t11 into:

t26: v4i32 = sign_extend t8
t27: v4i32 = add t26, t24

The last element of t27 is incorrect.

Closes #129181.

@dtcxzyw dtcxzyw requested review from RKSimon and topperc February 28, 2025 17:14
@llvmbot llvmbot added backend:X86 llvm:SelectionDAG SelectionDAGISel as well labels Feb 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 28, 2025

@llvm/pr-subscribers-backend-x86

@llvm/pr-subscribers-llvm-selectiondag

Author: Yingwei Zheng (dtcxzyw)

Changes

Since N2 will be reused in the fold, we cannot skip N2's undef elements if the corresponding element in N1 is well-defined.
For example:

t2: v4i32 = BUILD_VECTOR Constant:i32&lt;0&gt;, Constant:i32&lt;0&gt;, Constant:i32&lt;0&gt;, Constant:i32&lt;0&gt;
t24: v4i32 = BUILD_VECTOR undef:i32, undef:i32, Constant:i32&lt;1&gt;, undef:i32
t11: v4i32 = vselect t8, t2, t10

Before this patch, we fold t11 into:

t26: v4i32 = sign_extend t8
t27: v4i32 = add t26, t24

The last element of t27 is incorrect.

Closes #129181.


Full diff: https://github.com/llvm/llvm-project/pull/129272.diff

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+3-2)
  • (modified) llvm/test/CodeGen/X86/vselect-constants.ll (+18)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index f197ae61550a9..343a93785766c 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -12535,9 +12535,10 @@ SDValue DAGCombiner::foldVSelectOfConstants(SDNode *N) {
   for (unsigned i = 0; i != Elts; ++i) {
     SDValue N1Elt = N1.getOperand(i);
     SDValue N2Elt = N2.getOperand(i);
-    if (N1Elt.isUndef() || N2Elt.isUndef())
+    if (N1Elt.isUndef())
       continue;
-    if (N1Elt.getValueType() != N2Elt.getValueType()) {
+    // N2 should not contain undef values since it will be reused in the fold.
+    if (N2Elt.isUndef() || N1Elt.getValueType() != N2Elt.getValueType()) {
       AllAddOne = false;
       AllSubOne = false;
       break;
diff --git a/llvm/test/CodeGen/X86/vselect-constants.ll b/llvm/test/CodeGen/X86/vselect-constants.ll
index 901f7e4a00eb5..34bda718db8f6 100644
--- a/llvm/test/CodeGen/X86/vselect-constants.ll
+++ b/llvm/test/CodeGen/X86/vselect-constants.ll
@@ -302,3 +302,21 @@ define i32 @wrong_min_signbits(<2 x i16> %x) {
   %t1 = bitcast <2 x i16> %sel to i32
   ret i32 %t1
 }
+
+define i32 @pr129181() {
+; SSE-LABEL: pr129181:
+; SSE:       # %bb.0: # %entry
+; SSE-NEXT:    xorl %eax, %eax
+; SSE-NEXT:    retq
+;
+; AVX-LABEL: pr129181:
+; AVX:       # %bb.0: # %entry
+; AVX-NEXT:    xorl %eax, %eax
+; AVX-NEXT:    retq
+entry:
+  %x = insertelement <4 x i32> zeroinitializer, i32 0, i32 0
+  %cmp = icmp ult <4 x i32> %x, splat (i32 1)
+  %sel = select <4 x i1> %cmp, <4 x i32> zeroinitializer, <4 x i32> <i32 0, i32 0, i32 1, i32 poison>
+  %reduce = tail call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %sel)
+  ret i32 %reduce
+}

Copy link

⚠️ undef deprecator found issues in your code. ⚠️

You can test this locally with the following command:
git diff -U0 --pickaxe-regex -S '([^a-zA-Z0-9#_-]undef[^a-zA-Z0-9_-]|UndefValue::get)' 78aa61d8b60fc3e9d00236332078d14808abbc57 1bc745841ee18b901b6e47edebefe4fd864c5e40 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp llvm/test/CodeGen/X86/vselect-constants.ll

The following files introduce new uses of undef:

  • llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Undef is now deprecated and should only be used in the rare cases where no replacement is possible. For example, a load of uninitialized memory yields undef. You should use poison values for placeholders instead.

In tests, avoid using undef and having tests that trigger undefined behavior. If you need an operand with some unimportant value, you can add a new argument to the function and use that instead.

For example, this is considered a bad practice:

define void @fn() {
  ...
  br i1 undef, ...
}

Please use the following instead:

define void @fn(i1 %cond) {
  ...
  br i1 %cond, ...
}

Please refer to the Undefined Behavior Manual for more information.

Copy link
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - cheers

@dtcxzyw dtcxzyw merged commit 2709366 into llvm:main Mar 1, 2025
13 of 14 checks passed
@dtcxzyw dtcxzyw deleted the fix-pr129181 branch March 1, 2025 12:21
@dtcxzyw dtcxzyw added this to the LLVM 20.X Release milestone Mar 1, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage in LLVM Release Status Mar 1, 2025
@dtcxzyw
Copy link
Member Author

dtcxzyw commented Mar 1, 2025

/cherry-pick 2709366

@llvmbot
Copy link
Member

llvmbot commented Mar 1, 2025

/pull-request #129383

@llvmbot llvmbot moved this from Needs Triage to Done in LLVM Release Status Mar 1, 2025
@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 1, 2025

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/13557

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
PASS: lldb-unit :: ValueObject/./LLDBValueObjectTests/5/11 (2087 of 2097)
PASS: lldb-unit :: ValueObject/./LLDBValueObjectTests/7/11 (2088 of 2097)
PASS: lldb-unit :: ValueObject/./LLDBValueObjectTests/9/11 (2089 of 2097)
PASS: lldb-unit :: ValueObject/./LLDBValueObjectTests/8/11 (2090 of 2097)
PASS: lldb-unit :: tools/lldb-server/tests/./LLDBServerTests/0/2 (2091 of 2097)
PASS: lldb-unit :: tools/lldb-server/tests/./LLDBServerTests/1/2 (2092 of 2097)
PASS: lldb-unit :: Target/./TargetTests/11/14 (2093 of 2097)
PASS: lldb-unit :: Host/./HostTests/2/13 (2094 of 2097)
PASS: lldb-unit :: Process/gdb-remote/./ProcessGdbRemoteTests/8/9 (2095 of 2097)
PASS: lldb-api :: tools/lldb-server/TestLldbGdbServer.py (2096 of 2097)
command timed out: 2400 seconds without output running [b'ninja', b'check-lldb'], attempting to kill
process killed by signal 9
program finished with exit code -1
elapsedTime=2707.129204

swift-ci pushed a commit to swiftlang/llvm-project that referenced this pull request Mar 11, 2025
…ants` (llvm#129272)

Since N2 will be reused in the fold, we cannot skip N2's undef elements
if the corresponding element in N1 is well-defined.
For example:
```
t2: v4i32 = BUILD_VECTOR Constant:i32<0>, Constant:i32<0>, Constant:i32<0>, Constant:i32<0>
t24: v4i32 = BUILD_VECTOR undef:i32, undef:i32, Constant:i32<1>, undef:i32
t11: v4i32 = vselect t8, t2, t10
```
Before this patch, we fold t11 into:
```
t26: v4i32 = sign_extend t8
t27: v4i32 = add t26, t24
```
The last element of t27 is incorrect.

Closes llvm#129181.

(cherry picked from commit 2709366)
jph-13 pushed a commit to jph-13/llvm-project that referenced this pull request Mar 21, 2025
…ants` (llvm#129272)

Since N2 will be reused in the fold, we cannot skip N2's undef elements
if the corresponding element in N1 is well-defined.
For example:
```
t2: v4i32 = BUILD_VECTOR Constant:i32<0>, Constant:i32<0>, Constant:i32<0>, Constant:i32<0>
t24: v4i32 = BUILD_VECTOR undef:i32, undef:i32, Constant:i32<1>, undef:i32
t11: v4i32 = vselect t8, t2, t10
```
Before this patch, we fold t11 into:
```
t26: v4i32 = sign_extend t8
t27: v4i32 = add t26, t24
```
The last element of t27 is incorrect.

Closes llvm#129181.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:X86 llvm:SelectionDAG SelectionDAGISel as well
Projects
Development

Successfully merging this pull request may close these issues.

[clang] Miscompile at -O2/3
4 participants