David Green b0876994eb
[AArch64][GlobalISel] Clean up CTLZ vector type legalization. (#131514)
Similar to other operations, s8, s16 and s32 vector elements are clamped
to legal vector sizes, but in this case s64 are scalarized to use the
gpr instructions. This allows vector types to split as opposed to
scalarizing.
2025-03-19 19:28:36 +00:00

605 lines
19 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=aarch64-none-eabi -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
; RUN: llc -mtriple=aarch64-none-eabi -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define void @v2i8(ptr %p1) {
; CHECK-SD-LABEL: v2i8:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: ldrb w8, [x0]
; CHECK-SD-NEXT: ldrb w9, [x0, #1]
; CHECK-SD-NEXT: movi v0.2s, #24
; CHECK-SD-NEXT: fmov s1, w8
; CHECK-SD-NEXT: mov v1.s[1], w9
; CHECK-SD-NEXT: clz v1.2s, v1.2s
; CHECK-SD-NEXT: sub v0.2s, v1.2s, v0.2s
; CHECK-SD-NEXT: mov w8, v0.s[1]
; CHECK-SD-NEXT: fmov w9, s0
; CHECK-SD-NEXT: strb w9, [x0]
; CHECK-SD-NEXT: strb w8, [x0, #1]
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v2i8:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: ldr b0, [x0]
; CHECK-GI-NEXT: ldr b1, [x0, #1]
; CHECK-GI-NEXT: add x8, x0, #1
; CHECK-GI-NEXT: mov v0.b[0], v0.b[0]
; CHECK-GI-NEXT: mov v0.b[1], v1.b[0]
; CHECK-GI-NEXT: clz v0.8b, v0.8b
; CHECK-GI-NEXT: st1 { v0.b }[0], [x0]
; CHECK-GI-NEXT: st1 { v0.b }[1], [x8]
; CHECK-GI-NEXT: ret
entry:
%d = load <2 x i8>, ptr %p1
%s = call <2 x i8> @llvm.ctlz(<2 x i8> %d, i1 false)
store <2 x i8> %s, ptr %p1
ret void
}
define void @v3i8(ptr %p1) {
; CHECK-SD-LABEL: v3i8:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: sub sp, sp, #16
; CHECK-SD-NEXT: .cfi_def_cfa_offset 16
; CHECK-SD-NEXT: movi v0.4h, #8
; CHECK-SD-NEXT: ldr s1, [x0]
; CHECK-SD-NEXT: zip1 v1.8b, v1.8b, v0.8b
; CHECK-SD-NEXT: bic v1.4h, #255, lsl #8
; CHECK-SD-NEXT: clz v1.4h, v1.4h
; CHECK-SD-NEXT: sub v0.4h, v1.4h, v0.4h
; CHECK-SD-NEXT: uzp1 v1.8b, v0.8b, v0.8b
; CHECK-SD-NEXT: umov w8, v0.h[2]
; CHECK-SD-NEXT: str s1, [sp, #12]
; CHECK-SD-NEXT: ldrh w9, [sp, #12]
; CHECK-SD-NEXT: strb w8, [x0, #2]
; CHECK-SD-NEXT: strh w9, [x0]
; CHECK-SD-NEXT: add sp, sp, #16
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v3i8:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: ldr b0, [x0]
; CHECK-GI-NEXT: ldr b1, [x0, #1]
; CHECK-GI-NEXT: add x8, x0, #1
; CHECK-GI-NEXT: add x9, x0, #2
; CHECK-GI-NEXT: mov v0.b[0], v0.b[0]
; CHECK-GI-NEXT: mov v0.b[1], v1.b[0]
; CHECK-GI-NEXT: ldr b1, [x0, #2]
; CHECK-GI-NEXT: mov v0.b[2], v1.b[0]
; CHECK-GI-NEXT: clz v0.8b, v0.8b
; CHECK-GI-NEXT: st1 { v0.b }[0], [x0]
; CHECK-GI-NEXT: st1 { v0.b }[1], [x8]
; CHECK-GI-NEXT: st1 { v0.b }[2], [x9]
; CHECK-GI-NEXT: ret
entry:
%d = load <3 x i8>, ptr %p1
%s = call <3 x i8> @llvm.ctlz(<3 x i8> %d, i1 false)
store <3 x i8> %s, ptr %p1
ret void
}
define void @v4i8(ptr %p1) {
; CHECK-SD-LABEL: v4i8:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: ldr s1, [x0]
; CHECK-SD-NEXT: movi v0.4h, #8
; CHECK-SD-NEXT: ushll v1.8h, v1.8b, #0
; CHECK-SD-NEXT: clz v1.4h, v1.4h
; CHECK-SD-NEXT: sub v0.4h, v1.4h, v0.4h
; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v0.8b
; CHECK-SD-NEXT: str s0, [x0]
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v4i8:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: ldr w8, [x0]
; CHECK-GI-NEXT: fmov s0, w8
; CHECK-GI-NEXT: mov b1, v0.b[1]
; CHECK-GI-NEXT: mov v2.b[0], v0.b[0]
; CHECK-GI-NEXT: mov b3, v0.b[2]
; CHECK-GI-NEXT: mov b0, v0.b[3]
; CHECK-GI-NEXT: mov v2.b[1], v1.b[0]
; CHECK-GI-NEXT: mov v2.b[2], v3.b[0]
; CHECK-GI-NEXT: mov v2.b[3], v0.b[0]
; CHECK-GI-NEXT: clz v0.8b, v2.8b
; CHECK-GI-NEXT: fmov w8, s0
; CHECK-GI-NEXT: str w8, [x0]
; CHECK-GI-NEXT: ret
entry:
%d = load <4 x i8>, ptr %p1
%s = call <4 x i8> @llvm.ctlz(<4 x i8> %d, i1 false)
store <4 x i8> %s, ptr %p1
ret void
}
define <8 x i8> @v8i8(<8 x i8> %d) {
; CHECK-LABEL: v8i8:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.8b, v0.8b
; CHECK-NEXT: ret
entry:
%s = call <8 x i8> @llvm.ctlz(<8 x i8> %d, i1 false)
ret <8 x i8> %s
}
define <16 x i8> @v16i8(<16 x i8> %d) {
; CHECK-LABEL: v16i8:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.16b, v0.16b
; CHECK-NEXT: ret
entry:
%s = call <16 x i8> @llvm.ctlz(<16 x i8> %d, i1 false)
ret <16 x i8> %s
}
define <32 x i8> @v32i8(<32 x i8> %d) {
; CHECK-LABEL: v32i8:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.16b, v0.16b
; CHECK-NEXT: clz v1.16b, v1.16b
; CHECK-NEXT: ret
entry:
%s = call <32 x i8> @llvm.ctlz(<32 x i8> %d, i1 false)
ret <32 x i8> %s
}
define void @v2i16(ptr %p1) {
; CHECK-SD-LABEL: v2i16:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: ldrh w8, [x0]
; CHECK-SD-NEXT: ldrh w9, [x0, #2]
; CHECK-SD-NEXT: movi v0.2s, #16
; CHECK-SD-NEXT: fmov s1, w8
; CHECK-SD-NEXT: mov v1.s[1], w9
; CHECK-SD-NEXT: clz v1.2s, v1.2s
; CHECK-SD-NEXT: sub v0.2s, v1.2s, v0.2s
; CHECK-SD-NEXT: mov s1, v0.s[1]
; CHECK-SD-NEXT: str h0, [x0]
; CHECK-SD-NEXT: str h1, [x0, #2]
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v2i16:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: ldr h0, [x0]
; CHECK-GI-NEXT: add x8, x0, #2
; CHECK-GI-NEXT: ld1 { v0.h }[1], [x8]
; CHECK-GI-NEXT: clz v0.4h, v0.4h
; CHECK-GI-NEXT: str h0, [x0]
; CHECK-GI-NEXT: st1 { v0.h }[1], [x8]
; CHECK-GI-NEXT: ret
entry:
%d = load <2 x i16>, ptr %p1
%s = call <2 x i16> @llvm.ctlz(<2 x i16> %d, i1 false)
store <2 x i16> %s, ptr %p1
ret void
}
define void @v3i16(ptr %p1) {
; CHECK-SD-LABEL: v3i16:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: ldr d0, [x0]
; CHECK-SD-NEXT: add x8, x0, #4
; CHECK-SD-NEXT: clz v0.4h, v0.4h
; CHECK-SD-NEXT: st1 { v0.h }[2], [x8]
; CHECK-SD-NEXT: str s0, [x0]
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v3i16:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: ldr h0, [x0]
; CHECK-GI-NEXT: add x8, x0, #2
; CHECK-GI-NEXT: add x9, x0, #4
; CHECK-GI-NEXT: ld1 { v0.h }[1], [x8]
; CHECK-GI-NEXT: ld1 { v0.h }[2], [x9]
; CHECK-GI-NEXT: clz v0.4h, v0.4h
; CHECK-GI-NEXT: str h0, [x0]
; CHECK-GI-NEXT: st1 { v0.h }[1], [x8]
; CHECK-GI-NEXT: st1 { v0.h }[2], [x9]
; CHECK-GI-NEXT: ret
entry:
%d = load <3 x i16>, ptr %p1
%s = call <3 x i16> @llvm.ctlz(<3 x i16> %d, i1 false)
store <3 x i16> %s, ptr %p1
ret void
}
define <4 x i16> @v4i16(<4 x i16> %d) {
; CHECK-LABEL: v4i16:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.4h, v0.4h
; CHECK-NEXT: ret
entry:
%s = call <4 x i16> @llvm.ctlz(<4 x i16> %d, i1 false)
ret <4 x i16> %s
}
define <8 x i16> @v8i16(<8 x i16> %d) {
; CHECK-LABEL: v8i16:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.8h, v0.8h
; CHECK-NEXT: ret
entry:
%s = call <8 x i16> @llvm.ctlz(<8 x i16> %d, i1 false)
ret <8 x i16> %s
}
define <16 x i16> @v16i16(<16 x i16> %d) {
; CHECK-LABEL: v16i16:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.8h, v0.8h
; CHECK-NEXT: clz v1.8h, v1.8h
; CHECK-NEXT: ret
entry:
%s = call <16 x i16> @llvm.ctlz(<16 x i16> %d, i1 false)
ret <16 x i16> %s
}
define <2 x i32> @v2i32(<2 x i32> %d) {
; CHECK-LABEL: v2i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.2s, v0.2s
; CHECK-NEXT: ret
entry:
%s = call <2 x i32> @llvm.ctlz(<2 x i32> %d, i1 false)
ret <2 x i32> %s
}
define <3 x i32> @v3i32(<3 x i32> %d) {
; CHECK-LABEL: v3i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.4s, v0.4s
; CHECK-NEXT: ret
entry:
%s = call <3 x i32> @llvm.ctlz(<3 x i32> %d, i1 false)
ret <3 x i32> %s
}
define <4 x i32> @v4i32(<4 x i32> %d) {
; CHECK-LABEL: v4i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.4s, v0.4s
; CHECK-NEXT: ret
entry:
%s = call <4 x i32> @llvm.ctlz(<4 x i32> %d, i1 false)
ret <4 x i32> %s
}
define <8 x i32> @v8i32(<8 x i32> %d) {
; CHECK-LABEL: v8i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: clz v0.4s, v0.4s
; CHECK-NEXT: clz v1.4s, v1.4s
; CHECK-NEXT: ret
entry:
%s = call <8 x i32> @llvm.ctlz(<8 x i32> %d, i1 false)
ret <8 x i32> %s
}
define <2 x i64> @v2i64(<2 x i64> %d) {
; CHECK-SD-LABEL: v2i64:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: ushr v1.2d, v0.2d, #1
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v1.16b
; CHECK-SD-NEXT: ushr v1.2d, v0.2d, #2
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v1.16b
; CHECK-SD-NEXT: ushr v1.2d, v0.2d, #4
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v1.16b
; CHECK-SD-NEXT: ushr v1.2d, v0.2d, #8
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v1.16b
; CHECK-SD-NEXT: ushr v1.2d, v0.2d, #16
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v1.16b
; CHECK-SD-NEXT: ushr v1.2d, v0.2d, #32
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v1.16b
; CHECK-SD-NEXT: mvn v0.16b, v0.16b
; CHECK-SD-NEXT: cnt v0.16b, v0.16b
; CHECK-SD-NEXT: uaddlp v0.8h, v0.16b
; CHECK-SD-NEXT: uaddlp v0.4s, v0.8h
; CHECK-SD-NEXT: uaddlp v0.2d, v0.4s
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v2i64:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: fmov x8, d0
; CHECK-GI-NEXT: mov x9, v0.d[1]
; CHECK-GI-NEXT: clz x8, x8
; CHECK-GI-NEXT: mov v0.d[0], x8
; CHECK-GI-NEXT: clz x8, x9
; CHECK-GI-NEXT: mov v0.d[1], x8
; CHECK-GI-NEXT: ret
entry:
%s = call <2 x i64> @llvm.ctlz(<2 x i64> %d, i1 false)
ret <2 x i64> %s
}
define <3 x i64> @v3i64(<3 x i64> %d) {
; CHECK-SD-LABEL: v3i64:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0
; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1
; CHECK-SD-NEXT: // kill: def $d2 killed $d2 def $q2
; CHECK-SD-NEXT: mov v0.d[1], v1.d[0]
; CHECK-SD-NEXT: ushr v1.2d, v0.2d, #1
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v1.16b
; CHECK-SD-NEXT: ushr v1.2d, v2.2d, #1
; CHECK-SD-NEXT: ushr v3.2d, v0.2d, #2
; CHECK-SD-NEXT: orr v1.16b, v2.16b, v1.16b
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v1.2d, #2
; CHECK-SD-NEXT: ushr v3.2d, v0.2d, #4
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v2.16b
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v1.2d, #4
; CHECK-SD-NEXT: ushr v3.2d, v0.2d, #8
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v2.16b
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v1.2d, #8
; CHECK-SD-NEXT: ushr v3.2d, v0.2d, #16
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v2.16b
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v1.2d, #16
; CHECK-SD-NEXT: ushr v3.2d, v0.2d, #32
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v2.16b
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v1.2d, #32
; CHECK-SD-NEXT: mvn v0.16b, v0.16b
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v2.16b
; CHECK-SD-NEXT: cnt v0.16b, v0.16b
; CHECK-SD-NEXT: mvn v1.16b, v1.16b
; CHECK-SD-NEXT: cnt v1.16b, v1.16b
; CHECK-SD-NEXT: uaddlp v0.8h, v0.16b
; CHECK-SD-NEXT: uaddlp v0.4s, v0.8h
; CHECK-SD-NEXT: uaddlp v1.8h, v1.16b
; CHECK-SD-NEXT: uaddlp v0.2d, v0.4s
; CHECK-SD-NEXT: uaddlp v2.4s, v1.8h
; CHECK-SD-NEXT: ext v1.16b, v0.16b, v0.16b, #8
; CHECK-SD-NEXT: uaddlp v2.2d, v2.4s
; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0
; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1
; CHECK-SD-NEXT: // kill: def $d2 killed $d2 killed $q2
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v3i64:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: fmov x8, d0
; CHECK-GI-NEXT: fmov x9, d1
; CHECK-GI-NEXT: fmov x10, d2
; CHECK-GI-NEXT: clz x8, x8
; CHECK-GI-NEXT: clz x9, x9
; CHECK-GI-NEXT: clz x10, x10
; CHECK-GI-NEXT: fmov d0, x8
; CHECK-GI-NEXT: fmov d1, x9
; CHECK-GI-NEXT: fmov d2, x10
; CHECK-GI-NEXT: ret
entry:
%s = call <3 x i64> @llvm.ctlz(<3 x i64> %d, i1 false)
ret <3 x i64> %s
}
define <4 x i64> @v4i64(<4 x i64> %d) {
; CHECK-SD-LABEL: v4i64:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: ushr v2.2d, v0.2d, #1
; CHECK-SD-NEXT: ushr v3.2d, v1.2d, #1
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v2.16b
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v0.2d, #2
; CHECK-SD-NEXT: ushr v3.2d, v1.2d, #2
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v2.16b
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v0.2d, #4
; CHECK-SD-NEXT: ushr v3.2d, v1.2d, #4
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v2.16b
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v0.2d, #8
; CHECK-SD-NEXT: ushr v3.2d, v1.2d, #8
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v2.16b
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v0.2d, #16
; CHECK-SD-NEXT: ushr v3.2d, v1.2d, #16
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v2.16b
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v3.16b
; CHECK-SD-NEXT: ushr v2.2d, v0.2d, #32
; CHECK-SD-NEXT: ushr v3.2d, v1.2d, #32
; CHECK-SD-NEXT: orr v0.16b, v0.16b, v2.16b
; CHECK-SD-NEXT: orr v1.16b, v1.16b, v3.16b
; CHECK-SD-NEXT: mvn v0.16b, v0.16b
; CHECK-SD-NEXT: mvn v1.16b, v1.16b
; CHECK-SD-NEXT: cnt v0.16b, v0.16b
; CHECK-SD-NEXT: cnt v1.16b, v1.16b
; CHECK-SD-NEXT: uaddlp v0.8h, v0.16b
; CHECK-SD-NEXT: uaddlp v1.8h, v1.16b
; CHECK-SD-NEXT: uaddlp v0.4s, v0.8h
; CHECK-SD-NEXT: uaddlp v1.4s, v1.8h
; CHECK-SD-NEXT: uaddlp v0.2d, v0.4s
; CHECK-SD-NEXT: uaddlp v1.2d, v1.4s
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v4i64:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: fmov x9, d0
; CHECK-GI-NEXT: fmov x10, d1
; CHECK-GI-NEXT: mov x8, v0.d[1]
; CHECK-GI-NEXT: mov x11, v1.d[1]
; CHECK-GI-NEXT: clz x9, x9
; CHECK-GI-NEXT: clz x10, x10
; CHECK-GI-NEXT: mov v0.d[0], x9
; CHECK-GI-NEXT: mov v1.d[0], x10
; CHECK-GI-NEXT: clz x8, x8
; CHECK-GI-NEXT: clz x9, x11
; CHECK-GI-NEXT: mov v0.d[1], x8
; CHECK-GI-NEXT: mov v1.d[1], x9
; CHECK-GI-NEXT: ret
entry:
%s = call <4 x i64> @llvm.ctlz(<4 x i64> %d, i1 false)
ret <4 x i64> %s
}
define <2 x i128> @v2i128(<2 x i128> %d) {
; CHECK-SD-LABEL: v2i128:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: clz x8, x0
; CHECK-SD-NEXT: clz x9, x1
; CHECK-SD-NEXT: cmp x1, #0
; CHECK-SD-NEXT: add x8, x8, #64
; CHECK-SD-NEXT: clz x10, x2
; CHECK-SD-NEXT: mov x1, xzr
; CHECK-SD-NEXT: csel x0, x9, x8, ne
; CHECK-SD-NEXT: clz x8, x3
; CHECK-SD-NEXT: add x9, x10, #64
; CHECK-SD-NEXT: cmp x3, #0
; CHECK-SD-NEXT: mov x3, xzr
; CHECK-SD-NEXT: csel x2, x8, x9, ne
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v2i128:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: mov w8, wzr
; CHECK-GI-NEXT: clz x9, x0
; CHECK-GI-NEXT: clz x11, x1
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: adc x10, xzr, xzr
; CHECK-GI-NEXT: cmp x1, #0
; CHECK-GI-NEXT: csel x0, x9, x11, eq
; CHECK-GI-NEXT: clz x9, x2
; CHECK-GI-NEXT: csel x1, x10, xzr, eq
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: clz x10, x3
; CHECK-GI-NEXT: adc x8, xzr, xzr
; CHECK-GI-NEXT: cmp x3, #0
; CHECK-GI-NEXT: csel x2, x9, x10, eq
; CHECK-GI-NEXT: csel x3, x8, xzr, eq
; CHECK-GI-NEXT: ret
entry:
%s = call <2 x i128> @llvm.ctlz(<2 x i128> %d, i1 false)
ret <2 x i128> %s
}
define <3 x i128> @v3i128(<3 x i128> %d) {
; CHECK-SD-LABEL: v3i128:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: clz x8, x0
; CHECK-SD-NEXT: clz x9, x1
; CHECK-SD-NEXT: cmp x1, #0
; CHECK-SD-NEXT: add x8, x8, #64
; CHECK-SD-NEXT: clz x10, x2
; CHECK-SD-NEXT: mov x1, xzr
; CHECK-SD-NEXT: csel x0, x9, x8, ne
; CHECK-SD-NEXT: clz x8, x3
; CHECK-SD-NEXT: add x9, x10, #64
; CHECK-SD-NEXT: cmp x3, #0
; CHECK-SD-NEXT: mov x3, xzr
; CHECK-SD-NEXT: csel x2, x8, x9, ne
; CHECK-SD-NEXT: clz x8, x4
; CHECK-SD-NEXT: clz x9, x5
; CHECK-SD-NEXT: add x8, x8, #64
; CHECK-SD-NEXT: cmp x5, #0
; CHECK-SD-NEXT: mov x5, xzr
; CHECK-SD-NEXT: csel x4, x9, x8, ne
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v3i128:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: mov w8, wzr
; CHECK-GI-NEXT: clz x9, x0
; CHECK-GI-NEXT: clz x11, x1
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: adc x10, xzr, xzr
; CHECK-GI-NEXT: cmp x1, #0
; CHECK-GI-NEXT: csel x0, x9, x11, eq
; CHECK-GI-NEXT: clz x9, x2
; CHECK-GI-NEXT: csel x1, x10, xzr, eq
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: clz x11, x3
; CHECK-GI-NEXT: adc x10, xzr, xzr
; CHECK-GI-NEXT: cmp x3, #0
; CHECK-GI-NEXT: csel x2, x9, x11, eq
; CHECK-GI-NEXT: clz x9, x4
; CHECK-GI-NEXT: csel x3, x10, xzr, eq
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: clz x10, x5
; CHECK-GI-NEXT: adc x8, xzr, xzr
; CHECK-GI-NEXT: cmp x5, #0
; CHECK-GI-NEXT: csel x4, x9, x10, eq
; CHECK-GI-NEXT: csel x5, x8, xzr, eq
; CHECK-GI-NEXT: ret
entry:
%s = call <3 x i128> @llvm.ctlz(<3 x i128> %d, i1 false)
ret <3 x i128> %s
}
define <4 x i128> @v4i128(<4 x i128> %d) {
; CHECK-SD-LABEL: v4i128:
; CHECK-SD: // %bb.0: // %entry
; CHECK-SD-NEXT: clz x9, x0
; CHECK-SD-NEXT: clz x8, x2
; CHECK-SD-NEXT: clz x10, x1
; CHECK-SD-NEXT: add x9, x9, #64
; CHECK-SD-NEXT: cmp x1, #0
; CHECK-SD-NEXT: add x8, x8, #64
; CHECK-SD-NEXT: csel x0, x10, x9, ne
; CHECK-SD-NEXT: clz x9, x3
; CHECK-SD-NEXT: cmp x3, #0
; CHECK-SD-NEXT: csel x2, x9, x8, ne
; CHECK-SD-NEXT: clz x8, x4
; CHECK-SD-NEXT: clz x9, x5
; CHECK-SD-NEXT: add x8, x8, #64
; CHECK-SD-NEXT: cmp x5, #0
; CHECK-SD-NEXT: mov x1, xzr
; CHECK-SD-NEXT: csel x4, x9, x8, ne
; CHECK-SD-NEXT: clz x8, x6
; CHECK-SD-NEXT: clz x9, x7
; CHECK-SD-NEXT: add x8, x8, #64
; CHECK-SD-NEXT: cmp x7, #0
; CHECK-SD-NEXT: mov x3, xzr
; CHECK-SD-NEXT: csel x6, x9, x8, ne
; CHECK-SD-NEXT: mov x5, xzr
; CHECK-SD-NEXT: mov x7, xzr
; CHECK-SD-NEXT: ret
;
; CHECK-GI-LABEL: v4i128:
; CHECK-GI: // %bb.0: // %entry
; CHECK-GI-NEXT: mov w8, wzr
; CHECK-GI-NEXT: clz x9, x0
; CHECK-GI-NEXT: clz x11, x1
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: adc x10, xzr, xzr
; CHECK-GI-NEXT: cmp x1, #0
; CHECK-GI-NEXT: csel x0, x9, x11, eq
; CHECK-GI-NEXT: clz x9, x2
; CHECK-GI-NEXT: csel x1, x10, xzr, eq
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: clz x11, x3
; CHECK-GI-NEXT: adc x10, xzr, xzr
; CHECK-GI-NEXT: cmp x3, #0
; CHECK-GI-NEXT: csel x2, x9, x11, eq
; CHECK-GI-NEXT: clz x9, x4
; CHECK-GI-NEXT: csel x3, x10, xzr, eq
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: clz x11, x5
; CHECK-GI-NEXT: adc x10, xzr, xzr
; CHECK-GI-NEXT: cmp x5, #0
; CHECK-GI-NEXT: csel x4, x9, x11, eq
; CHECK-GI-NEXT: clz x9, x6
; CHECK-GI-NEXT: csel x5, x10, xzr, eq
; CHECK-GI-NEXT: cmp w8, #1
; CHECK-GI-NEXT: add x9, x9, #64
; CHECK-GI-NEXT: clz x10, x7
; CHECK-GI-NEXT: adc x8, xzr, xzr
; CHECK-GI-NEXT: cmp x7, #0
; CHECK-GI-NEXT: csel x6, x9, x10, eq
; CHECK-GI-NEXT: csel x7, x8, xzr, eq
; CHECK-GI-NEXT: ret
entry:
%s = call <4 x i128> @llvm.ctlz(<4 x i128> %d, i1 false)
ret <4 x i128> %s
}