blob: 2d5db9ad8b2f19a4d51f4ea49803732d42f2424e [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
; RUN: llc -mtriple=aarch64-none-elf < %s | FileCheck %s
define <4 x i32> @masked_shl_v4i32(<4 x i32> %x, <4 x i32> %amt) {
; CHECK-LABEL: masked_shl_v4i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.4s, #63
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
; CHECK-NEXT: ret
entry:
%m = and <4 x i32> %amt, splat (i32 63)
%shl = shl <4 x i32> %x, %m
%ok = icmp ult <4 x i32> %m, splat (i32 32)
%res = select <4 x i1> %ok, <4 x i32> %shl, <4 x i32> zeroinitializer
ret <4 x i32> %res
}
define <4 x i32> @masked_shl_v4i32_swapped(<4 x i32> %x, <4 x i32> %amt) {
; CHECK-LABEL: masked_shl_v4i32_swapped:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.4s, #63
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
; CHECK-NEXT: ret
entry:
%m = and <4 x i32> %amt, splat (i32 63)
%shl = shl <4 x i32> %x, %m
%oob = icmp uge <4 x i32> %m, splat (i32 32)
%res = select <4 x i1> %oob, <4 x i32> zeroinitializer, <4 x i32> %shl
ret <4 x i32> %res
}
define <4 x i32> @masked_srl_v4i32(<4 x i32> %x, <4 x i32> %amt) {
; CHECK-LABEL: masked_srl_v4i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.4s, #63
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: neg v1.4s, v1.4s
; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
; CHECK-NEXT: ret
entry:
%m = and <4 x i32> %amt, splat (i32 63)
%srl = lshr <4 x i32> %x, %m
%ok = icmp ult <4 x i32> %m, splat (i32 32)
%res = select <4 x i1> %ok, <4 x i32> %srl, <4 x i32> zeroinitializer
ret <4 x i32> %res
}
define <16 x i8> @masked_shl_v16i8(<16 x i8> %x, <16 x i8> %amt) {
; CHECK-LABEL: masked_shl_v16i8:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.16b, #15
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: ushl v0.16b, v0.16b, v1.16b
; CHECK-NEXT: ret
entry:
%m = and <16 x i8> %amt, splat (i8 15)
%shl = shl <16 x i8> %x, %m
%ok = icmp ult <16 x i8> %m, splat (i8 8)
%res = select <16 x i1> %ok, <16 x i8> %shl, <16 x i8> zeroinitializer
ret <16 x i8> %res
}
define <8 x i16> @masked_shl_v8i16(<8 x i16> %x, <8 x i16> %amt) {
; CHECK-LABEL: masked_shl_v8i16:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.8h, #31
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: ushl v0.8h, v0.8h, v1.8h
; CHECK-NEXT: ret
entry:
%m = and <8 x i16> %amt, splat (i16 31)
%shl = shl <8 x i16> %x, %m
%ok = icmp ult <8 x i16> %m, splat (i16 16)
%res = select <8 x i1> %ok, <8 x i16> %shl, <8 x i16> zeroinitializer
ret <8 x i16> %res
}
define <2 x i64> @masked_shl_v2i64(<2 x i64> %x, <2 x i64> %amt) {
; CHECK-LABEL: masked_shl_v2i64:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #127 // =0x7f
; CHECK-NEXT: dup v2.2d, x8
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: ushl v0.2d, v0.2d, v1.2d
; CHECK-NEXT: ret
entry:
%m = and <2 x i64> %amt, splat (i64 127)
%shl = shl <2 x i64> %x, %m
%ok = icmp ult <2 x i64> %m, splat (i64 64)
%res = select <2 x i1> %ok, <2 x i64> %shl, <2 x i64> zeroinitializer
ret <2 x i64> %res
}
define <2 x i32> @masked_shl_v2i32(<2 x i32> %x, <2 x i32> %amt) {
; CHECK-LABEL: masked_shl_v2i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.2s, #63
; CHECK-NEXT: and v1.8b, v1.8b, v2.8b
; CHECK-NEXT: ushl v0.2s, v0.2s, v1.2s
; CHECK-NEXT: ret
entry:
%m = and <2 x i32> %amt, splat (i32 63)
%shl = shl <2 x i32> %x, %m
%ok = icmp ult <2 x i32> %m, splat (i32 32)
%res = select <2 x i1> %ok, <2 x i32> %shl, <2 x i32> zeroinitializer
ret <2 x i32> %res
}
define <4 x i32> @unbounded_shl_v4i32(<4 x i32> %x, <4 x i32> %amt) {
; CHECK-LABEL: unbounded_shl_v4i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.4s, #32
; CHECK-NEXT: umin v1.4s, v1.4s, v2.4s
; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
; CHECK-NEXT: ret
entry:
%shl = shl <4 x i32> %x, %amt
%ok = icmp ult <4 x i32> %amt, splat (i32 32)
%res = select <4 x i1> %ok, <4 x i32> %shl, <4 x i32> zeroinitializer
ret <4 x i32> %res
}
define <4 x i32> @unbounded_srl_v4i32(<4 x i32> %x, <4 x i32> %amt) {
; CHECK-LABEL: unbounded_srl_v4i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.4s, #32
; CHECK-NEXT: umin v1.4s, v1.4s, v2.4s
; CHECK-NEXT: neg v1.4s, v1.4s
; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
; CHECK-NEXT: ret
entry:
%srl = lshr <4 x i32> %x, %amt
%ok = icmp ult <4 x i32> %amt, splat (i32 32)
%res = select <4 x i1> %ok, <4 x i32> %srl, <4 x i32> zeroinitializer
ret <4 x i32> %res
}
define <4 x i32> @masked_shl_v4i32_mask255(<4 x i32> %x, <4 x i32> %amt) {
; CHECK-LABEL: masked_shl_v4i32_mask255:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.2d, #0x0000ff000000ff
; CHECK-NEXT: movi v3.4s, #32
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: umin v1.4s, v1.4s, v3.4s
; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
; CHECK-NEXT: ret
entry:
%m = and <4 x i32> %amt, splat (i32 255)
%shl = shl <4 x i32> %x, %m
%ok = icmp ult <4 x i32> %m, splat (i32 32)
%res = select <4 x i1> %ok, <4 x i32> %shl, <4 x i32> zeroinitializer
ret <4 x i32> %res
}
define <2 x i64> @unbounded_shl_v2i64_sve(<2 x i64> %x, <2 x i64> %amt) #0 {
; CHECK-LABEL: unbounded_shl_v2i64_sve:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1
; CHECK-NEXT: umin z1.d, z1.d, #64
; CHECK-NEXT: ushl v0.2d, v0.2d, v1.2d
; CHECK-NEXT: ret
entry:
%shl = shl <2 x i64> %x, %amt
%ok = icmp ult <2 x i64> %amt, splat (i64 64)
%res = select <2 x i1> %ok, <2 x i64> %shl, <2 x i64> zeroinitializer
ret <2 x i64> %res
}
define <1 x i128> @neg_masked_shl_v1i128(<1 x i128> %x, <1 x i128> %amt) {
; CHECK-LABEL: neg_masked_shl_v1i128:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: and x8, x2, #0x3f
; CHECK-NEXT: lsr x9, x0, #1
; CHECK-NEXT: lsl x11, x1, x2
; CHECK-NEXT: eor x10, x8, #0x3f
; CHECK-NEXT: cmp x8, #128
; CHECK-NEXT: lsr x9, x9, x10
; CHECK-NEXT: lsl x10, x0, x2
; CHECK-NEXT: orr x9, x11, x9
; CHECK-NEXT: csel x0, x10, xzr, lo
; CHECK-NEXT: csel x1, x9, xzr, lo
; CHECK-NEXT: ret
entry:
%m = and <1 x i128> %amt, splat (i128 63)
%shl = shl <1 x i128> %x, %m
%ok = icmp ult <1 x i128> %m, splat (i128 128)
%res = select <1 x i1> %ok, <1 x i128> %shl, <1 x i128> zeroinitializer
ret <1 x i128> %res
}
define <2 x i64> @neg_unbounded_shl_v2i64(<2 x i64> %x, <2 x i64> %amt) {
; CHECK-LABEL: neg_unbounded_shl_v2i64:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: mov w8, #64 // =0x40
; CHECK-NEXT: ushl v0.2d, v0.2d, v1.2d
; CHECK-NEXT: dup v2.2d, x8
; CHECK-NEXT: cmhi v1.2d, v2.2d, v1.2d
; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
; CHECK-NEXT: ret
entry:
%shl = shl <2 x i64> %x, %amt
%ok = icmp ult <2 x i64> %amt, splat (i64 64)
%res = select <2 x i1> %ok, <2 x i64> %shl, <2 x i64> zeroinitializer
ret <2 x i64> %res
}
define <4 x i32> @neg_masked_shl_v4i32_wrong_bound(<4 x i32> %x, <4 x i32> %amt) {
; CHECK-LABEL: neg_masked_shl_v4i32_wrong_bound:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.4s, #63
; CHECK-NEXT: movi v3.4s, #16
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: ushl v0.4s, v0.4s, v1.4s
; CHECK-NEXT: cmhi v1.4s, v3.4s, v1.4s
; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
; CHECK-NEXT: ret
entry:
%m = and <4 x i32> %amt, splat (i32 63)
%shl = shl <4 x i32> %x, %m
%ok = icmp ult <4 x i32> %m, splat (i32 16)
%res = select <4 x i1> %ok, <4 x i32> %shl, <4 x i32> zeroinitializer
ret <4 x i32> %res
}
define <4 x i32> @neg_masked_ashr_v4i32(<4 x i32> %x, <4 x i32> %amt) {
; CHECK-LABEL: neg_masked_ashr_v4i32:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: movi v2.4s, #63
; CHECK-NEXT: and v1.16b, v1.16b, v2.16b
; CHECK-NEXT: movi v2.4s, #32
; CHECK-NEXT: neg v3.4s, v1.4s
; CHECK-NEXT: cmhi v1.4s, v2.4s, v1.4s
; CHECK-NEXT: sshl v0.4s, v0.4s, v3.4s
; CHECK-NEXT: and v0.16b, v1.16b, v0.16b
; CHECK-NEXT: ret
entry:
%m = and <4 x i32> %amt, splat (i32 63)
%ashr = ashr <4 x i32> %x, %m
%ok = icmp ult <4 x i32> %m, splat (i32 32)
%res = select <4 x i1> %ok, <4 x i32> %ashr, <4 x i32> zeroinitializer
ret <4 x i32> %res
}
attributes #0 = { "target-features"="+sve" }
define <8 x i32> @neg_masked_shl_v8i32_sve_vls(<8 x i32> %x, <8 x i32> %amt) #1 {
; CHECK-LABEL: neg_masked_shl_v8i32_sve_vls:
; CHECK: // %bb.0: // %entry
; CHECK-NEXT: ptrue p0.s, vl4
; CHECK-NEXT: // kill: def $q2 killed $q2 def $z2
; CHECK-NEXT: // kill: def $q3 killed $q3 def $z3
; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0
; CHECK-NEXT: // kill: def $q1 killed $q1 def $z1
; CHECK-NEXT: ptrue p1.s
; CHECK-NEXT: splice z2.s, p0, z2.s, z3.s
; CHECK-NEXT: splice z0.s, p0, z0.s, z1.s
; CHECK-NEXT: and z2.s, z2.s, #0x3f
; CHECK-NEXT: cmplo p0.s, p1/z, z2.s, #32
; CHECK-NEXT: lsl z0.s, p1/m, z0.s, z2.s
; CHECK-NEXT: mov z1.s, p0/z, #-1 // =0xffffffffffffffff
; CHECK-NEXT: and z0.d, z1.d, z0.d
; CHECK-NEXT: movprfx z1, z0
; CHECK-NEXT: ext z1.b, z1.b, z0.b, #16
; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0
; CHECK-NEXT: // kill: def $q1 killed $q1 killed $z1
; CHECK-NEXT: ret
entry:
%m = and <8 x i32> %amt, splat (i32 63)
%shl = shl <8 x i32> %x, %m
%ok = icmp ult <8 x i32> %m, splat (i32 32)
%res = select <8 x i1> %ok, <8 x i32> %shl, <8 x i32> zeroinitializer
ret <8 x i32> %res
}
attributes #1 = { "target-features"="+sve" vscale_range(2,2) }