]> granicus.if.org Git - llvm/commitdiff
[TargetLowering] Simplify (ctpop x) == 1
authorDavid Bolvansky <david.bolvansky@gmail.com>
Sun, 9 Jun 2019 18:18:57 +0000 (18:18 +0000)
committerDavid Bolvansky <david.bolvansky@gmail.com>
Sun, 9 Jun 2019 18:18:57 +0000 (18:18 +0000)
Reviewers: craig.topper, spatel, RKSimon, bkramer

Reviewed By: spatel

Subscribers: javed.absar, lebedev.ri, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D63004

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362912 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/TargetLowering.cpp
test/CodeGen/AArch64/arm64-popcnt.ll
test/CodeGen/X86/ctpop-combine.ll

index c2123dbfdd95fd60be80d2eae1c8d5f50aaa9305..7d93e8685e87ee802fc0e007e6d1cbbf5671156f 100644 (file)
@@ -2691,7 +2691,18 @@ SDValue TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
         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 a9cec13d343c195933713c32a9d21c422bfdb00e..3c3bc4765e7a62681efe61759de8cf648c65bece 100644 (file)
@@ -326,37 +326,17 @@ define i32 @ctpop_eq_one(i64 %x) nounwind readnone {
 ;
 ; 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 d1a888396f39192cbd821a651d97c7cb8454fd66..41a7d93025dd1f9e295338b9f65bf6137ccc40a7 100644 (file)
@@ -122,28 +122,13 @@ define i32 @ctpop_eq_one(i64 %x) nounwind readnone {
 ;
 ; 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