Skip to content

[DAGCombine] Correctly extend the constant RHS in TargetLowering::SimplifySetCC #152862

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
Aug 9, 2025

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Aug 9, 2025

In #150270, when the predicate is eq/ne and the trunc has only an nsw flag, the RHS is incorrectly zero-extended.

Closes #152630.

@llvmbot
Copy link
Member

llvmbot commented Aug 9, 2025

@llvm/pr-subscribers-backend-x86

Author: Yingwei Zheng (dtcxzyw)

Changes

In #150270, when the predicate is eq/ne and the trunc has only an nsw flag, the RHS is incorrectly zero-extended.

Closes #152630.


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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+5-4)
  • (added) llvm/test/CodeGen/X86/pr152630.ll (+34)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index e235d144e85ff..8fbabfa55e93f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -5125,10 +5125,11 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
           !ISD::isUnsignedIntSetCC(Cond))) &&
         isTypeDesirableForOp(ISD::SETCC, N0.getOperand(0).getValueType())) {
       EVT NewVT = N0.getOperand(0).getValueType();
-      SDValue NewConst = DAG.getConstant(ISD::isSignedIntSetCC(Cond)
-                                             ? C1.sext(NewVT.getSizeInBits())
-                                             : C1.zext(NewVT.getSizeInBits()),
-                                         dl, NewVT);
+      SDValue NewConst = DAG.getConstant(
+          (N0->getFlags().hasNoSignedWrap() && !ISD::isUnsignedIntSetCC(Cond))
+              ? C1.sext(NewVT.getSizeInBits())
+              : C1.zext(NewVT.getSizeInBits()),
+          dl, NewVT);
       return DAG.getSetCC(dl, VT, N0.getOperand(0), NewConst, Cond);
     }
 
diff --git a/llvm/test/CodeGen/X86/pr152630.ll b/llvm/test/CodeGen/X86/pr152630.ll
new file mode 100644
index 0000000000000..8fa98831c37b0
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr152630.ll
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+define i32 @pr152630(i1 %cond) nounwind {
+; CHECK-LABEL: pr152630:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    andl $1, %edi
+; CHECK-NEXT:    decl %edi
+; CHECK-NEXT:    cmpl $-1, %edi
+; CHECK-NEXT:    je .LBB0_2
+; CHECK-NEXT:  # %bb.1: # %entry
+; CHECK-NEXT:    movzbl %dil, %eax
+; CHECK-NEXT:    testl %eax, %eax
+; CHECK-NEXT:    jne .LBB0_3
+; CHECK-NEXT:  .LBB0_2: # %if.then
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    retq
+; CHECK-NEXT:  .LBB0_3: # %if.else
+; CHECK-NEXT:    movl $1, %eax
+; CHECK-NEXT:    retq
+entry:
+  %sel = select i1 %cond, i32 0, i32 -1
+  %conv = trunc nsw i32 %sel to i8
+  switch i8 %conv, label %if.else [
+    i8 -1, label %if.then
+    i8 0, label %if.then
+  ]
+
+if.then:
+  ret i32 0
+
+if.else:
+  ret i32 1
+}

@llvmbot
Copy link
Member

llvmbot commented Aug 9, 2025

@llvm/pr-subscribers-llvm-selectiondag

Author: Yingwei Zheng (dtcxzyw)

Changes

In #150270, when the predicate is eq/ne and the trunc has only an nsw flag, the RHS is incorrectly zero-extended.

Closes #152630.


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

2 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+5-4)
  • (added) llvm/test/CodeGen/X86/pr152630.ll (+34)
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index e235d144e85ff..8fbabfa55e93f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -5125,10 +5125,11 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
           !ISD::isUnsignedIntSetCC(Cond))) &&
         isTypeDesirableForOp(ISD::SETCC, N0.getOperand(0).getValueType())) {
       EVT NewVT = N0.getOperand(0).getValueType();
-      SDValue NewConst = DAG.getConstant(ISD::isSignedIntSetCC(Cond)
-                                             ? C1.sext(NewVT.getSizeInBits())
-                                             : C1.zext(NewVT.getSizeInBits()),
-                                         dl, NewVT);
+      SDValue NewConst = DAG.getConstant(
+          (N0->getFlags().hasNoSignedWrap() && !ISD::isUnsignedIntSetCC(Cond))
+              ? C1.sext(NewVT.getSizeInBits())
+              : C1.zext(NewVT.getSizeInBits()),
+          dl, NewVT);
       return DAG.getSetCC(dl, VT, N0.getOperand(0), NewConst, Cond);
     }
 
diff --git a/llvm/test/CodeGen/X86/pr152630.ll b/llvm/test/CodeGen/X86/pr152630.ll
new file mode 100644
index 0000000000000..8fa98831c37b0
--- /dev/null
+++ b/llvm/test/CodeGen/X86/pr152630.ll
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+define i32 @pr152630(i1 %cond) nounwind {
+; CHECK-LABEL: pr152630:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    andl $1, %edi
+; CHECK-NEXT:    decl %edi
+; CHECK-NEXT:    cmpl $-1, %edi
+; CHECK-NEXT:    je .LBB0_2
+; CHECK-NEXT:  # %bb.1: # %entry
+; CHECK-NEXT:    movzbl %dil, %eax
+; CHECK-NEXT:    testl %eax, %eax
+; CHECK-NEXT:    jne .LBB0_3
+; CHECK-NEXT:  .LBB0_2: # %if.then
+; CHECK-NEXT:    xorl %eax, %eax
+; CHECK-NEXT:    retq
+; CHECK-NEXT:  .LBB0_3: # %if.else
+; CHECK-NEXT:    movl $1, %eax
+; CHECK-NEXT:    retq
+entry:
+  %sel = select i1 %cond, i32 0, i32 -1
+  %conv = trunc nsw i32 %sel to i8
+  switch i8 %conv, label %if.else [
+    i8 -1, label %if.then
+    i8 0, label %if.then
+  ]
+
+if.then:
+  ret i32 0
+
+if.else:
+  ret i32 1
+}

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

LGTM

@dtcxzyw dtcxzyw merged commit 62735d2 into llvm:main Aug 9, 2025
12 checks passed
@dtcxzyw dtcxzyw deleted the fix-pr152630 branch August 9, 2025 17:24
@llvm-ci
Copy link
Collaborator

llvm-ci commented Aug 9, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-key-instructions running on sie-linux-worker5 while building llvm at step 6 "test-build-unified-tree-check-all".

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

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'SanitizerCommon-tsan-x86_64-Linux :: vsnprintf.cpp' FAILED ********************
Exit Code: 137

Command Output (stderr):
--
/home/buildbot/buildbot-root/llvm-ki/build/./bin/clang  --driver-mode=g++ -gline-tables-only -fsanitize=thread  -m64 -funwind-tables  -I/home/buildbot/buildbot-root/llvm-ki/llvm-project/compiler-rt/test -ldl -O2 /home/buildbot/buildbot-root/llvm-ki/llvm-project/compiler-rt/test/sanitizer_common/TestCases/vsnprintf.cpp -o /home/buildbot/buildbot-root/llvm-ki/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/tsan-x86_64-Linux/Output/vsnprintf.cpp.tmp # RUN: at line 4
+ /home/buildbot/buildbot-root/llvm-ki/build/./bin/clang --driver-mode=g++ -gline-tables-only -fsanitize=thread -m64 -funwind-tables -I/home/buildbot/buildbot-root/llvm-ki/llvm-project/compiler-rt/test -ldl -O2 /home/buildbot/buildbot-root/llvm-ki/llvm-project/compiler-rt/test/sanitizer_common/TestCases/vsnprintf.cpp -o /home/buildbot/buildbot-root/llvm-ki/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/tsan-x86_64-Linux/Output/vsnprintf.cpp.tmp
env TSAN_OPTIONS=check_printf=1  /home/buildbot/buildbot-root/llvm-ki/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/tsan-x86_64-Linux/Output/vsnprintf.cpp.tmp 2>&1 # RUN: at line 5
+ env TSAN_OPTIONS=check_printf=1 /home/buildbot/buildbot-root/llvm-ki/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/tsan-x86_64-Linux/Output/vsnprintf.cpp.tmp
/home/buildbot/buildbot-root/llvm-ki/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/tsan-x86_64-Linux/Output/vsnprintf.cpp.script: line 2: 159159 Killed                  env TSAN_OPTIONS=check_printf=1 /home/buildbot/buildbot-root/llvm-ki/build/runtimes/runtimes-bins/compiler-rt/test/sanitizer_common/tsan-x86_64-Linux/Output/vsnprintf.cpp.tmp 2>&1

--

********************


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
None yet
Development

Successfully merging this pull request may close these issues.

[SDAG][X86] Miscompilation at -O3
5 participants