diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -3910,6 +3910,17 @@ return DAG.getSetCC(dl, VT, N0.getOperand(0), N1, Cond); } + // Fold set_cc seteq (ashr X, BW-1), -1 -> set_cc setlt X, 0 + // and set_cc setne (ashr X, BW-1), -1 -> set_cc setge X, 0 + if ((Cond == ISD::SETEQ || Cond == ISD::SETNE) && + N0.getOpcode() == ISD::SRA && isa(N0.getOperand(1)) && + N0.getConstantOperandAPInt(1) == OpVT.getScalarSizeInBits() - 1 && + N1C && N1C->isAllOnesValue()) { + return DAG.getSetCC(dl, VT, N0.getOperand(0), + DAG.getConstant(0, dl, OpVT), + Cond == ISD::SETEQ ? ISD::SETLT : ISD::SETGT); + } + if (SDValue V = optimizeSetCCOfSignedTruncationCheck(VT, N0, N1, Cond, DCI, dl)) return V; diff --git a/llvm/test/CodeGen/AArch64/select-constant-xor.ll b/llvm/test/CodeGen/AArch64/select-constant-xor.ll --- a/llvm/test/CodeGen/AArch64/select-constant-xor.ll +++ b/llvm/test/CodeGen/AArch64/select-constant-xor.ll @@ -103,9 +103,8 @@ define i32 @icmpasreq(i32 %input, i32 %a, i32 %b) { ; CHECK-LABEL: icmpasreq: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #-1 -; CHECK-NEXT: cmp w8, w0, asr #31 -; CHECK-NEXT: csel w0, w1, w2, eq +; CHECK-NEXT: cmp w0, #0 +; CHECK-NEXT: csel w0, w1, w2, lt ; CHECK-NEXT: ret %sh = ashr i32 %input, 31 %c = icmp eq i32 %sh, -1 @@ -116,9 +115,8 @@ define i32 @icmpasrne(i32 %input, i32 %a, i32 %b) { ; CHECK-LABEL: icmpasrne: ; CHECK: // %bb.0: -; CHECK-NEXT: mov w8, #-1 -; CHECK-NEXT: cmp w8, w0, asr #31 -; CHECK-NEXT: csel w0, w1, w2, ne +; CHECK-NEXT: cmp w0, #0 +; CHECK-NEXT: csel w0, w1, w2, gt ; CHECK-NEXT: ret %sh = ashr i32 %input, 31 %c = icmp ne i32 %sh, -1 diff --git a/llvm/test/CodeGen/AMDGPU/select-constant-xor.ll b/llvm/test/CodeGen/AMDGPU/select-constant-xor.ll --- a/llvm/test/CodeGen/AMDGPU/select-constant-xor.ll +++ b/llvm/test/CodeGen/AMDGPU/select-constant-xor.ll @@ -123,8 +123,7 @@ ; CHECK: ; %bb.0: ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CHECK-NEXT: s_waitcnt_vscnt null, 0x0 -; CHECK-NEXT: v_ashrrev_i32_e32 v0, 31, v0 -; CHECK-NEXT: v_cmp_eq_u32_e32 vcc_lo, -1, v0 +; CHECK-NEXT: v_cmp_gt_i32_e32 vcc_lo, 0, v0 ; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc_lo ; CHECK-NEXT: s_setpc_b64 s[30:31] %sh = ashr i32 %input, 31 @@ -138,8 +137,7 @@ ; CHECK: ; %bb.0: ; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) ; CHECK-NEXT: s_waitcnt_vscnt null, 0x0 -; CHECK-NEXT: v_ashrrev_i32_e32 v0, 31, v0 -; CHECK-NEXT: v_cmp_ne_u32_e32 vcc_lo, -1, v0 +; CHECK-NEXT: v_cmp_lt_i32_e32 vcc_lo, 0, v0 ; CHECK-NEXT: v_cndmask_b32_e32 v0, v2, v1, vcc_lo ; CHECK-NEXT: s_setpc_b64 s[30:31] %sh = ashr i32 %input, 31 diff --git a/llvm/test/CodeGen/ARM/select-constant-xor.ll b/llvm/test/CodeGen/ARM/select-constant-xor.ll --- a/llvm/test/CodeGen/ARM/select-constant-xor.ll +++ b/llvm/test/CodeGen/ARM/select-constant-xor.ll @@ -353,17 +353,15 @@ define i32 @icmpasreq(i32 %input, i32 %a, i32 %b) { ; CHECK7A-LABEL: icmpasreq: ; CHECK7A: @ %bb.0: -; CHECK7A-NEXT: mvn r3, #0 -; CHECK7A-NEXT: cmp r3, r0, asr #31 -; CHECK7A-NEXT: movne r1, r2 +; CHECK7A-NEXT: cmp r0, #0 +; CHECK7A-NEXT: movpl r1, r2 ; CHECK7A-NEXT: mov r0, r1 ; CHECK7A-NEXT: bx lr ; ; CHECK6M-LABEL: icmpasreq: ; CHECK6M: @ %bb.0: -; CHECK6M-NEXT: asrs r0, r0, #31 -; CHECK6M-NEXT: adds r0, r0, #1 -; CHECK6M-NEXT: beq .LBB8_2 +; CHECK6M-NEXT: cmp r0, #0 +; CHECK6M-NEXT: bmi .LBB8_2 ; CHECK6M-NEXT: @ %bb.1: ; CHECK6M-NEXT: mov r1, r2 ; CHECK6M-NEXT: .LBB8_2: @@ -372,18 +370,16 @@ ; ; CHECK7M-LABEL: icmpasreq: ; CHECK7M: @ %bb.0: -; CHECK7M-NEXT: asrs r0, r0, #31 -; CHECK7M-NEXT: adds r0, #1 -; CHECK7M-NEXT: it ne -; CHECK7M-NEXT: movne r1, r2 +; CHECK7M-NEXT: cmp r0, #0 +; CHECK7M-NEXT: it pl +; CHECK7M-NEXT: movpl r1, r2 ; CHECK7M-NEXT: mov r0, r1 ; CHECK7M-NEXT: bx lr ; ; CHECK81M-LABEL: icmpasreq: ; CHECK81M: @ %bb.0: -; CHECK81M-NEXT: asrs r0, r0, #31 -; CHECK81M-NEXT: adds r0, #1 -; CHECK81M-NEXT: csel r0, r1, r2, eq +; CHECK81M-NEXT: cmp r0, #0 +; CHECK81M-NEXT: csel r0, r1, r2, mi ; CHECK81M-NEXT: bx lr %sh = ashr i32 %input, 31 %c = icmp eq i32 %sh, -1 @@ -394,17 +390,15 @@ define i32 @icmpasrne(i32 %input, i32 %a, i32 %b) { ; CHECK7A-LABEL: icmpasrne: ; CHECK7A: @ %bb.0: -; CHECK7A-NEXT: mvn r3, #0 -; CHECK7A-NEXT: cmp r3, r0, asr #31 -; CHECK7A-NEXT: moveq r1, r2 +; CHECK7A-NEXT: cmp r0, #0 +; CHECK7A-NEXT: movle r1, r2 ; CHECK7A-NEXT: mov r0, r1 ; CHECK7A-NEXT: bx lr ; ; CHECK6M-LABEL: icmpasrne: ; CHECK6M: @ %bb.0: -; CHECK6M-NEXT: asrs r0, r0, #31 -; CHECK6M-NEXT: adds r0, r0, #1 -; CHECK6M-NEXT: bne .LBB9_2 +; CHECK6M-NEXT: cmp r0, #0 +; CHECK6M-NEXT: bgt .LBB9_2 ; CHECK6M-NEXT: @ %bb.1: ; CHECK6M-NEXT: mov r1, r2 ; CHECK6M-NEXT: .LBB9_2: @@ -413,18 +407,16 @@ ; ; CHECK7M-LABEL: icmpasrne: ; CHECK7M: @ %bb.0: -; CHECK7M-NEXT: asrs r0, r0, #31 -; CHECK7M-NEXT: adds r0, #1 -; CHECK7M-NEXT: it eq -; CHECK7M-NEXT: moveq r1, r2 +; CHECK7M-NEXT: cmp r0, #0 +; CHECK7M-NEXT: it le +; CHECK7M-NEXT: movle r1, r2 ; CHECK7M-NEXT: mov r0, r1 ; CHECK7M-NEXT: bx lr ; ; CHECK81M-LABEL: icmpasrne: ; CHECK81M: @ %bb.0: -; CHECK81M-NEXT: asrs r0, r0, #31 -; CHECK81M-NEXT: adds r0, #1 -; CHECK81M-NEXT: csel r0, r1, r2, ne +; CHECK81M-NEXT: cmp r0, #0 +; CHECK81M-NEXT: csel r0, r1, r2, gt ; CHECK81M-NEXT: bx lr %sh = ashr i32 %input, 31 %c = icmp ne i32 %sh, -1 diff --git a/llvm/test/CodeGen/PowerPC/select-constant-xor.ll b/llvm/test/CodeGen/PowerPC/select-constant-xor.ll --- a/llvm/test/CodeGen/PowerPC/select-constant-xor.ll +++ b/llvm/test/CodeGen/PowerPC/select-constant-xor.ll @@ -113,9 +113,8 @@ define i32 @icmpasreq(i32 %input, i32 %a, i32 %b) { ; CHECK-LABEL: icmpasreq: ; CHECK: # %bb.0: -; CHECK-NEXT: srawi 3, 3, 31 -; CHECK-NEXT: cmpwi 3, -1 -; CHECK-NEXT: iseleq 3, 4, 5 +; CHECK-NEXT: cmpwi 3, 0 +; CHECK-NEXT: isellt 3, 4, 5 ; CHECK-NEXT: blr %sh = ashr i32 %input, 31 %c = icmp eq i32 %sh, -1 @@ -126,9 +125,8 @@ define i32 @icmpasrne(i32 %input, i32 %a, i32 %b) { ; CHECK-LABEL: icmpasrne: ; CHECK: # %bb.0: -; CHECK-NEXT: srawi 3, 3, 31 -; CHECK-NEXT: cmpwi 3, -1 -; CHECK-NEXT: iseleq 3, 5, 4 +; CHECK-NEXT: cmpwi 3, 0 +; CHECK-NEXT: iselgt 3, 4, 5 ; CHECK-NEXT: blr %sh = ashr i32 %input, 31 %c = icmp ne i32 %sh, -1 diff --git a/llvm/test/CodeGen/RISCV/select-constant-xor.ll b/llvm/test/CodeGen/RISCV/select-constant-xor.ll --- a/llvm/test/CodeGen/RISCV/select-constant-xor.ll +++ b/llvm/test/CodeGen/RISCV/select-constant-xor.ll @@ -202,21 +202,18 @@ define i32 @icmpasreq(i32 %input, i32 %a, i32 %b) { ; CHECK32-LABEL: icmpasreq: ; CHECK32: # %bb.0: -; CHECK32-NEXT: srai a3, a0, 31 -; CHECK32-NEXT: addi a4, zero, -1 -; CHECK32-NEXT: mv a0, a1 -; CHECK32-NEXT: beq a3, a4, .LBB8_2 +; CHECK32-NEXT: bltz a0, .LBB8_2 ; CHECK32-NEXT: # %bb.1: -; CHECK32-NEXT: mv a0, a2 +; CHECK32-NEXT: mv a1, a2 ; CHECK32-NEXT: .LBB8_2: +; CHECK32-NEXT: mv a0, a1 ; CHECK32-NEXT: ret ; ; CHECK64-LABEL: icmpasreq: ; CHECK64: # %bb.0: -; CHECK64-NEXT: sraiw a3, a0, 31 -; CHECK64-NEXT: addi a4, zero, -1 +; CHECK64-NEXT: sext.w a3, a0 ; CHECK64-NEXT: mv a0, a1 -; CHECK64-NEXT: beq a3, a4, .LBB8_2 +; CHECK64-NEXT: bltz a3, .LBB8_2 ; CHECK64-NEXT: # %bb.1: ; CHECK64-NEXT: mv a0, a2 ; CHECK64-NEXT: .LBB8_2: @@ -230,21 +227,18 @@ define i32 @icmpasrne(i32 %input, i32 %a, i32 %b) { ; CHECK32-LABEL: icmpasrne: ; CHECK32: # %bb.0: -; CHECK32-NEXT: srai a3, a0, 31 -; CHECK32-NEXT: addi a4, zero, -1 -; CHECK32-NEXT: mv a0, a1 -; CHECK32-NEXT: bne a3, a4, .LBB9_2 +; CHECK32-NEXT: bgtz a0, .LBB9_2 ; CHECK32-NEXT: # %bb.1: -; CHECK32-NEXT: mv a0, a2 +; CHECK32-NEXT: mv a1, a2 ; CHECK32-NEXT: .LBB9_2: +; CHECK32-NEXT: mv a0, a1 ; CHECK32-NEXT: ret ; ; CHECK64-LABEL: icmpasrne: ; CHECK64: # %bb.0: -; CHECK64-NEXT: sraiw a3, a0, 31 -; CHECK64-NEXT: addi a4, zero, -1 +; CHECK64-NEXT: sext.w a3, a0 ; CHECK64-NEXT: mv a0, a1 -; CHECK64-NEXT: bne a3, a4, .LBB9_2 +; CHECK64-NEXT: bgtz a3, .LBB9_2 ; CHECK64-NEXT: # %bb.1: ; CHECK64-NEXT: mv a0, a2 ; CHECK64-NEXT: .LBB9_2: diff --git a/llvm/test/CodeGen/X86/select-constant-xor.ll b/llvm/test/CodeGen/X86/select-constant-xor.ll --- a/llvm/test/CodeGen/X86/select-constant-xor.ll +++ b/llvm/test/CodeGen/X86/select-constant-xor.ll @@ -115,9 +115,8 @@ ; CHECK-LABEL: icmpasreq: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %esi, %eax -; CHECK-NEXT: sarl $31, %edi -; CHECK-NEXT: cmpl $-1, %edi -; CHECK-NEXT: cmovnel %edx, %eax +; CHECK-NEXT: testl %edi, %edi +; CHECK-NEXT: cmovnsl %edx, %eax ; CHECK-NEXT: retq %sh = ashr i32 %input, 31 %c = icmp eq i32 %sh, -1 @@ -129,9 +128,8 @@ ; CHECK-LABEL: icmpasrne: ; CHECK: # %bb.0: ; CHECK-NEXT: movl %esi, %eax -; CHECK-NEXT: sarl $31, %edi -; CHECK-NEXT: cmpl $-1, %edi -; CHECK-NEXT: cmovel %edx, %eax +; CHECK-NEXT: testl %edi, %edi +; CHECK-NEXT: cmovlel %edx, %eax ; CHECK-NEXT: retq %sh = ashr i32 %input, 31 %c = icmp ne i32 %sh, -1