From c8af776a9a3033f63e56227a46360078a08400bc Mon Sep 17 00:00:00 2001 From: Simon Pilgrim 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 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)