[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
Tue Jun 11 07:58:00 PDT 2024
https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/94948
>From c8af776a9a3033f63e56227a46360078a08400bc 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 1/2] [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 | 36 +++++++------------
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, 45 insertions(+), 43 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index cad3ea4716db3..9628e67471060 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 dde877c5bb61e..cf51d713fb6cf 100644
--- a/llvm/test/CodeGen/X86/abs.ll
+++ b/llvm/test/CodeGen/X86/abs.ll
@@ -718,17 +718,18 @@ define i8 @test_minsigned_i8(i8 %a0, i8 %a1) nounwind {
; X64-NEXT: movl %edi, %ecx
; X64-NEXT: xorb %al, %cl
; X64-NEXT: subb %al, %cl
-; X64-NEXT: cmpb $-128, %dil
+; X64-NEXT: negb %dil
; X64-NEXT: movzbl %cl, %eax
-; X64-NEXT: cmovel %esi, %eax
+; X64-NEXT: cmovol %esi, %eax
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq
;
; 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:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: # kill: def $al killed $al killed $eax
@@ -750,12 +751,10 @@ 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, %ecx
-; X64-NEXT: movl %ecx, %eax
+; X64-NEXT: movl %edi, %eax
; X64-NEXT: negw %ax
-; X64-NEXT: cmovsw %cx, %ax
-; X64-NEXT: cmpl $32768, %ecx # imm = 0x8000
-; X64-NEXT: cmovel %esi, %eax
+; X64-NEXT: cmovsw %di, %ax
+; X64-NEXT: cmovol %esi, %eax
; X64-NEXT: # kill: def $ax killed $ax killed $eax
; X64-NEXT: retq
;
@@ -765,11 +764,7 @@ define i16 @test_minsigned_i16(i16 %a0, i16 %a1) nounwind {
; X86-NEXT: movl %ecx, %eax
; X86-NEXT: negw %ax
; X86-NEXT: cmovsw %cx, %ax
-; X86-NEXT: cmpl $32768, %ecx # imm = 0x8000
-; X86-NEXT: jne .LBB18_2
-; X86-NEXT: # %bb.1:
-; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: .LBB18_2:
+; X86-NEXT: cmovow {{[0-9]+}}(%esp), %ax
; X86-NEXT: retl
%lim = icmp eq i16 %a0, -32768
%abs = tail call i16 @llvm.abs.i16(i16 %a0, i1 false)
@@ -783,8 +778,7 @@ define i32 @test_minsigned_i32(i32 %a0, i32 %a1) nounwind {
; X64-NEXT: movl %edi, %eax
; X64-NEXT: negl %eax
; X64-NEXT: cmovsl %edi, %eax
-; X64-NEXT: cmpl $-2147483648, %edi # imm = 0x80000000
-; X64-NEXT: cmovel %esi, %eax
+; X64-NEXT: cmovol %esi, %eax
; X64-NEXT: retq
;
; X86-LABEL: test_minsigned_i32:
@@ -793,11 +787,7 @@ define i32 @test_minsigned_i32(i32 %a0, i32 %a1) nounwind {
; X86-NEXT: movl %ecx, %eax
; X86-NEXT: negl %eax
; X86-NEXT: cmovsl %ecx, %eax
-; X86-NEXT: cmpl $-2147483648, %ecx # imm = 0x80000000
-; X86-NEXT: jne .LBB19_2
-; X86-NEXT: # %bb.1:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: .LBB19_2:
+; X86-NEXT: cmovol {{[0-9]+}}(%esp), %eax
; X86-NEXT: retl
%lim = icmp eq i32 %a0, -2147483648
%abs = tail call i32 @llvm.abs.i32(i32 %a0, i1 false)
@@ -811,9 +801,7 @@ define i64 @test_minsigned_i64(i64 %a0, i64 %a1) nounwind {
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: negq %rax
; X64-NEXT: cmovsq %rdi, %rax
-; X64-NEXT: movabsq $-9223372036854775808, %rcx # imm = 0x8000000000000000
-; X64-NEXT: cmpq %rcx, %rdi
-; X64-NEXT: cmoveq %rsi, %rax
+; X64-NEXT: cmovoq %rsi, %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 999be0f98b6fc..532b2c09a9175 100644
--- a/llvm/test/CodeGen/X86/is_fpclass.ll
+++ b/llvm/test/CodeGen/X86/is_fpclass.ll
@@ -937,15 +937,16 @@ entry:
define i1 @is_minus_zero_f(float %x) {
; X86-LABEL: is_minus_zero_f:
; X86: # %bb.0: # %entry
-; X86-NEXT: cmpl $-2147483648, {{[0-9]+}}(%esp) # imm = 0x80000000
-; X86-NEXT: sete %al
+; X86-NEXT: xorl %eax, %eax
+; X86-NEXT: cmpl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: seto %al
; X86-NEXT: retl
;
; X64-LABEL: is_minus_zero_f:
; X64: # %bb.0: # %entry
; X64-NEXT: movd %xmm0, %eax
-; X64-NEXT: cmpl $-2147483648, %eax # imm = 0x80000000
-; X64-NEXT: sete %al
+; X64-NEXT: negl %eax
+; X64-NEXT: seto %al
; X64-NEXT: retq
entry:
%0 = tail call i1 @llvm.is.fpclass.f32(float %x, i32 32) ; 0x20 = "-zero"
@@ -955,15 +956,16 @@ entry:
define i1 @not_is_minus_zero_f(float %x) {
; X86-LABEL: not_is_minus_zero_f:
; X86: # %bb.0: # %entry
-; X86-NEXT: cmpl $-2147483648, {{[0-9]+}}(%esp) # imm = 0x80000000
-; X86-NEXT: setne %al
+; X86-NEXT: xorl %eax, %eax
+; X86-NEXT: cmpl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: setno %al
; X86-NEXT: retl
;
; X64-LABEL: not_is_minus_zero_f:
; X64: # %bb.0: # %entry
; X64-NEXT: movd %xmm0, %eax
-; X64-NEXT: cmpl $-2147483648, %eax # imm = 0x80000000
-; X64-NEXT: setne %al
+; X64-NEXT: negl %eax
+; X64-NEXT: setno %al
; X64-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:
>From fedeabaa2a6608277c6fd26e2f65f1112d6070a1 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Tue, 11 Jun 2024 12:03:50 +0100
Subject: [PATCH 2/2] [X86] Limit i8/i16 eq/ne MIN_SIGNED_INT to one use only
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 14 ++++++++------
llvm/test/CodeGen/X86/abs.ll | 23 ++++++++++++++---------
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 9628e67471060..0d79e4eb3f75a 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -23820,12 +23820,14 @@ SDValue X86TargetLowering::emitFlagsForSetcc(SDValue Op0, SDValue Op1,
// 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);
+ if (VT == MVT::i32 || VT == MVT::i64 || Op0->hasOneUse()) {
+ 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:
diff --git a/llvm/test/CodeGen/X86/abs.ll b/llvm/test/CodeGen/X86/abs.ll
index cf51d713fb6cf..bae140abdf6b1 100644
--- a/llvm/test/CodeGen/X86/abs.ll
+++ b/llvm/test/CodeGen/X86/abs.ll
@@ -718,18 +718,17 @@ define i8 @test_minsigned_i8(i8 %a0, i8 %a1) nounwind {
; X64-NEXT: movl %edi, %ecx
; X64-NEXT: xorb %al, %cl
; X64-NEXT: subb %al, %cl
-; X64-NEXT: negb %dil
+; X64-NEXT: cmpb $-128, %dil
; X64-NEXT: movzbl %cl, %eax
-; X64-NEXT: cmovol %esi, %eax
+; X64-NEXT: cmovel %esi, %eax
; X64-NEXT: # kill: def $al killed $al killed $eax
; X64-NEXT: retq
;
; X86-LABEL: test_minsigned_i8:
; X86: # %bb.0:
; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movl %eax, %ecx
-; X86-NEXT: negb %cl
-; X86-NEXT: jno .LBB17_1
+; X86-NEXT: cmpb $-128, %al
+; X86-NEXT: jne .LBB17_1
; X86-NEXT: # %bb.2:
; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-NEXT: # kill: def $al killed $al killed $eax
@@ -751,10 +750,12 @@ 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: movl %edi, %eax
+; X64-NEXT: movzwl %di, %ecx
+; X64-NEXT: movl %ecx, %eax
; X64-NEXT: negw %ax
-; X64-NEXT: cmovsw %di, %ax
-; X64-NEXT: cmovol %esi, %eax
+; X64-NEXT: cmovsw %cx, %ax
+; X64-NEXT: cmpl $32768, %ecx # imm = 0x8000
+; X64-NEXT: cmovel %esi, %eax
; X64-NEXT: # kill: def $ax killed $ax killed $eax
; X64-NEXT: retq
;
@@ -764,7 +765,11 @@ define i16 @test_minsigned_i16(i16 %a0, i16 %a1) nounwind {
; X86-NEXT: movl %ecx, %eax
; X86-NEXT: negw %ax
; X86-NEXT: cmovsw %cx, %ax
-; X86-NEXT: cmovow {{[0-9]+}}(%esp), %ax
+; X86-NEXT: cmpl $32768, %ecx # imm = 0x8000
+; X86-NEXT: jne .LBB18_2
+; X86-NEXT: # %bb.1:
+; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: .LBB18_2:
; X86-NEXT: retl
%lim = icmp eq i16 %a0, -32768
%abs = tail call i16 @llvm.abs.i16(i16 %a0, i1 false)
More information about the llvm-commits
mailing list