Skip to content

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

--

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


@asmok-g
Copy link

asmok-g commented Aug 20, 2025

Heads-up: We saw the following tests used to fail on the original commit under asan, but after this fix clang crashes when I try to run them:

  • llvm/llvm-project/lldb/test/API/commands/expression/call-function/TestCallStdStringFunction.py.arm_gemu.test
  • //llvm/llvm-project/lldb/test/API:commands/expression/call-function/TestCallStdStringFunction.py.test
  • /llvm/llvm-project/lldb/test/API:lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py.arm_gemu.test
  • //llvm/llvm-project/lldb/test/API:lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py.test
    I'm still not sure if this is due to something in our internal setup at google. Working on a repro but posting the heads-up in the meanwhile.

@AlexMaclean
Copy link
Member

@asmok-g Sorry to hear that my change seems to be causing more issues! Would it be possible to attach more details about how to reproduce and whether there is any information produced when clang crashes? I'm very unfamiliar with lldb and I'm having trouble reproducing this issue locally.

@asmok-g
Copy link

asmok-g commented Aug 20, 2025

@AlexMaclean Sorry, I discovered the root-causing of the clang crash was not accurate and I can reproduce it also before this commit. I need a way to test the miscompiles-under-asan caused by the original commit are fixed by this fix. Will update the thread soon.

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

7 participants