llvm/llvm/test/CodeGen/AArch64/qmovn.ll

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=aarch64-none-elf -verify-machineinstrs %s -o - | FileCheck %s

define <4 x i16> @vqmovni32_smaxmin(<4 x i32> %s0) {
; CHECK-LABEL: vqmovni32_smaxmin:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtn v0.4h, v0.4s
; CHECK-NEXT:    ret
entry:
  %c1 = icmp slt <4 x i32> %s0, <i32 32767, i32 32767, i32 32767, i32 32767>
  %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>
  %c2 = icmp sgt <4 x i32> %s1, <i32 -32768, i32 -32768, i32 -32768, i32 -32768>
  %s2 = select <4 x i1> %c2, <4 x i32> %s1, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>
  %t = trunc <4 x i32> %s2 to <4 x i16>
  ret <4 x i16> %t
}

define <4 x i16> @vqmovni32_sminmax(<4 x i32> %s0) {
; CHECK-LABEL: vqmovni32_sminmax:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtn v0.4h, v0.4s
; CHECK-NEXT:    ret
entry:
  %c1 = icmp sgt <4 x i32> %s0, <i32 -32768, i32 -32768, i32 -32768, i32 -32768>
  %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>
  %c2 = icmp slt <4 x i32> %s1, <i32 32767, i32 32767, i32 32767, i32 32767>
  %s2 = select <4 x i1> %c2, <4 x i32> %s1, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>
  %t = trunc <4 x i32> %s2 to <4 x i16>
  ret <4 x i16> %t
}

define <4 x i16> @vqmovni32_umaxmin(<4 x i32> %s0) {
; CHECK-LABEL: vqmovni32_umaxmin:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    uqxtn v0.4h, v0.4s
; CHECK-NEXT:    ret
entry:
  %c1 = icmp ult <4 x i32> %s0, <i32 65535, i32 65535, i32 65535, i32 65535>
  %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>
  %t = trunc <4 x i32> %s1 to <4 x i16>
  ret <4 x i16> %t
}

define <8 x i8> @vqmovni16_smaxmin(<8 x i16> %s0) {
; CHECK-LABEL: vqmovni16_smaxmin:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtn v0.8b, v0.8h
; CHECK-NEXT:    ret
entry:
  %c1 = icmp slt <8 x i16> %s0, <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>
  %s1 = select <8 x i1> %c1, <8 x i16> %s0, <8 x i16> <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>
  %c2 = icmp sgt <8 x i16> %s1, <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>
  %s2 = select <8 x i1> %c2, <8 x i16> %s1, <8 x i16> <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>
  %t = trunc <8 x i16> %s2 to <8 x i8>
  ret <8 x i8> %t
}

define <8 x i8> @vqmovni16_sminmax(<8 x i16> %s0) {
; CHECK-LABEL: vqmovni16_sminmax:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtn v0.8b, v0.8h
; CHECK-NEXT:    ret
entry:
  %c1 = icmp sgt <8 x i16> %s0, <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>
  %s1 = select <8 x i1> %c1, <8 x i16> %s0, <8 x i16> <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>
  %c2 = icmp slt <8 x i16> %s1, <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>
  %s2 = select <8 x i1> %c2, <8 x i16> %s1, <8 x i16> <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>
  %t = trunc <8 x i16> %s2 to <8 x i8>
  ret <8 x i8> %t
}

define <8 x i8> @vqmovni16_umaxmin(<8 x i16> %s0) {
; CHECK-LABEL: vqmovni16_umaxmin:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    uqxtn v0.8b, v0.8h
; CHECK-NEXT:    ret
entry:
  %c1 = icmp ult <8 x i16> %s0, <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
  %s1 = select <8 x i1> %c1, <8 x i16> %s0, <8 x i16> <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
  %t = trunc <8 x i16> %s1 to <8 x i8>
  ret <8 x i8> %t
}

define <2 x i32> @vqmovni64_smaxmin(<2 x i64> %s0) {
; CHECK-LABEL: vqmovni64_smaxmin:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtn v0.2s, v0.2d
; CHECK-NEXT:    ret
entry:
  %c1 = icmp slt <2 x i64> %s0, <i64 2147483647, i64 2147483647>
  %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> <i64 2147483647, i64 2147483647>
  %c2 = icmp sgt <2 x i64> %s1, <i64 -2147483648, i64 -2147483648>
  %s2 = select <2 x i1> %c2, <2 x i64> %s1, <2 x i64> <i64 -2147483648, i64 -2147483648>
  %t = trunc <2 x i64> %s2 to <2 x i32>
  ret <2 x i32> %t
}

define <2 x i32> @vqmovni64_sminmax(<2 x i64> %s0) {
; CHECK-LABEL: vqmovni64_sminmax:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtn v0.2s, v0.2d
; CHECK-NEXT:    ret
entry:
  %c1 = icmp sgt <2 x i64> %s0, <i64 -2147483648, i64 -2147483648>
  %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> <i64 -2147483648, i64 -2147483648>
  %c2 = icmp slt <2 x i64> %s1, <i64 2147483647, i64 2147483647>
  %s2 = select <2 x i1> %c2, <2 x i64> %s1, <2 x i64> <i64 2147483647, i64 2147483647>
  %t = trunc <2 x i64> %s2 to <2 x i32>
  ret <2 x i32> %t
}

define <2 x i32> @vqmovni64_smaxmin_u(<2 x i64> %s0) {
; CHECK-LABEL: vqmovni64_smaxmin_u:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtun v0.2s, v0.2d
; CHECK-NEXT:    ret
entry:
  %c1 = icmp slt <2 x i64> %s0, <i64 4294967295, i64 4294967295>
  %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> <i64 4294967295, i64 4294967295>
  %c2 = icmp sgt <2 x i64> %s1, zeroinitializer
  %s2 = select <2 x i1> %c2, <2 x i64> %s1, <2 x i64> zeroinitializer
  %t = trunc <2 x i64> %s2 to <2 x i32>
  ret <2 x i32> %t
}

define <2 x i32> @vqmovni64_sminmax_u(<2 x i64> %s0) {
; CHECK-LABEL: vqmovni64_sminmax_u:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtun v0.2s, v0.2d
; CHECK-NEXT:    ret
entry:
  %c1 = icmp sgt <2 x i64> %s0, zeroinitializer
  %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> zeroinitializer
  %c2 = icmp slt <2 x i64> %s1, <i64 4294967295, i64 4294967295>
  %s2 = select <2 x i1> %c2, <2 x i64> %s1, <2 x i64> <i64 4294967295, i64 4294967295>
  %t = trunc <2 x i64> %s2 to <2 x i32>
  ret <2 x i32> %t
}

define <4 x i16> @vqmovni32_smaxmin_u(<4 x i32> %s0) {
; CHECK-LABEL: vqmovni32_smaxmin_u:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtun v0.4h, v0.4s
; CHECK-NEXT:    ret
entry:
  %c1 = icmp slt <4 x i32> %s0, <i32 65535, i32 65535, i32 65535, i32 65535>
  %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>
  %c2 = icmp sgt <4 x i32> %s1, zeroinitializer
  %s2 = select <4 x i1> %c2, <4 x i32> %s1, <4 x i32> zeroinitializer
  %t = trunc <4 x i32> %s2 to <4 x i16>
  ret <4 x i16> %t
}

define <4 x i16> @vqmovni32_sminmax_u(<4 x i32> %s0) {
; CHECK-LABEL: vqmovni32_sminmax_u:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtun v0.4h, v0.4s
; CHECK-NEXT:    ret
entry:
  %c1 = icmp sgt <4 x i32> %s0, zeroinitializer
  %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> zeroinitializer
  %c2 = icmp slt <4 x i32> %s1, <i32 65535, i32 65535, i32 65535, i32 65535>
  %s2 = select <4 x i1> %c2, <4 x i32> %s1, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>
  %t = trunc <4 x i32> %s2 to <4 x i16>
  ret <4 x i16> %t
}

define <8 x i8> @vqmovni16_smaxmin_u(<8 x i16> %s0) {
; CHECK-LABEL: vqmovni16_smaxmin_u:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtun v0.8b, v0.8h
; CHECK-NEXT:    ret
entry:
  %c1 = icmp slt <8 x i16> %s0, <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
  %s1 = select <8 x i1> %c1, <8 x i16> %s0, <8 x i16> <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
  %c2 = icmp sgt <8 x i16> %s1, zeroinitializer
  %s2 = select <8 x i1> %c2, <8 x i16> %s1, <8 x i16> zeroinitializer
  %t = trunc <8 x i16> %s2 to <8 x i8>
  ret <8 x i8> %t
}

define <8 x i8> @vqmovni16_sminmax_u(<8 x i16> %s0) {
; CHECK-LABEL: vqmovni16_sminmax_u:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    sqxtun v0.8b, v0.8h
; CHECK-NEXT:    ret
entry:
  %c1 = icmp sgt <8 x i16> %s0, zeroinitializer
  %s1 = select <8 x i1> %c1, <8 x i16> %s0, <8 x i16> zeroinitializer
  %c2 = icmp slt <8 x i16> %s1, <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
  %s2 = select <8 x i1> %c2, <8 x i16> %s1, <8 x i16> <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>
  %t = trunc <8 x i16> %s2 to <8 x i8>
  ret <8 x i8> %t
}

define <2 x i32> @vqmovni64_umaxmin(<2 x i64> %s0) {
; CHECK-LABEL: vqmovni64_umaxmin:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    uqxtn v0.2s, v0.2d
; CHECK-NEXT:    ret
entry:
  %c1 = icmp ult <2 x i64> %s0, <i64 4294967295, i64 4294967295>
  %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> <i64 4294967295, i64 4294967295>
  %t = trunc <2 x i64> %s1 to <2 x i32>
  ret <2 x i32> %t
}

; Test the (concat_vectors (X), (trunc(smin(smax(Y, -2^n), 2^n-1))) pattern.

define <16 x i8> @signed_minmax_v8i16_to_v16i8(<8 x i8> %x, <8 x i16> %y) {
; CHECK-LABEL: signed_minmax_v8i16_to_v16i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtn2 v0.16b, v1.8h
; CHECK-NEXT:    ret
entry:
  %min = call <8 x i16> @llvm.smin.v8i16(<8 x i16> %y, <8 x i16> <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>)
  %max = call <8 x i16> @llvm.smax.v8i16(<8 x i16> %min, <8 x i16> <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>)
  %trunc = trunc <8 x i16> %max to <8 x i8>
  %shuffle = shufflevector <8 x i8> %x, <8 x i8> %trunc, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
  ret <16 x i8> %shuffle
}

define <8 x i16> @signed_minmax_v4i32_to_v8i16(<4 x i16> %x, <4 x i32> %y) {
; CHECK-LABEL: signed_minmax_v4i32_to_v8i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtn2 v0.8h, v1.4s
; CHECK-NEXT:    ret
entry:
  %min = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %y, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>)
  %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %min, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>)
  %trunc = trunc <4 x i32> %max to <4 x i16>
  %shuffle = shufflevector <4 x i16> %x, <4 x i16> %trunc, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i16> %shuffle
}

define <4 x i32> @signed_minmax_v2i64_to_v4i32(<2 x i32> %x, <2 x i64> %y) {
; CHECK-LABEL: signed_minmax_v2i64_to_v4i32:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtn2 v0.4s, v1.2d
; CHECK-NEXT:    ret
entry:
  %min = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %y, <2 x i64> <i64 2147483647, i64 2147483647>)
  %max = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %min, <2 x i64> <i64 -2147483648, i64 -2147483648>)
  %trunc = trunc <2 x i64> %max to <2 x i32>
  %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x i32> %shuffle
}

; Test the (concat_vectors (X), (trunc(smax(smin(Y, 2^n-1), -2^n))) pattern.

define <16 x i8> @signed_maxmin_v8i16_to_v16i8(<8 x i8> %x, <8 x i16> %y) {
; CHECK-LABEL: signed_maxmin_v8i16_to_v16i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtn2 v0.16b, v1.8h
; CHECK-NEXT:    ret
entry:
  %max = call <8 x i16> @llvm.smax.v8i16(<8 x i16> %y, <8 x i16> <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>)
  %min = call <8 x i16> @llvm.smin.v8i16(<8 x i16> %max, <8 x i16> <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>)
  %trunc = trunc <8 x i16> %min to <8 x i8>
  %shuffle = shufflevector <8 x i8> %x, <8 x i8> %trunc, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
  ret <16 x i8> %shuffle
}

define <8 x i16> @signed_maxmin_v4i32_to_v8i16(<4 x i16> %x, <4 x i32> %y) {
; CHECK-LABEL: signed_maxmin_v4i32_to_v8i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtn2 v0.8h, v1.4s
; CHECK-NEXT:    ret
entry:
  %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>)
  %min = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %max, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>)
  %trunc = trunc <4 x i32> %min to <4 x i16>
  %shuffle = shufflevector <4 x i16> %x, <4 x i16> %trunc, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i16> %shuffle
}

define <4 x i32> @signed_maxmin_v2i64_to_v4i32(<2 x i32> %x, <2 x i64> %y) {
; CHECK-LABEL: signed_maxmin_v2i64_to_v4i32:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtn2 v0.4s, v1.2d
; CHECK-NEXT:    ret
entry:
  %max = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> <i64 -2147483648, i64 -2147483648>)
  %min = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %max, <2 x i64> <i64 2147483647, i64 2147483647>)
  %trunc = trunc <2 x i64> %min to <2 x i32>
  %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x i32> %shuffle
}

; Test the (concat_vectors (X), (trunc(umin(Y, 2^n)))) pattern.

define <16 x i8> @unsigned_v8i16_to_v16i8(<8 x i8> %x, <8 x i16> %y) {
; CHECK-LABEL: unsigned_v8i16_to_v16i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    uqxtn2 v0.16b, v1.8h
; CHECK-NEXT:    ret
entry:
  %min = call <8 x i16> @llvm.umin.v8i16(<8 x i16> %y, <8 x i16> <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>)
  %trunc = trunc <8 x i16> %min to <8 x i8>
  %shuffle = shufflevector <8 x i8> %x, <8 x i8> %trunc, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
  ret <16 x i8> %shuffle
}

define <8 x i16> @unsigned_v4i32_to_v8i16(<4 x i16> %x, <4 x i32> %y) {
; CHECK-LABEL: unsigned_v4i32_to_v8i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    uqxtn2 v0.8h, v1.4s
; CHECK-NEXT:    ret
entry:
  %min = call <4 x i32> @llvm.umin.v4i32(<4 x i32> %y, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>)
  %trunc = trunc <4 x i32> %min to <4 x i16>
  %shuffle = shufflevector <4 x i16> %x, <4 x i16> %trunc, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i16> %shuffle
}

define <4 x i32> @unsigned_v2i64_to_v4i32(<2 x i32> %x, <2 x i64> %y) {
; CHECK-LABEL: unsigned_v2i64_to_v4i32:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    uqxtn2 v0.4s, v1.2d
; CHECK-NEXT:    ret
entry:
  %min = call <2 x i64> @llvm.umin.v2i64(<2 x i64> %y, <2 x i64> <i64 4294967295, i64 4294967295>)
  %trunc = trunc <2 x i64> %min to <2 x i32>
  %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x i32> %shuffle
}

; Test the (concat_vectors (X), (trunc(umin(smax(Y, 0), 2^n))))) pattern.

define <16 x i8> @us_maxmin_v8i16_to_v16i8(<8 x i8> %x, <8 x i16> %y) {
; CHECK-LABEL: us_maxmin_v8i16_to_v16i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtun2 v0.16b, v1.8h
; CHECK-NEXT:    ret
entry:
  %max = call <8 x i16> @llvm.smax.v8i16(<8 x i16> %y, <8 x i16> zeroinitializer)
  %min = call <8 x i16> @llvm.umin.v8i16(<8 x i16> %max, <8 x i16> <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>)
  %trunc = trunc <8 x i16> %min to <8 x i8>
  %shuffle = shufflevector <8 x i8> %x, <8 x i8> %trunc, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
  ret <16 x i8> %shuffle
}

define <8 x i16> @us_maxmin_v4i32_to_v8i16(<4 x i16> %x, <4 x i32> %y) {
; CHECK-LABEL: us_maxmin_v4i32_to_v8i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtun2 v0.8h, v1.4s
; CHECK-NEXT:    ret
entry:
  %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> zeroinitializer)
  %min = call <4 x i32> @llvm.umin.v4i32(<4 x i32> %max, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>)
  %trunc = trunc <4 x i32> %min to <4 x i16>
  %shuffle = shufflevector <4 x i16> %x, <4 x i16> %trunc, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i16> %shuffle
}

define <4 x i32> @us_maxmin_v2i64_to_v4i32(<2 x i32> %x, <2 x i64> %y) {
; CHECK-LABEL: us_maxmin_v2i64_to_v4i32:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtun2 v0.4s, v1.2d
; CHECK-NEXT:    ret
entry:
  %max = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> zeroinitializer)
  %min = call <2 x i64> @llvm.umin.v2i64(<2 x i64> %max, <2 x i64> <i64 4294967295, i64 4294967295>)
  %trunc = trunc <2 x i64> %min to <2 x i32>
  %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x i32> %shuffle
}

; Test the (concat_vectors (X), (trunc(smin(smax(Y, 0), 2^n))))) pattern.

define <16 x i8> @sminsmax_range_unsigned_i16_to_i8(<8 x i8> %x, <8 x i16> %y) {
; CHECK-LABEL: sminsmax_range_unsigned_i16_to_i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtun2 v0.16b, v1.8h
; CHECK-NEXT:    ret
entry:
  %min = call <8 x i16> @llvm.smax.v8i16(<8 x i16> %y, <8 x i16> zeroinitializer)
  %max = call <8 x i16> @llvm.smin.v8i16(<8 x i16> %min, <8 x i16> <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>)
  %trunc = trunc <8 x i16> %max to <8 x i8>
  %shuffle = shufflevector <8 x i8> %x, <8 x i8> %trunc, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
  ret <16 x i8> %shuffle
}

define <8 x i16> @sminsmax_range_unsigned_i32_to_i16(<4 x i16> %x, <4 x i32> %y) {
; CHECK-LABEL: sminsmax_range_unsigned_i32_to_i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtun2 v0.8h, v1.4s
; CHECK-NEXT:    ret
entry:
  %smax = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> zeroinitializer)
  %smin = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %smax, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>)
  %trunc = trunc <4 x i32> %smin to <4 x i16>
  %shuffle = shufflevector <4 x i16> %x, <4 x i16> %trunc, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i16> %shuffle
}

define <4 x i32> @sminsmax_range_unsigned_i64_to_i32(<2 x i32> %x, <2 x i64> %y) {
; CHECK-LABEL: sminsmax_range_unsigned_i64_to_i32:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
; CHECK-NEXT:    sqxtun2 v0.4s, v1.2d
; CHECK-NEXT:    ret
entry:
  %smax = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> zeroinitializer)
  %smin = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %smax, <2 x i64> <i64 4294967295, i64 4294967295>)
  %trunc = trunc <2 x i64> %smin to <2 x i32>
  %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x i32> %shuffle
}

; Type support varification - not supported with saturated value
; i64 -> i16
define <4 x i16> @sminsmax_range_unsigned_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {
; CHECK-LABEL: sminsmax_range_unsigned_i64_to_i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    cmgt v2.2d, v1.2d, #0
; CHECK-NEXT:    movi v3.2d, #0x0000000000ffff
; CHECK-NEXT:    and v1.16b, v1.16b, v2.16b
; CHECK-NEXT:    cmgt v2.2d, v3.2d, v1.2d
; CHECK-NEXT:    bif v1.16b, v3.16b, v2.16b
; CHECK-NEXT:    xtn v1.2s, v1.2d
; CHECK-NEXT:    uzp1 v0.4h, v0.4h, v1.4h
; CHECK-NEXT:    ret
entry:
  %smax = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> zeroinitializer)
  %smin = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %smax, <2 x i64> <i64 65535, i64 65535>)
  %trunc = trunc <2 x i64> %smin to <2 x i16>
  %shuffle = shufflevector <2 x i16> %x, <2 x i16> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x i16> %shuffle
}

define <4 x i16> @sminsmax_range_signed_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {
; CHECK-LABEL: sminsmax_range_signed_i64_to_i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    mov x8, #-32768 // =0xffffffffffff8000
; CHECK-NEXT:    dup v2.2d, x8
; CHECK-NEXT:    mov w8, #32767 // =0x7fff
; CHECK-NEXT:    cmgt v3.2d, v1.2d, v2.2d
; CHECK-NEXT:    bif v1.16b, v2.16b, v3.16b
; CHECK-NEXT:    dup v2.2d, x8
; CHECK-NEXT:    cmgt v3.2d, v2.2d, v1.2d
; CHECK-NEXT:    bif v1.16b, v2.16b, v3.16b
; CHECK-NEXT:    xtn v1.2s, v1.2d
; CHECK-NEXT:    uzp1 v0.4h, v0.4h, v1.4h
; CHECK-NEXT:    ret
entry:
  %smax = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> <i64 -32768, i64 -32768>)
  %smin = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %smax, <2 x i64> <i64 32767, i64 32767>)
  %trunc = trunc <2 x i64> %smin to <2 x i16>
  %shuffle = shufflevector <2 x i16> %x, <2 x i16> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x i16> %shuffle
}

define <4 x i16> @umin_range_unsigned_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {
; CHECK-LABEL: umin_range_unsigned_i64_to_i16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    movi v2.2d, #0x0000000000ffff
; CHECK-NEXT:    cmhi v3.2d, v2.2d, v1.2d
; CHECK-NEXT:    bif v1.16b, v2.16b, v3.16b
; CHECK-NEXT:    xtn v1.2s, v1.2d
; CHECK-NEXT:    uzp1 v0.4h, v0.4h, v1.4h
; CHECK-NEXT:    ret
entry:
  %umin = call <2 x i64> @llvm.umin.v2i64(<2 x i64> %y, <2 x i64> <i64 65535, i64 65535>)
  %trunc = trunc <2 x i64> %umin to <2 x i16>
  %shuffle = shufflevector <2 x i16> %x, <2 x i16> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
  ret <4 x i16> %shuffle
}

; i32 -> i8
define <8 x i8> @sminsmax_range_unsigned_i64_to_i8(<4 x i8> %x, <4 x i32> %y) {
; CHECK-LABEL: sminsmax_range_unsigned_i64_to_i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    movi v2.2d, #0000000000000000
; CHECK-NEXT:    smax v1.4s, v1.4s, v2.4s
; CHECK-NEXT:    movi v2.2d, #0x0000ff000000ff
; CHECK-NEXT:    smin v1.4s, v1.4s, v2.4s
; CHECK-NEXT:    xtn v1.4h, v1.4s
; CHECK-NEXT:    uzp1 v0.8b, v0.8b, v1.8b
; CHECK-NEXT:    ret
entry:
  %smax = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> zeroinitializer)
  %smin = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %smax, <4 x i32> <i32 255, i32 255, i32 255, i32 255>)
  %trunc = trunc <4 x i32> %smin to <4 x i8>
  %shuffle = shufflevector <4 x i8> %x, <4 x i8> %trunc, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i8> %shuffle
}

define <8 x i8> @sminsmax_range_signed_i32_to_i8(<4 x i8> %x, <4 x i32> %y) {
; CHECK-LABEL: sminsmax_range_signed_i32_to_i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    mvni v2.4s, #127
; CHECK-NEXT:    smax v1.4s, v1.4s, v2.4s
; CHECK-NEXT:    movi v2.4s, #127
; CHECK-NEXT:    smin v1.4s, v1.4s, v2.4s
; CHECK-NEXT:    xtn v1.4h, v1.4s
; CHECK-NEXT:    uzp1 v0.8b, v0.8b, v1.8b
; CHECK-NEXT:    ret
entry:
  %smax = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> <i32 -128, i32 -128, i32 -128, i32 -128>)
  %smin = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %smax, <4 x i32> <i32 127, i32 127, i32 127, i32 127>)
  %trunc = trunc <4 x i32> %smin to <4 x i8>
  %shuffle = shufflevector <4 x i8> %x, <4 x i8> %trunc, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i8> %shuffle
}

define <8 x i8> @umin_range_unsigned_i32_to_i8(<4 x i8> %x, <4 x i32> %y) {
; CHECK-LABEL: umin_range_unsigned_i32_to_i8:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    movi v2.2d, #0x0000ff000000ff
; CHECK-NEXT:    umin v1.4s, v1.4s, v2.4s
; CHECK-NEXT:    xtn v1.4h, v1.4s
; CHECK-NEXT:    uzp1 v0.8b, v0.8b, v1.8b
; CHECK-NEXT:    ret
entry:
  %umin = call <4 x i32> @llvm.umin.v4i32(<4 x i32> %y, <4 x i32> <i32 255, i32 255, i32 255, i32 255>)
  %trunc = trunc <4 x i32> %umin to <4 x i8>
  %shuffle = shufflevector <4 x i8> %x, <4 x i8> %trunc, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
  ret <8 x i8> %shuffle
}