Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2689,7 +2689,18 @@ return DAG.getSetCC(dl, VT, And, DAG.getConstant(0, dl, CTVT), CC); } - // TODO: (ctpop x) == 1 -> x && (x & x-1) == 0 iff ctpop is illegal. + // (ctpop x) == 1 -> x && (x & x-1) == 0 iff ctpop is illegal. + if (Cond == ISD::SETEQ && C1 == 1 && + !isOperationLegalOrCustom(ISD::CTPOP, CTVT)) { + SDValue Sub = + DAG.getNode(ISD::SUB, dl, CTVT, CTOp, DAG.getConstant(1, dl, CTVT)); + SDValue And = DAG.getNode(ISD::AND, dl, CTVT, CTOp, Sub); + SDValue LHS = DAG.getSetCC(dl, VT, CTOp, DAG.getConstant(0, dl, CTVT), + ISD::SETUGT); + SDValue RHS = + DAG.getSetCC(dl, VT, And, DAG.getConstant(0, dl, CTVT), ISD::SETEQ); + return DAG.getNode(ISD::AND, dl, VT, LHS, RHS); + } } // (zext x) == C --> x == (trunc C) Index: test/CodeGen/AArch64/arm64-popcnt.ll =================================================================== --- test/CodeGen/AArch64/arm64-popcnt.ll +++ test/CodeGen/AArch64/arm64-popcnt.ll @@ -326,37 +326,17 @@ ; ; CHECK-ARM8A-NEON-LABEL: ctpop_eq_one: ; CHECK-ARM8A-NEON: @ %bb.0: -; CHECK-ARM8A-NEON-NEXT: push {r11, lr} -; CHECK-ARM8A-NEON-NEXT: movw r12, #21845 -; CHECK-ARM8A-NEON-NEXT: movw lr, #3855 -; CHECK-ARM8A-NEON-NEXT: movt r12, #21845 -; CHECK-ARM8A-NEON-NEXT: and r3, r12, r0, lsr #1 -; CHECK-ARM8A-NEON-NEXT: sub r0, r0, r3 -; CHECK-ARM8A-NEON-NEXT: movw r3, #13107 -; CHECK-ARM8A-NEON-NEXT: movt r3, #13107 -; CHECK-ARM8A-NEON-NEXT: and r2, r0, r3 -; CHECK-ARM8A-NEON-NEXT: and r0, r3, r0, lsr #2 -; CHECK-ARM8A-NEON-NEXT: movt lr, #3855 -; CHECK-ARM8A-NEON-NEXT: add r0, r2, r0 -; CHECK-ARM8A-NEON-NEXT: and r2, r12, r1, lsr #1 -; CHECK-ARM8A-NEON-NEXT: sub r1, r1, r2 -; CHECK-ARM8A-NEON-NEXT: and r2, r1, r3 -; CHECK-ARM8A-NEON-NEXT: add r0, r0, r0, lsr #4 -; CHECK-ARM8A-NEON-NEXT: and r1, r3, r1, lsr #2 -; CHECK-ARM8A-NEON-NEXT: and r0, r0, lr -; CHECK-ARM8A-NEON-NEXT: add r1, r2, r1 -; CHECK-ARM8A-NEON-NEXT: movw r2, #257 -; CHECK-ARM8A-NEON-NEXT: movt r2, #257 -; CHECK-ARM8A-NEON-NEXT: add r1, r1, r1, lsr #4 -; CHECK-ARM8A-NEON-NEXT: mul r0, r0, r2 -; CHECK-ARM8A-NEON-NEXT: and r1, r1, lr -; CHECK-ARM8A-NEON-NEXT: mul r1, r1, r2 -; CHECK-ARM8A-NEON-NEXT: lsr r0, r0, #24 -; CHECK-ARM8A-NEON-NEXT: add r0, r0, r1, lsr #24 -; CHECK-ARM8A-NEON-NEXT: eor r0, r0, #1 -; CHECK-ARM8A-NEON-NEXT: clz r0, r0 -; CHECK-ARM8A-NEON-NEXT: lsr r0, r0, #5 -; CHECK-ARM8A-NEON-NEXT: pop {r11, pc} +; CHECK-ARM8A-NEON-NEXT: subs r2, r0, #1 +; CHECK-ARM8A-NEON-NEXT: sbc r3, r1, #0 +; CHECK-ARM8A-NEON-NEXT: and r2, r0, r2 +; CHECK-ARM8A-NEON-NEXT: and r3, r1, r3 +; CHECK-ARM8A-NEON-NEXT: orrs r0, r0, r1 +; CHECK-ARM8A-NEON-NEXT: orr r2, r2, r3 +; CHECK-ARM8A-NEON-NEXT: movwne r0, #1 +; CHECK-ARM8A-NEON-NEXT: clz r2, r2 +; CHECK-ARM8A-NEON-NEXT: lsr r2, r2, #5 +; CHECK-ARM8A-NEON-NEXT: and r0, r0, r2 +; CHECK-ARM8A-NEON-NEXT: bx lr %count = tail call i64 @llvm.ctpop.i64(i64 %x) %cmp = icmp eq i64 %count, 1 %conv = zext i1 %cmp to i32 Index: test/CodeGen/X86/ctpop-combine.ll =================================================================== --- test/CodeGen/X86/ctpop-combine.ll +++ test/CodeGen/X86/ctpop-combine.ll @@ -122,28 +122,13 @@ ; ; NO-POPCOUNT-LABEL: ctpop_eq_one: ; NO-POPCOUNT: # %bb.0: -; NO-POPCOUNT-NEXT: movq %rdi, %rax -; NO-POPCOUNT-NEXT: shrq %rax -; NO-POPCOUNT-NEXT: movabsq $6148914691236517205, %rcx # imm = 0x5555555555555555 -; NO-POPCOUNT-NEXT: andq %rax, %rcx -; NO-POPCOUNT-NEXT: subq %rcx, %rdi -; NO-POPCOUNT-NEXT: movabsq $3689348814741910323, %rax # imm = 0x3333333333333333 -; NO-POPCOUNT-NEXT: movq %rdi, %rcx -; NO-POPCOUNT-NEXT: andq %rax, %rcx -; NO-POPCOUNT-NEXT: shrq $2, %rdi -; NO-POPCOUNT-NEXT: andq %rax, %rdi -; NO-POPCOUNT-NEXT: addq %rcx, %rdi -; NO-POPCOUNT-NEXT: movq %rdi, %rax -; NO-POPCOUNT-NEXT: shrq $4, %rax -; NO-POPCOUNT-NEXT: addq %rdi, %rax -; NO-POPCOUNT-NEXT: movabsq $1085102592571150095, %rcx # imm = 0xF0F0F0F0F0F0F0F -; NO-POPCOUNT-NEXT: andq %rax, %rcx -; NO-POPCOUNT-NEXT: movabsq $72340172838076673, %rdx # imm = 0x101010101010101 -; NO-POPCOUNT-NEXT: imulq %rcx, %rdx -; NO-POPCOUNT-NEXT: shrq $56, %rdx -; NO-POPCOUNT-NEXT: xorl %eax, %eax -; NO-POPCOUNT-NEXT: cmpq $1, %rdx +; NO-POPCOUNT-NEXT: leaq -1(%rdi), %rax +; NO-POPCOUNT-NEXT: testq %rax, %rdi ; NO-POPCOUNT-NEXT: sete %al +; NO-POPCOUNT-NEXT: testq %rdi, %rdi +; NO-POPCOUNT-NEXT: setne %cl +; NO-POPCOUNT-NEXT: andb %al, %cl +; NO-POPCOUNT-NEXT: movzbl %cl, %eax ; NO-POPCOUNT-NEXT: retq %count = tail call i64 @llvm.ctpop.i64(i64 %x) %cmp = icmp eq i64 %count, 1