Skip to content

Commit

Permalink
[DAG] Generalize setcc(setcc) fold to use known bits.
Browse files Browse the repository at this point in the history
If we have a `SETCC (SETCC), 0, NE` and ZeroOrOneBooleanContent, we can remove
the outer setcc as it will produce the same value as the inner. This can be
generalized to anything where the top bits are known to be 0, as the value will
remain as 1 or 0.
  • Loading branch information
davemgreen committed Feb 6, 2024
1 parent 29fa64f commit 2e3de99
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 48 deletions.
22 changes: 13 additions & 9 deletions llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4718,21 +4718,25 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
DAG.getConstant(C1 & Imm, dl, ExtDstTy), Cond);
} else if ((N1C->isZero() || N1C->isOne()) &&
(Cond == ISD::SETEQ || Cond == ISD::SETNE)) {
// SETCC (SETCC), [0|1], [EQ|NE] -> SETCC
if (N0.getOpcode() == ISD::SETCC &&
// SETCC (X), [0|1], [EQ|NE] -> X if X is known 0/1. i1 types are
// excluded as they are handled below whilst checking for foldBooleans.
if ((N0.getOpcode() == ISD::SETCC || VT.getScalarType() != MVT::i1) &&
isTypeLegal(VT) && VT.bitsLE(N0.getValueType()) &&
(N0.getValueType() == MVT::i1 ||
getBooleanContents(N0.getOperand(0).getValueType()) ==
ZeroOrOneBooleanContent)) {
getBooleanContents(N0.getValueType()) == ZeroOrOneBooleanContent) &&
DAG.MaskedValueIsZero(
N0, APInt::getBitsSetFrom(N0.getValueSizeInBits(), 1))) {
bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (!N1C->isOne());
if (TrueWhenTrue)
return DAG.getNode(ISD::TRUNCATE, dl, VT, N0);
// Invert the condition.
ISD::CondCode CC = cast<CondCodeSDNode>(N0.getOperand(2))->get();
CC = ISD::getSetCCInverse(CC, N0.getOperand(0).getValueType());
if (DCI.isBeforeLegalizeOps() ||
isCondCodeLegal(CC, N0.getOperand(0).getSimpleValueType()))
return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC);
if (N0.getOpcode() == ISD::SETCC) {
ISD::CondCode CC = cast<CondCodeSDNode>(N0.getOperand(2))->get();
CC = ISD::getSetCCInverse(CC, N0.getOperand(0).getValueType());
if (DCI.isBeforeLegalizeOps() ||
isCondCodeLegal(CC, N0.getOperand(0).getSimpleValueType()))
return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC);
}
}

if ((N0.getOpcode() == ISD::XOR ||
Expand Down
5 changes: 2 additions & 3 deletions llvm/test/CodeGen/AArch64/setcc_knownbits.ll
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ define i1 @lshr_ctlz_undef_cmpeq_one_i64(i64 %in) {
; CHECK-LABEL: lshr_ctlz_undef_cmpeq_one_i64:
; CHECK: // %bb.0:
; CHECK-NEXT: clz x8, x0
; CHECK-NEXT: lsr x8, x8, #6
; CHECK-NEXT: cmp x8, #1
; CHECK-NEXT: cset w0, eq
; CHECK-NEXT: lsr x0, x8, #6
; CHECK-NEXT: // kill: def $w0 killed $w0 killed $x0
; CHECK-NEXT: ret
%ctlz = call i64 @llvm.ctlz.i64(i64 %in, i1 -1)
%lshr = lshr i64 %ctlz, 6
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/WebAssembly/xor_reassociate.ll
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ define i32 @reassociate_xor(float %x, float %y) {
; CHECK-NEXT: local.get 0
; CHECK-NEXT: f32.const 0x1p-23
; CHECK-NEXT: f32.gt
; CHECK-NEXT: i32.ne
; CHECK-NEXT: i32.xor
; CHECK-NEXT: br_if 0 # 0: down to label0
; CHECK-NEXT: # %bb.1: # %if.then.i
; CHECK-NEXT: i32.const 0
Expand Down
46 changes: 22 additions & 24 deletions llvm/test/CodeGen/X86/lzcnt-cmp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -50,35 +50,33 @@ define i1 @lshr_ctlz_undef_cmpeq_one_i64(i64 %in) nounwind {
; X86-BSR-NEXT: xorl $31, %eax
; X86-BSR-NEXT: addl $32, %eax
; X86-BSR-NEXT: .LBB1_2:
; X86-BSR-NEXT: testl $-64, %eax
; X86-BSR-NEXT: setne %al
; X86-BSR-NEXT: shrl $6, %eax
; X86-BSR-NEXT: # kill: def $al killed $al killed $eax
; X86-BSR-NEXT: retl
;
; X86-LZCNT-LABEL: lshr_ctlz_undef_cmpeq_one_i64:
; X86-LZCNT: # %bb.0:
; X86-LZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax
; X86-LZCNT-NEXT: addl $32, %eax
; X86-LZCNT-NEXT: xorl %ecx, %ecx
; X86-LZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %ecx
; X86-LZCNT-NEXT: addl $32, %ecx
; X86-LZCNT-NEXT: xorl %eax, %eax
; X86-LZCNT-NEXT: cmpl $0, {{[0-9]+}}(%esp)
; X86-LZCNT-NEXT: cmovel %eax, %ecx
; X86-LZCNT-NEXT: testb $64, %cl
; X86-LZCNT-NEXT: setne %al
; X86-LZCNT-NEXT: cmovel %ecx, %eax
; X86-LZCNT-NEXT: shrl $6, %eax
; X86-LZCNT-NEXT: # kill: def $al killed $al killed $eax
; X86-LZCNT-NEXT: retl
;
; X64-BSR-LABEL: lshr_ctlz_undef_cmpeq_one_i64:
; X64-BSR: # %bb.0:
; X64-BSR-NEXT: bsrq %rdi, %rax
; X64-BSR-NEXT: shrl $6, %eax
; X64-BSR-NEXT: cmpl $1, %eax
; X64-BSR-NEXT: sete %al
; X64-BSR-NEXT: # kill: def $al killed $al killed $rax
; X64-BSR-NEXT: retq
;
; X64-LZCNT-LABEL: lshr_ctlz_undef_cmpeq_one_i64:
; X64-LZCNT: # %bb.0:
; X64-LZCNT-NEXT: lzcntq %rdi, %rax
; X64-LZCNT-NEXT: shrl $6, %eax
; X64-LZCNT-NEXT: cmpl $1, %eax
; X64-LZCNT-NEXT: sete %al
; X64-LZCNT-NEXT: # kill: def $al killed $al killed $rax
; X64-LZCNT-NEXT: retq
%ctlz = call i64 @llvm.ctlz.i64(i64 %in, i1 -1)
%lshr = lshr i64 %ctlz, 6
Expand Down Expand Up @@ -131,33 +129,33 @@ define i1 @lshr_ctlz_undef_cmpne_zero_i64(i64 %in) nounwind {
; X86-BSR-NEXT: xorl $31, %eax
; X86-BSR-NEXT: addl $32, %eax
; X86-BSR-NEXT: .LBB3_2:
; X86-BSR-NEXT: testl $-64, %eax
; X86-BSR-NEXT: setne %al
; X86-BSR-NEXT: shrl $6, %eax
; X86-BSR-NEXT: # kill: def $al killed $al killed $eax
; X86-BSR-NEXT: retl
;
; X86-LZCNT-LABEL: lshr_ctlz_undef_cmpne_zero_i64:
; X86-LZCNT: # %bb.0:
; X86-LZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %eax
; X86-LZCNT-NEXT: addl $32, %eax
; X86-LZCNT-NEXT: xorl %ecx, %ecx
; X86-LZCNT-NEXT: lzcntl {{[0-9]+}}(%esp), %ecx
; X86-LZCNT-NEXT: addl $32, %ecx
; X86-LZCNT-NEXT: xorl %eax, %eax
; X86-LZCNT-NEXT: cmpl $0, {{[0-9]+}}(%esp)
; X86-LZCNT-NEXT: cmovel %eax, %ecx
; X86-LZCNT-NEXT: testb $64, %cl
; X86-LZCNT-NEXT: setne %al
; X86-LZCNT-NEXT: cmovel %ecx, %eax
; X86-LZCNT-NEXT: shrl $6, %eax
; X86-LZCNT-NEXT: # kill: def $al killed $al killed $eax
; X86-LZCNT-NEXT: retl
;
; X64-BSR-LABEL: lshr_ctlz_undef_cmpne_zero_i64:
; X64-BSR: # %bb.0:
; X64-BSR-NEXT: bsrq %rdi, %rax
; X64-BSR-NEXT: testl $-64, %eax
; X64-BSR-NEXT: setne %al
; X64-BSR-NEXT: shrl $6, %eax
; X64-BSR-NEXT: # kill: def $al killed $al killed $rax
; X64-BSR-NEXT: retq
;
; X64-LZCNT-LABEL: lshr_ctlz_undef_cmpne_zero_i64:
; X64-LZCNT: # %bb.0:
; X64-LZCNT-NEXT: lzcntq %rdi, %rax
; X64-LZCNT-NEXT: testb $64, %al
; X64-LZCNT-NEXT: setne %al
; X64-LZCNT-NEXT: shrl $6, %eax
; X64-LZCNT-NEXT: # kill: def $al killed $al killed $rax
; X64-LZCNT-NEXT: retq
%ctlz = call i64 @llvm.ctlz.i64(i64 %in, i1 -1)
%lshr = lshr i64 %ctlz, 6
Expand Down
14 changes: 6 additions & 8 deletions llvm/test/CodeGen/X86/umul_fix_sat.ll
Original file line number Diff line number Diff line change
Expand Up @@ -517,15 +517,13 @@ define i64 @func8(i64 %x, i64 %y) nounwind {
; X86-NEXT: adcl $0, %ecx
; X86-NEXT: addl %ebp, %edx
; X86-NEXT: adcl $0, %ecx
; X86-NEXT: shldl $1, %edx, %ecx
; X86-NEXT: shrdl $31, %edx, %eax
; X86-NEXT: movl %edx, %esi
; X86-NEXT: shrl $31, %esi
; X86-NEXT: xorl %edi, %edi
; X86-NEXT: negl %esi
; X86-NEXT: sbbl %edi, %edi
; X86-NEXT: orl %edi, %eax
; X86-NEXT: shrdl $31, %ecx, %edx
; X86-NEXT: orl %edi, %edx
; X86-NEXT: testl $-2147483648, %edx # imm = 0x80000000
; X86-NEXT: movl $-1, %edx
; X86-NEXT: cmovnel %edx, %eax
; X86-NEXT: cmovnel %edx, %ecx
; X86-NEXT: movl %ecx, %edx
; X86-NEXT: popl %esi
; X86-NEXT: popl %edi
; X86-NEXT: popl %ebx
Expand Down
11 changes: 8 additions & 3 deletions llvm/test/CodeGen/X86/xor.ll
Original file line number Diff line number Diff line change
Expand Up @@ -403,14 +403,19 @@ define i32 @PR17487(i1 %tobool) {
;
; X64-LIN-LABEL: PR17487:
; X64-LIN: # %bb.0:
; X64-LIN-NEXT: movl %edi, %eax
; X64-LIN-NEXT: andl $1, %eax
; X64-LIN-NEXT: movd %edi, %xmm0
; X64-LIN-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,1,0,1]
; X64-LIN-NEXT: pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0
; X64-LIN-NEXT: pextrw $4, %xmm0, %eax
; X64-LIN-NEXT: retq
;
; X64-WIN-LABEL: PR17487:
; X64-WIN: # %bb.0:
; X64-WIN-NEXT: andb $1, %cl
; X64-WIN-NEXT: movzbl %cl, %eax
; X64-WIN-NEXT: movd %eax, %xmm0
; X64-WIN-NEXT: pshufd {{.*#+}} xmm0 = xmm0[0,1,0,1]
; X64-WIN-NEXT: pand __xmm@00000000000000010000000000000001(%rip), %xmm0
; X64-WIN-NEXT: pextrw $4, %xmm0, %eax
; X64-WIN-NEXT: retq
%tmp = insertelement <2 x i1> undef, i1 %tobool, i32 1
%tmp1 = zext <2 x i1> %tmp to <2 x i64>
Expand Down

0 comments on commit 2e3de99

Please sign in to comment.