[llvm] [X86] ICMP EQ/NE MIN_SIGNED_INT - avoid immediate argument by using NEG + SETO/SETNO (PR #94948)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 10 10:06:28 PDT 2024


https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/94948

>From 4571fce073e344ac308362919be19bf6301e4e15 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Mon, 10 Jun 2024 10:42:42 +0100
Subject: [PATCH] [X86] ICMP EQ/NE MIN_SIGNED_INT - avoid immediate argument by
 using NEG + SETO/SETNO

Fixes #67709
---
 llvm/lib/Target/X86/X86ISelLowering.cpp       | 12 ++++
 .../test/CodeGen/X86/2008-06-16-SubregsBug.ll |  4 +-
 llvm/test/CodeGen/X86/abs.ll                  | 58 +++++++++----------
 llvm/test/CodeGen/X86/combine-sdiv.ll         |  4 +-
 llvm/test/CodeGen/X86/is_fpclass.ll           | 18 +++---
 llvm/test/CodeGen/X86/lsr-overflow.ll         |  6 +-
 llvm/test/CodeGen/X86/shrink-compare-pgso.ll  |  4 +-
 llvm/test/CodeGen/X86/shrink-compare.ll       |  4 +-
 8 files changed, 61 insertions(+), 49 deletions(-)

diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 2aec14e93d082..cb51952285e71 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -23816,6 +23816,18 @@ SDValue X86TargetLowering::emitFlagsForSetcc(SDValue Op0, SDValue Op1,
       }
     }
 
+    // Look for X == INT_MIN or X != INT_MIN. We can use NEG and test for
+    // overflow.
+    if (isMinSignedConstant(Op1)) {
+      EVT VT = Op0.getValueType();
+      SDVTList CmpVTs = DAG.getVTList(VT, MVT::i32);
+      X86::CondCode CondCode = CC == ISD::SETEQ ? X86::COND_O : X86::COND_NO;
+      X86CC = DAG.getTargetConstant(CondCode, dl, MVT::i8);
+      SDValue Neg =
+          DAG.getNode(X86ISD::SUB, dl, CmpVTs, DAG.getConstant(0, dl, VT), Op0);
+      return SDValue(Neg.getNode(), 1);
+    }
+
     // Try to use the carry flag from the add in place of an separate CMP for:
     // (seteq (add X, -1), -1). Similar for setne.
     if (isAllOnesConstant(Op1) && Op0.getOpcode() == ISD::ADD &&
diff --git a/llvm/test/CodeGen/X86/2008-06-16-SubregsBug.ll b/llvm/test/CodeGen/X86/2008-06-16-SubregsBug.ll
index feaa38a7600a2..00ffea903079e 100644
--- a/llvm/test/CodeGen/X86/2008-06-16-SubregsBug.ll
+++ b/llvm/test/CodeGen/X86/2008-06-16-SubregsBug.ll
@@ -8,8 +8,8 @@ define i16 @test(ptr %tmp179) nounwind  {
 ; CHECK-NEXT:    movzwl (%eax), %eax
 ; CHECK-NEXT:    movl %eax, %ecx
 ; CHECK-NEXT:    andl $64512, %ecx ## imm = 0xFC00
-; CHECK-NEXT:    cmpl $32768, %ecx ## imm = 0x8000
-; CHECK-NEXT:    jne LBB0_2
+; CHECK-NEXT:    negw %cx
+; CHECK-NEXT:    jno LBB0_2
 ; CHECK-NEXT:  ## %bb.1: ## %bb189
 ; CHECK-NEXT:    ## kill: def $ax killed $ax killed $eax
 ; CHECK-NEXT:    retl
diff --git a/llvm/test/CodeGen/X86/abs.ll b/llvm/test/CodeGen/X86/abs.ll
index 7642c0c954142..1b5828a9e49c4 100644
--- a/llvm/test/CodeGen/X86/abs.ll
+++ b/llvm/test/CodeGen/X86/abs.ll
@@ -713,8 +713,9 @@ define i128 @test_sextinreg_i128(i128 %a) nounwind {
 define i8 @test_minsigned_i8(i8 %a0, i8 %a1) nounwind {
 ; X64-LABEL: test_minsigned_i8:
 ; X64:       # %bb.0:
-; X64-NEXT:    cmpb $-128, %dil
-; X64-NEXT:    jne .LBB17_1
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    negb %al
+; X64-NEXT:    jno .LBB17_1
 ; X64-NEXT:  # %bb.2: # %select.end
 ; X64-NEXT:    movl %esi, %eax
 ; X64-NEXT:    retq
@@ -729,8 +730,9 @@ define i8 @test_minsigned_i8(i8 %a0, i8 %a1) nounwind {
 ; X86-LABEL: test_minsigned_i8:
 ; X86:       # %bb.0:
 ; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
-; X86-NEXT:    cmpb $-128, %al
-; X86-NEXT:    jne .LBB17_1
+; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    negb %cl
+; X86-NEXT:    jno .LBB17_1
 ; X86-NEXT:  # %bb.2: # %select.end
 ; X86-NEXT:    movzbl {{[0-9]+}}(%esp), %eax
 ; X86-NEXT:    retl
@@ -749,30 +751,28 @@ define i8 @test_minsigned_i8(i8 %a0, i8 %a1) nounwind {
 define i16 @test_minsigned_i16(i16 %a0, i16 %a1) nounwind {
 ; X64-LABEL: test_minsigned_i16:
 ; X64:       # %bb.0:
-; X64-NEXT:    movzwl %di, %eax
-; X64-NEXT:    cmpl $32768, %eax # imm = 0x8000
-; X64-NEXT:    jne .LBB18_1
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    negw %ax
+; X64-NEXT:    jno .LBB18_1
 ; X64-NEXT:  # %bb.2: # %select.end
 ; X64-NEXT:    movl %esi, %eax
 ; X64-NEXT:    retq
 ; X64-NEXT:  .LBB18_1: # %select.false.sink
+; X64-NEXT:    cmovnsw %ax, %di
 ; X64-NEXT:    movl %edi, %eax
-; X64-NEXT:    negw %ax
-; X64-NEXT:    cmovsw %di, %ax
 ; X64-NEXT:    retq
 ;
 ; X86-LABEL: test_minsigned_i16:
 ; X86:       # %bb.0:
-; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    cmpl $32768, %ecx # imm = 0x8000
-; X86-NEXT:    jne .LBB18_1
+; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    negw %cx
+; X86-NEXT:    jno .LBB18_1
 ; X86-NEXT:  # %bb.2: # %select.end
 ; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
 ; X86-NEXT:    retl
 ; X86-NEXT:  .LBB18_1: # %select.false.sink
-; X86-NEXT:    movl %ecx, %eax
-; X86-NEXT:    negw %ax
-; X86-NEXT:    cmovsw %cx, %ax
+; X86-NEXT:    cmovnsw %cx, %ax
 ; X86-NEXT:    retl
   %lim = icmp eq i16 %a0, -32768
   %abs = tail call i16 @llvm.abs.i16(i16 %a0, i1 false)
@@ -783,29 +783,28 @@ define i16 @test_minsigned_i16(i16 %a0, i16 %a1) nounwind {
 define i32 @test_minsigned_i32(i32 %a0, i32 %a1) nounwind {
 ; X64-LABEL: test_minsigned_i32:
 ; X64:       # %bb.0:
-; X64-NEXT:    cmpl $-2147483648, %edi # imm = 0x80000000
-; X64-NEXT:    jne .LBB19_1
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    negl %eax
+; X64-NEXT:    jno .LBB19_1
 ; X64-NEXT:  # %bb.2: # %select.end
 ; X64-NEXT:    movl %esi, %eax
 ; X64-NEXT:    retq
 ; X64-NEXT:  .LBB19_1: # %select.false.sink
+; X64-NEXT:    cmovnsl %eax, %edi
 ; X64-NEXT:    movl %edi, %eax
-; X64-NEXT:    negl %eax
-; X64-NEXT:    cmovsl %edi, %eax
 ; X64-NEXT:    retq
 ;
 ; X86-LABEL: test_minsigned_i32:
 ; X86:       # %bb.0:
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    cmpl $-2147483648, %ecx # imm = 0x80000000
-; X86-NEXT:    jne .LBB19_1
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    negl %ecx
+; X86-NEXT:    jno .LBB19_1
 ; X86-NEXT:  # %bb.2: # %select.end
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
 ; X86-NEXT:    retl
 ; X86-NEXT:  .LBB19_1: # %select.false.sink
-; X86-NEXT:    movl %ecx, %eax
-; X86-NEXT:    negl %eax
-; X86-NEXT:    cmovsl %ecx, %eax
+; X86-NEXT:    cmovnsl %ecx, %eax
 ; X86-NEXT:    retl
   %lim = icmp eq i32 %a0, -2147483648
   %abs = tail call i32 @llvm.abs.i32(i32 %a0, i1 false)
@@ -816,16 +815,15 @@ define i32 @test_minsigned_i32(i32 %a0, i32 %a1) nounwind {
 define i64 @test_minsigned_i64(i64 %a0, i64 %a1) nounwind {
 ; X64-LABEL: test_minsigned_i64:
 ; X64:       # %bb.0:
-; X64-NEXT:    movabsq $-9223372036854775808, %rax # imm = 0x8000000000000000
-; X64-NEXT:    cmpq %rax, %rdi
-; X64-NEXT:    jne .LBB20_1
+; X64-NEXT:    movq %rdi, %rax
+; X64-NEXT:    negq %rax
+; X64-NEXT:    jno .LBB20_1
 ; X64-NEXT:  # %bb.2: # %select.end
 ; X64-NEXT:    movq %rsi, %rax
 ; X64-NEXT:    retq
 ; X64-NEXT:  .LBB20_1: # %select.false.sink
+; X64-NEXT:    cmovnsq %rax, %rdi
 ; X64-NEXT:    movq %rdi, %rax
-; X64-NEXT:    negq %rax
-; X64-NEXT:    cmovsq %rdi, %rax
 ; X64-NEXT:    retq
 ;
 ; X86-LABEL: test_minsigned_i64:
diff --git a/llvm/test/CodeGen/X86/combine-sdiv.ll b/llvm/test/CodeGen/X86/combine-sdiv.ll
index 49797fbefa597..5c5487815b336 100644
--- a/llvm/test/CodeGen/X86/combine-sdiv.ll
+++ b/llvm/test/CodeGen/X86/combine-sdiv.ll
@@ -58,8 +58,8 @@ define i32 @combine_sdiv_by_minsigned(i32 %x) {
 ; CHECK-LABEL: combine_sdiv_by_minsigned:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    xorl %eax, %eax
-; CHECK-NEXT:    cmpl $-2147483648, %edi # imm = 0x80000000
-; CHECK-NEXT:    sete %al
+; CHECK-NEXT:    negl %edi
+; CHECK-NEXT:    seto %al
 ; CHECK-NEXT:    retq
   %1 = sdiv i32 %x, -2147483648
   ret i32 %1
diff --git a/llvm/test/CodeGen/X86/is_fpclass.ll b/llvm/test/CodeGen/X86/is_fpclass.ll
index 2046d790cc57e..780341c4b6821 100644
--- a/llvm/test/CodeGen/X86/is_fpclass.ll
+++ b/llvm/test/CodeGen/X86/is_fpclass.ll
@@ -936,15 +936,16 @@ entry:
 define i1 @is_minus_zero_f(float %x) {
 ; CHECK-32-LABEL: is_minus_zero_f:
 ; CHECK-32:       # %bb.0: # %entry
-; CHECK-32-NEXT:    cmpl $-2147483648, {{[0-9]+}}(%esp) # imm = 0x80000000
-; CHECK-32-NEXT:    sete %al
+; CHECK-32-NEXT:    xorl %eax, %eax
+; CHECK-32-NEXT:    cmpl {{[0-9]+}}(%esp), %eax
+; CHECK-32-NEXT:    seto %al
 ; CHECK-32-NEXT:    retl
 ;
 ; CHECK-64-LABEL: is_minus_zero_f:
 ; CHECK-64:       # %bb.0: # %entry
 ; CHECK-64-NEXT:    movd %xmm0, %eax
-; CHECK-64-NEXT:    cmpl $-2147483648, %eax # imm = 0x80000000
-; CHECK-64-NEXT:    sete %al
+; CHECK-64-NEXT:    negl %eax
+; CHECK-64-NEXT:    seto %al
 ; CHECK-64-NEXT:    retq
 entry:
   %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 32)  ; 0x20 = "-zero"
@@ -954,15 +955,16 @@ entry:
 define i1 @not_is_minus_zero_f(float %x) {
 ; CHECK-32-LABEL: not_is_minus_zero_f:
 ; CHECK-32:       # %bb.0: # %entry
-; CHECK-32-NEXT:    cmpl $-2147483648, {{[0-9]+}}(%esp) # imm = 0x80000000
-; CHECK-32-NEXT:    setne %al
+; CHECK-32-NEXT:    xorl %eax, %eax
+; CHECK-32-NEXT:    cmpl {{[0-9]+}}(%esp), %eax
+; CHECK-32-NEXT:    setno %al
 ; CHECK-32-NEXT:    retl
 ;
 ; CHECK-64-LABEL: not_is_minus_zero_f:
 ; CHECK-64:       # %bb.0: # %entry
 ; CHECK-64-NEXT:    movd %xmm0, %eax
-; CHECK-64-NEXT:    cmpl $-2147483648, %eax # imm = 0x80000000
-; CHECK-64-NEXT:    setne %al
+; CHECK-64-NEXT:    negl %eax
+; CHECK-64-NEXT:    setno %al
 ; CHECK-64-NEXT:    retq
 entry:
   %0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 991)  ; ~0x20 = ~"-zero"
diff --git a/llvm/test/CodeGen/X86/lsr-overflow.ll b/llvm/test/CodeGen/X86/lsr-overflow.ll
index 09c1c07ef3de0..79440c282be75 100644
--- a/llvm/test/CodeGen/X86/lsr-overflow.ll
+++ b/llvm/test/CodeGen/X86/lsr-overflow.ll
@@ -4,9 +4,9 @@
 ; The comparison uses the pre-inc value, which could lead LSR to
 ; try to compute -INT64_MIN.
 
-; CHECK: movabsq $-9223372036854775808, %rax
-; CHECK: cmpq  %rax,
-; CHECK: sete  %al
+; CHECK-NOT: movabsq $-9223372036854775808, %rax
+; CHECK: negq  %r
+; CHECK-NEXT: seto  %al
 
 declare i64 @bar()
 
diff --git a/llvm/test/CodeGen/X86/shrink-compare-pgso.ll b/llvm/test/CodeGen/X86/shrink-compare-pgso.ll
index 254b8fe3fc6e3..5a15ee36c0726 100644
--- a/llvm/test/CodeGen/X86/shrink-compare-pgso.ll
+++ b/llvm/test/CodeGen/X86/shrink-compare-pgso.ll
@@ -265,8 +265,8 @@ if.end:
 define dso_local void @test_sext_i8_icmp_neg128(i8 %x) nounwind !prof !14 {
 ; CHECK-LABEL: test_sext_i8_icmp_neg128:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    cmpb $-128, %dil
-; CHECK-NEXT:    je bar # TAILCALL
+; CHECK-NEXT:    negb %dil
+; CHECK-NEXT:    jo bar # TAILCALL
 ; CHECK-NEXT:  # %bb.1: # %if.end
 ; CHECK-NEXT:    retq
 entry:
diff --git a/llvm/test/CodeGen/X86/shrink-compare.ll b/llvm/test/CodeGen/X86/shrink-compare.ll
index 840167ff9f4a0..1a61451c26a03 100644
--- a/llvm/test/CodeGen/X86/shrink-compare.ll
+++ b/llvm/test/CodeGen/X86/shrink-compare.ll
@@ -265,8 +265,8 @@ if.end:
 define dso_local void @test_sext_i8_icmp_neg128(i8 %x) nounwind minsize {
 ; CHECK-LABEL: test_sext_i8_icmp_neg128:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    cmpb $-128, %dil
-; CHECK-NEXT:    je bar # TAILCALL
+; CHECK-NEXT:    negb %dil
+; CHECK-NEXT:    jo bar # TAILCALL
 ; CHECK-NEXT:  # %bb.1: # %if.end
 ; CHECK-NEXT:    retq
 entry:



More information about the llvm-commits mailing list