diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -4462,6 +4462,11 @@ return false; case X86::COND_G: case X86::COND_GE: case X86::COND_L: case X86::COND_LE: + // If SF is used, but the instruction doesn't update the SF, then we + // can't do the optimization. + if (NoSignFlag) + return false; + LLVM_FALLTHROUGH; case X86::COND_O: case X86::COND_NO: // If OF is used, the instruction needs to clear it like CmpZero does. if (!ClearsOverflowFlag) diff --git a/llvm/test/CodeGen/X86/pr56103.ll b/llvm/test/CodeGen/X86/pr56103.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr56103.ll @@ -0,0 +1,61 @@ +; RUN: llc < %s -mtriple=x86_64-linux-generic | FileCheck %s + +; Check the test instruction won't be optimizated by peephole opt. +; CHECK: testq + +@e = dso_local local_unnamed_addr global i16 0, align 2 +@a = dso_local local_unnamed_addr global i32 0, align 4 +@c = dso_local local_unnamed_addr global i32 0, align 4 +@b = dso_local local_unnamed_addr global i64 0, align 8 + +; Function Attrs: nounwind uwtable +define dso_local i32 @main() local_unnamed_addr #0 { +entry: + store i16 1, ptr @e, align 2, !tbaa !5 + store i64 1, ptr @b, align 8, !tbaa !9 + %0 = load i32, ptr @a, align 4, !tbaa !11 + %shr = ashr i32 -2, %0 + %1 = load i32, ptr @c, align 4, !tbaa !11 + %sub = add i32 %1, -1 + %conv2 = zext i32 %sub to i64 + %2 = and i32 %shr, 65535 + %conv3 = zext i32 %2 to i64 + %sub4 = add nsw i64 %conv3, -1 + %xor = xor i64 %sub4, %conv2 + %neg5 = xor i32 %0, -1 + %conv6 = sext i32 %neg5 to i64 + %and = and i64 %xor, %conv6 + %cmp = icmp slt i64 %and, 1 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + call void @abort() #2 + unreachable + +if.end: ; preds = %entry + ret i32 0 +} + +; Function Attrs: noreturn nounwind +declare void @abort() local_unnamed_addr #1 + +attributes #0 = { nounwind uwtable "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { noreturn nounwind "frame-pointer"="none" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #2 = { noreturn nounwind } + +!llvm.module.flags = !{!0, !1, !2, !3} +!llvm.ident = !{!4} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 7, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{i32 7, !"uwtable", i32 2} +!4 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project.git e4361089ff5fc4bf1400f650876edd2b267a49af)"} +!5 = !{!6, !6, i64 0} +!6 = !{!"short", !7, i64 0} +!7 = !{!"omnipotent char", !8, i64 0} +!8 = !{!"Simple C/C++ TBAA"} +!9 = !{!10, !10, i64 0} +!10 = !{!"long", !7, i64 0} +!11 = !{!12, !12, i64 0} +!12 = !{!"int", !7, i64 0}