| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=aarch64-none-eabi | FileCheck %s --check-prefix=NEON |
| ; RUN: llc < %s -mtriple=aarch64-none-eabi -mattr=+sve | FileCheck %s --check-prefix=SVE |
| ; RUN: llc < %s -mtriple=aarch64-none-eabi -mattr=+cssc | FileCheck %s --check-prefix=CSSC |
| |
| ; i256 popcount (register args, result truncated to i64) |
| define i64 @ctpop_i256(i256 %a) nounwind { |
| ; |
| ; |
| ; NEON-LABEL: ctpop_i256: |
| ; NEON: // %bb.0: |
| ; NEON-NEXT: fmov d0, x2 |
| ; NEON-NEXT: fmov d1, x0 |
| ; NEON-NEXT: mov v0.d[1], x3 |
| ; NEON-NEXT: mov v1.d[1], x1 |
| ; NEON-NEXT: cnt v0.16b, v0.16b |
| ; NEON-NEXT: cnt v1.16b, v1.16b |
| ; NEON-NEXT: addv b0, v0.16b |
| ; NEON-NEXT: addv b1, v1.16b |
| ; NEON-NEXT: fmov x8, d0 |
| ; NEON-NEXT: fmov x9, d1 |
| ; NEON-NEXT: add x0, x9, x8 |
| ; NEON-NEXT: ret |
| ; |
| ; SVE-LABEL: ctpop_i256: |
| ; SVE: // %bb.0: |
| ; SVE-NEXT: fmov d0, x2 |
| ; SVE-NEXT: fmov d1, x0 |
| ; SVE-NEXT: ptrue p0.d |
| ; SVE-NEXT: mov v0.d[1], x3 |
| ; SVE-NEXT: mov v1.d[1], x1 |
| ; SVE-NEXT: cnt z0.d, p0/m, z0.d |
| ; SVE-NEXT: cnt z1.d, p0/m, z1.d |
| ; SVE-NEXT: add v0.2d, v1.2d, v0.2d |
| ; SVE-NEXT: addp d0, v0.2d |
| ; SVE-NEXT: fmov x0, d0 |
| ; SVE-NEXT: ret |
| ; |
| ; CSSC-LABEL: ctpop_i256: |
| ; CSSC: // %bb.0: |
| ; CSSC-NEXT: cnt x8, x3 |
| ; CSSC-NEXT: cnt x9, x2 |
| ; CSSC-NEXT: cnt x10, x1 |
| ; CSSC-NEXT: cnt x11, x0 |
| ; CSSC-NEXT: add x8, x9, x8 |
| ; CSSC-NEXT: add x9, x11, x10 |
| ; CSSC-NEXT: add x0, x9, x8 |
| ; CSSC-NEXT: ret |
| %pop = call i256 @llvm.ctpop.i256(i256 %a) |
| %r = trunc i256 %pop to i64 |
| ret i64 %r |
| } |
| |
| ; i256 Hamming distance: popcount(x ^ y) |
| define i64 @hamming_i256(i256 %a, i256 %b) nounwind { |
| ; |
| ; |
| ; NEON-LABEL: hamming_i256: |
| ; NEON: // %bb.0: |
| ; NEON-NEXT: eor x8, x0, x4 |
| ; NEON-NEXT: eor x10, x2, x6 |
| ; NEON-NEXT: eor x9, x1, x5 |
| ; NEON-NEXT: fmov d0, x8 |
| ; NEON-NEXT: fmov d1, x10 |
| ; NEON-NEXT: eor x8, x3, x7 |
| ; NEON-NEXT: mov v1.d[1], x8 |
| ; NEON-NEXT: mov v0.d[1], x9 |
| ; NEON-NEXT: cnt v1.16b, v1.16b |
| ; NEON-NEXT: cnt v0.16b, v0.16b |
| ; NEON-NEXT: addv b1, v1.16b |
| ; NEON-NEXT: addv b0, v0.16b |
| ; NEON-NEXT: fmov x8, d1 |
| ; NEON-NEXT: fmov x9, d0 |
| ; NEON-NEXT: add x0, x9, x8 |
| ; NEON-NEXT: ret |
| ; |
| ; SVE-LABEL: hamming_i256: |
| ; SVE: // %bb.0: |
| ; SVE-NEXT: eor x8, x0, x4 |
| ; SVE-NEXT: eor x10, x2, x6 |
| ; SVE-NEXT: eor x9, x1, x5 |
| ; SVE-NEXT: fmov d0, x8 |
| ; SVE-NEXT: fmov d1, x10 |
| ; SVE-NEXT: eor x8, x3, x7 |
| ; SVE-NEXT: ptrue p0.d |
| ; SVE-NEXT: mov v1.d[1], x8 |
| ; SVE-NEXT: mov v0.d[1], x9 |
| ; SVE-NEXT: cnt z1.d, p0/m, z1.d |
| ; SVE-NEXT: cnt z0.d, p0/m, z0.d |
| ; SVE-NEXT: add v0.2d, v0.2d, v1.2d |
| ; SVE-NEXT: addp d0, v0.2d |
| ; SVE-NEXT: fmov x0, d0 |
| ; SVE-NEXT: ret |
| ; |
| ; CSSC-LABEL: hamming_i256: |
| ; CSSC: // %bb.0: |
| ; CSSC-NEXT: eor x8, x3, x7 |
| ; CSSC-NEXT: eor x9, x0, x4 |
| ; CSSC-NEXT: eor x10, x1, x5 |
| ; CSSC-NEXT: eor x11, x2, x6 |
| ; CSSC-NEXT: cnt x8, x8 |
| ; CSSC-NEXT: cnt x10, x10 |
| ; CSSC-NEXT: cnt x11, x11 |
| ; CSSC-NEXT: cnt x9, x9 |
| ; CSSC-NEXT: add x8, x11, x8 |
| ; CSSC-NEXT: add x9, x9, x10 |
| ; CSSC-NEXT: add x0, x9, x8 |
| ; CSSC-NEXT: ret |
| %xor = xor i256 %a, %b |
| %pop = call i256 @llvm.ctpop.i256(i256 %xor) |
| %r = trunc i256 %pop to i64 |
| ret i64 %r |
| } |
| |
| ; i256 count leading zeros |
| define i256 @ctlz_i256(i256 %a) nounwind { |
| ; |
| ; |
| ; NEON-LABEL: ctlz_i256: |
| ; NEON: // %bb.0: |
| ; NEON-NEXT: clz x8, x2 |
| ; NEON-NEXT: clz x9, x3 |
| ; NEON-NEXT: cmp x3, #0 |
| ; NEON-NEXT: add x8, x8, #64 |
| ; NEON-NEXT: clz x10, x0 |
| ; NEON-NEXT: orr x11, x2, x3 |
| ; NEON-NEXT: csel x8, x9, x8, ne |
| ; NEON-NEXT: clz x9, x1 |
| ; NEON-NEXT: add x10, x10, #64 |
| ; NEON-NEXT: cmp x1, #0 |
| ; NEON-NEXT: mov x1, xzr |
| ; NEON-NEXT: mov x2, xzr |
| ; NEON-NEXT: csel x9, x9, x10, ne |
| ; NEON-NEXT: cmp x11, #0 |
| ; NEON-NEXT: mov x3, xzr |
| ; NEON-NEXT: add x9, x9, #128 |
| ; NEON-NEXT: csel x0, x8, x9, ne |
| ; NEON-NEXT: ret |
| ; |
| ; SVE-LABEL: ctlz_i256: |
| ; SVE: // %bb.0: |
| ; SVE-NEXT: clz x8, x2 |
| ; SVE-NEXT: clz x9, x3 |
| ; SVE-NEXT: cmp x3, #0 |
| ; SVE-NEXT: add x8, x8, #64 |
| ; SVE-NEXT: clz x10, x0 |
| ; SVE-NEXT: orr x11, x2, x3 |
| ; SVE-NEXT: csel x8, x9, x8, ne |
| ; SVE-NEXT: clz x9, x1 |
| ; SVE-NEXT: add x10, x10, #64 |
| ; SVE-NEXT: cmp x1, #0 |
| ; SVE-NEXT: mov x1, xzr |
| ; SVE-NEXT: mov x2, xzr |
| ; SVE-NEXT: csel x9, x9, x10, ne |
| ; SVE-NEXT: cmp x11, #0 |
| ; SVE-NEXT: mov x3, xzr |
| ; SVE-NEXT: add x9, x9, #128 |
| ; SVE-NEXT: csel x0, x8, x9, ne |
| ; SVE-NEXT: ret |
| ; |
| ; CSSC-LABEL: ctlz_i256: |
| ; CSSC: // %bb.0: |
| ; CSSC-NEXT: clz x8, x2 |
| ; CSSC-NEXT: clz x9, x3 |
| ; CSSC-NEXT: cmp x3, #0 |
| ; CSSC-NEXT: add x8, x8, #64 |
| ; CSSC-NEXT: clz x10, x0 |
| ; CSSC-NEXT: orr x11, x2, x3 |
| ; CSSC-NEXT: csel x8, x9, x8, ne |
| ; CSSC-NEXT: clz x9, x1 |
| ; CSSC-NEXT: add x10, x10, #64 |
| ; CSSC-NEXT: cmp x1, #0 |
| ; CSSC-NEXT: mov x1, xzr |
| ; CSSC-NEXT: mov x2, xzr |
| ; CSSC-NEXT: csel x9, x9, x10, ne |
| ; CSSC-NEXT: cmp x11, #0 |
| ; CSSC-NEXT: mov x3, xzr |
| ; CSSC-NEXT: add x9, x9, #128 |
| ; CSSC-NEXT: csel x0, x8, x9, ne |
| ; CSSC-NEXT: ret |
| %r = call i256 @llvm.ctlz.i256(i256 %a, i1 false) |
| ret i256 %r |
| } |
| |
| ; i256 count trailing zeros |
| define i256 @cttz_i256(i256 %a) nounwind { |
| ; |
| ; |
| ; NEON-LABEL: cttz_i256: |
| ; NEON: // %bb.0: |
| ; NEON-NEXT: rbit x8, x1 |
| ; NEON-NEXT: rbit x9, x0 |
| ; NEON-NEXT: rbit x10, x3 |
| ; NEON-NEXT: cmp x0, #0 |
| ; NEON-NEXT: rbit x11, x2 |
| ; NEON-NEXT: mov x3, xzr |
| ; NEON-NEXT: clz x8, x8 |
| ; NEON-NEXT: clz x9, x9 |
| ; NEON-NEXT: add x8, x8, #64 |
| ; NEON-NEXT: csel x8, x9, x8, ne |
| ; NEON-NEXT: clz x9, x10 |
| ; NEON-NEXT: clz x10, x11 |
| ; NEON-NEXT: add x9, x9, #64 |
| ; NEON-NEXT: cmp x2, #0 |
| ; NEON-NEXT: orr x11, x0, x1 |
| ; NEON-NEXT: csel x9, x10, x9, ne |
| ; NEON-NEXT: cmp x11, #0 |
| ; NEON-NEXT: mov x1, xzr |
| ; NEON-NEXT: add x9, x9, #128 |
| ; NEON-NEXT: mov x2, xzr |
| ; NEON-NEXT: csel x0, x8, x9, ne |
| ; NEON-NEXT: ret |
| ; |
| ; SVE-LABEL: cttz_i256: |
| ; SVE: // %bb.0: |
| ; SVE-NEXT: rbit x8, x1 |
| ; SVE-NEXT: rbit x9, x0 |
| ; SVE-NEXT: rbit x10, x3 |
| ; SVE-NEXT: cmp x0, #0 |
| ; SVE-NEXT: rbit x11, x2 |
| ; SVE-NEXT: mov x3, xzr |
| ; SVE-NEXT: clz x8, x8 |
| ; SVE-NEXT: clz x9, x9 |
| ; SVE-NEXT: add x8, x8, #64 |
| ; SVE-NEXT: csel x8, x9, x8, ne |
| ; SVE-NEXT: clz x9, x10 |
| ; SVE-NEXT: clz x10, x11 |
| ; SVE-NEXT: add x9, x9, #64 |
| ; SVE-NEXT: cmp x2, #0 |
| ; SVE-NEXT: orr x11, x0, x1 |
| ; SVE-NEXT: csel x9, x10, x9, ne |
| ; SVE-NEXT: cmp x11, #0 |
| ; SVE-NEXT: mov x1, xzr |
| ; SVE-NEXT: add x9, x9, #128 |
| ; SVE-NEXT: mov x2, xzr |
| ; SVE-NEXT: csel x0, x8, x9, ne |
| ; SVE-NEXT: ret |
| ; |
| ; CSSC-LABEL: cttz_i256: |
| ; CSSC: // %bb.0: |
| ; CSSC-NEXT: ctz x8, x1 |
| ; CSSC-NEXT: ctz x9, x0 |
| ; CSSC-NEXT: cmp x0, #0 |
| ; CSSC-NEXT: add x8, x8, #64 |
| ; CSSC-NEXT: ctz x10, x3 |
| ; CSSC-NEXT: orr x11, x0, x1 |
| ; CSSC-NEXT: csel x8, x9, x8, ne |
| ; CSSC-NEXT: ctz x9, x2 |
| ; CSSC-NEXT: add x10, x10, #64 |
| ; CSSC-NEXT: cmp x2, #0 |
| ; CSSC-NEXT: mov x1, xzr |
| ; CSSC-NEXT: mov x2, xzr |
| ; CSSC-NEXT: csel x9, x9, x10, ne |
| ; CSSC-NEXT: cmp x11, #0 |
| ; CSSC-NEXT: mov x3, xzr |
| ; CSSC-NEXT: add x9, x9, #128 |
| ; CSSC-NEXT: csel x0, x8, x9, ne |
| ; CSSC-NEXT: ret |
| %r = call i256 @llvm.cttz.i256(i256 %a, i1 false) |
| ret i256 %r |
| } |