622 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=aarch64-none-elf -verify-machineinstrs -global-isel=0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD3; RUN: llc -mtriple=aarch64-none-elf -verify-machineinstrs -global-isel=1 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI4 5define <4 x i16> @vqmovni32_smaxmin(<4 x i32> %s0) {6; CHECK-LABEL: vqmovni32_smaxmin:7; CHECK: // %bb.0: // %entry8; CHECK-NEXT: sqxtn v0.4h, v0.4s9; CHECK-NEXT: ret10entry:11 %c1 = icmp slt <4 x i32> %s0, <i32 32767, i32 32767, i32 32767, i32 32767>12 %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>13 %c2 = icmp sgt <4 x i32> %s1, <i32 -32768, i32 -32768, i32 -32768, i32 -32768>14 %s2 = select <4 x i1> %c2, <4 x i32> %s1, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>15 %t = trunc <4 x i32> %s2 to <4 x i16>16 ret <4 x i16> %t17}18 19define <4 x i16> @vqmovni32_sminmax(<4 x i32> %s0) {20; CHECK-LABEL: vqmovni32_sminmax:21; CHECK: // %bb.0: // %entry22; CHECK-NEXT: sqxtn v0.4h, v0.4s23; CHECK-NEXT: ret24entry:25 %c1 = icmp sgt <4 x i32> %s0, <i32 -32768, i32 -32768, i32 -32768, i32 -32768>26 %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>27 %c2 = icmp slt <4 x i32> %s1, <i32 32767, i32 32767, i32 32767, i32 32767>28 %s2 = select <4 x i1> %c2, <4 x i32> %s1, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>29 %t = trunc <4 x i32> %s2 to <4 x i16>30 ret <4 x i16> %t31}32 33define <4 x i16> @vqmovni32_umaxmin(<4 x i32> %s0) {34; CHECK-LABEL: vqmovni32_umaxmin:35; CHECK: // %bb.0: // %entry36; CHECK-NEXT: uqxtn v0.4h, v0.4s37; CHECK-NEXT: ret38entry:39 %c1 = icmp ult <4 x i32> %s0, <i32 65535, i32 65535, i32 65535, i32 65535>40 %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>41 %t = trunc <4 x i32> %s1 to <4 x i16>42 ret <4 x i16> %t43}44 45define <8 x i8> @vqmovni16_smaxmin(<8 x i16> %s0) {46; CHECK-LABEL: vqmovni16_smaxmin:47; CHECK: // %bb.0: // %entry48; CHECK-NEXT: sqxtn v0.8b, v0.8h49; CHECK-NEXT: ret50entry:51 %c1 = icmp slt <8 x i16> %s0, <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>52 %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>53 %c2 = icmp sgt <8 x i16> %s1, <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>54 %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>55 %t = trunc <8 x i16> %s2 to <8 x i8>56 ret <8 x i8> %t57}58 59define <8 x i8> @vqmovni16_sminmax(<8 x i16> %s0) {60; CHECK-LABEL: vqmovni16_sminmax:61; CHECK: // %bb.0: // %entry62; CHECK-NEXT: sqxtn v0.8b, v0.8h63; CHECK-NEXT: ret64entry:65 %c1 = icmp sgt <8 x i16> %s0, <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>66 %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>67 %c2 = icmp slt <8 x i16> %s1, <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>68 %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>69 %t = trunc <8 x i16> %s2 to <8 x i8>70 ret <8 x i8> %t71}72 73define <8 x i8> @vqmovni16_umaxmin(<8 x i16> %s0) {74; CHECK-LABEL: vqmovni16_umaxmin:75; CHECK: // %bb.0: // %entry76; CHECK-NEXT: uqxtn v0.8b, v0.8h77; CHECK-NEXT: ret78entry:79 %c1 = icmp ult <8 x i16> %s0, <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>80 %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>81 %t = trunc <8 x i16> %s1 to <8 x i8>82 ret <8 x i8> %t83}84 85define <2 x i32> @vqmovni64_smaxmin(<2 x i64> %s0) {86; CHECK-LABEL: vqmovni64_smaxmin:87; CHECK: // %bb.0: // %entry88; CHECK-NEXT: sqxtn v0.2s, v0.2d89; CHECK-NEXT: ret90entry:91 %c1 = icmp slt <2 x i64> %s0, <i64 2147483647, i64 2147483647>92 %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> <i64 2147483647, i64 2147483647>93 %c2 = icmp sgt <2 x i64> %s1, <i64 -2147483648, i64 -2147483648>94 %s2 = select <2 x i1> %c2, <2 x i64> %s1, <2 x i64> <i64 -2147483648, i64 -2147483648>95 %t = trunc <2 x i64> %s2 to <2 x i32>96 ret <2 x i32> %t97}98 99define <2 x i32> @vqmovni64_sminmax(<2 x i64> %s0) {100; CHECK-LABEL: vqmovni64_sminmax:101; CHECK: // %bb.0: // %entry102; CHECK-NEXT: sqxtn v0.2s, v0.2d103; CHECK-NEXT: ret104entry:105 %c1 = icmp sgt <2 x i64> %s0, <i64 -2147483648, i64 -2147483648>106 %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> <i64 -2147483648, i64 -2147483648>107 %c2 = icmp slt <2 x i64> %s1, <i64 2147483647, i64 2147483647>108 %s2 = select <2 x i1> %c2, <2 x i64> %s1, <2 x i64> <i64 2147483647, i64 2147483647>109 %t = trunc <2 x i64> %s2 to <2 x i32>110 ret <2 x i32> %t111}112 113define <2 x i32> @vqmovni64_smaxmin_u(<2 x i64> %s0) {114; CHECK-LABEL: vqmovni64_smaxmin_u:115; CHECK: // %bb.0: // %entry116; CHECK-NEXT: sqxtun v0.2s, v0.2d117; CHECK-NEXT: ret118entry:119 %c1 = icmp slt <2 x i64> %s0, <i64 4294967295, i64 4294967295>120 %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> <i64 4294967295, i64 4294967295>121 %c2 = icmp sgt <2 x i64> %s1, zeroinitializer122 %s2 = select <2 x i1> %c2, <2 x i64> %s1, <2 x i64> zeroinitializer123 %t = trunc <2 x i64> %s2 to <2 x i32>124 ret <2 x i32> %t125}126 127define <2 x i32> @vqmovni64_sminmax_u(<2 x i64> %s0) {128; CHECK-LABEL: vqmovni64_sminmax_u:129; CHECK: // %bb.0: // %entry130; CHECK-NEXT: sqxtun v0.2s, v0.2d131; CHECK-NEXT: ret132entry:133 %c1 = icmp sgt <2 x i64> %s0, zeroinitializer134 %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> zeroinitializer135 %c2 = icmp slt <2 x i64> %s1, <i64 4294967295, i64 4294967295>136 %s2 = select <2 x i1> %c2, <2 x i64> %s1, <2 x i64> <i64 4294967295, i64 4294967295>137 %t = trunc <2 x i64> %s2 to <2 x i32>138 ret <2 x i32> %t139}140 141define <4 x i16> @vqmovni32_smaxmin_u(<4 x i32> %s0) {142; CHECK-LABEL: vqmovni32_smaxmin_u:143; CHECK: // %bb.0: // %entry144; CHECK-NEXT: sqxtun v0.4h, v0.4s145; CHECK-NEXT: ret146entry:147 %c1 = icmp slt <4 x i32> %s0, <i32 65535, i32 65535, i32 65535, i32 65535>148 %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>149 %c2 = icmp sgt <4 x i32> %s1, zeroinitializer150 %s2 = select <4 x i1> %c2, <4 x i32> %s1, <4 x i32> zeroinitializer151 %t = trunc <4 x i32> %s2 to <4 x i16>152 ret <4 x i16> %t153}154 155define <4 x i16> @vqmovni32_sminmax_u(<4 x i32> %s0) {156; CHECK-LABEL: vqmovni32_sminmax_u:157; CHECK: // %bb.0: // %entry158; CHECK-NEXT: sqxtun v0.4h, v0.4s159; CHECK-NEXT: ret160entry:161 %c1 = icmp sgt <4 x i32> %s0, zeroinitializer162 %s1 = select <4 x i1> %c1, <4 x i32> %s0, <4 x i32> zeroinitializer163 %c2 = icmp slt <4 x i32> %s1, <i32 65535, i32 65535, i32 65535, i32 65535>164 %s2 = select <4 x i1> %c2, <4 x i32> %s1, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>165 %t = trunc <4 x i32> %s2 to <4 x i16>166 ret <4 x i16> %t167}168 169define <8 x i8> @vqmovni16_smaxmin_u(<8 x i16> %s0) {170; CHECK-LABEL: vqmovni16_smaxmin_u:171; CHECK: // %bb.0: // %entry172; CHECK-NEXT: sqxtun v0.8b, v0.8h173; CHECK-NEXT: ret174entry:175 %c1 = icmp slt <8 x i16> %s0, <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>176 %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>177 %c2 = icmp sgt <8 x i16> %s1, zeroinitializer178 %s2 = select <8 x i1> %c2, <8 x i16> %s1, <8 x i16> zeroinitializer179 %t = trunc <8 x i16> %s2 to <8 x i8>180 ret <8 x i8> %t181}182 183define <8 x i8> @vqmovni16_sminmax_u(<8 x i16> %s0) {184; CHECK-LABEL: vqmovni16_sminmax_u:185; CHECK: // %bb.0: // %entry186; CHECK-NEXT: sqxtun v0.8b, v0.8h187; CHECK-NEXT: ret188entry:189 %c1 = icmp sgt <8 x i16> %s0, zeroinitializer190 %s1 = select <8 x i1> %c1, <8 x i16> %s0, <8 x i16> zeroinitializer191 %c2 = icmp slt <8 x i16> %s1, <i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255, i16 255>192 %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>193 %t = trunc <8 x i16> %s2 to <8 x i8>194 ret <8 x i8> %t195}196 197define <2 x i32> @vqmovni64_umaxmin(<2 x i64> %s0) {198; CHECK-LABEL: vqmovni64_umaxmin:199; CHECK: // %bb.0: // %entry200; CHECK-NEXT: uqxtn v0.2s, v0.2d201; CHECK-NEXT: ret202entry:203 %c1 = icmp ult <2 x i64> %s0, <i64 4294967295, i64 4294967295>204 %s1 = select <2 x i1> %c1, <2 x i64> %s0, <2 x i64> <i64 4294967295, i64 4294967295>205 %t = trunc <2 x i64> %s1 to <2 x i32>206 ret <2 x i32> %t207}208 209; Test the (concat_vectors (X), (trunc(smin(smax(Y, -2^n), 2^n-1))) pattern.210 211define <16 x i8> @signed_minmax_v8i16_to_v16i8(<8 x i8> %x, <8 x i16> %y) {212; CHECK-LABEL: signed_minmax_v8i16_to_v16i8:213; CHECK: // %bb.0: // %entry214; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0215; CHECK-NEXT: sqxtn2 v0.16b, v1.8h216; CHECK-NEXT: ret217entry:218 %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>)219 %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>)220 %trunc = trunc <8 x i16> %max to <8 x i8>221 %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>222 ret <16 x i8> %shuffle223}224 225define <8 x i16> @signed_minmax_v4i32_to_v8i16(<4 x i16> %x, <4 x i32> %y) {226; CHECK-LABEL: signed_minmax_v4i32_to_v8i16:227; CHECK: // %bb.0: // %entry228; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0229; CHECK-NEXT: sqxtn2 v0.8h, v1.4s230; CHECK-NEXT: ret231entry:232 %min = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %y, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>)233 %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %min, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>)234 %trunc = trunc <4 x i32> %max to <4 x i16>235 %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>236 ret <8 x i16> %shuffle237}238 239define <4 x i32> @signed_minmax_v2i64_to_v4i32(<2 x i32> %x, <2 x i64> %y) {240; CHECK-LABEL: signed_minmax_v2i64_to_v4i32:241; CHECK: // %bb.0: // %entry242; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0243; CHECK-NEXT: sqxtn2 v0.4s, v1.2d244; CHECK-NEXT: ret245entry:246 %min = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %y, <2 x i64> <i64 2147483647, i64 2147483647>)247 %max = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %min, <2 x i64> <i64 -2147483648, i64 -2147483648>)248 %trunc = trunc <2 x i64> %max to <2 x i32>249 %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>250 ret <4 x i32> %shuffle251}252 253; Test the (concat_vectors (X), (trunc(smax(smin(Y, 2^n-1), -2^n))) pattern.254 255define <16 x i8> @signed_maxmin_v8i16_to_v16i8(<8 x i8> %x, <8 x i16> %y) {256; CHECK-LABEL: signed_maxmin_v8i16_to_v16i8:257; CHECK: // %bb.0: // %entry258; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0259; CHECK-NEXT: sqxtn2 v0.16b, v1.8h260; CHECK-NEXT: ret261entry:262 %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>)263 %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>)264 %trunc = trunc <8 x i16> %min to <8 x i8>265 %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>266 ret <16 x i8> %shuffle267}268 269define <8 x i16> @signed_maxmin_v4i32_to_v8i16(<4 x i16> %x, <4 x i32> %y) {270; CHECK-LABEL: signed_maxmin_v4i32_to_v8i16:271; CHECK: // %bb.0: // %entry272; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0273; CHECK-NEXT: sqxtn2 v0.8h, v1.4s274; CHECK-NEXT: ret275entry:276 %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> <i32 -32768, i32 -32768, i32 -32768, i32 -32768>)277 %min = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %max, <4 x i32> <i32 32767, i32 32767, i32 32767, i32 32767>)278 %trunc = trunc <4 x i32> %min to <4 x i16>279 %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>280 ret <8 x i16> %shuffle281}282 283define <4 x i32> @signed_maxmin_v2i64_to_v4i32(<2 x i32> %x, <2 x i64> %y) {284; CHECK-LABEL: signed_maxmin_v2i64_to_v4i32:285; CHECK: // %bb.0: // %entry286; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0287; CHECK-NEXT: sqxtn2 v0.4s, v1.2d288; CHECK-NEXT: ret289entry:290 %max = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> <i64 -2147483648, i64 -2147483648>)291 %min = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %max, <2 x i64> <i64 2147483647, i64 2147483647>)292 %trunc = trunc <2 x i64> %min to <2 x i32>293 %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>294 ret <4 x i32> %shuffle295}296 297; Test the (concat_vectors (X), (trunc(umin(Y, 2^n)))) pattern.298 299define <16 x i8> @unsigned_v8i16_to_v16i8(<8 x i8> %x, <8 x i16> %y) {300; CHECK-LABEL: unsigned_v8i16_to_v16i8:301; CHECK: // %bb.0: // %entry302; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0303; CHECK-NEXT: uqxtn2 v0.16b, v1.8h304; CHECK-NEXT: ret305entry:306 %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>)307 %trunc = trunc <8 x i16> %min to <8 x i8>308 %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>309 ret <16 x i8> %shuffle310}311 312define <8 x i16> @unsigned_v4i32_to_v8i16(<4 x i16> %x, <4 x i32> %y) {313; CHECK-LABEL: unsigned_v4i32_to_v8i16:314; CHECK: // %bb.0: // %entry315; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0316; CHECK-NEXT: uqxtn2 v0.8h, v1.4s317; CHECK-NEXT: ret318entry:319 %min = call <4 x i32> @llvm.umin.v4i32(<4 x i32> %y, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>)320 %trunc = trunc <4 x i32> %min to <4 x i16>321 %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>322 ret <8 x i16> %shuffle323}324 325define <4 x i32> @unsigned_v2i64_to_v4i32(<2 x i32> %x, <2 x i64> %y) {326; CHECK-LABEL: unsigned_v2i64_to_v4i32:327; CHECK: // %bb.0: // %entry328; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0329; CHECK-NEXT: uqxtn2 v0.4s, v1.2d330; CHECK-NEXT: ret331entry:332 %min = call <2 x i64> @llvm.umin.v2i64(<2 x i64> %y, <2 x i64> <i64 4294967295, i64 4294967295>)333 %trunc = trunc <2 x i64> %min to <2 x i32>334 %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>335 ret <4 x i32> %shuffle336}337 338; Test the (concat_vectors (X), (trunc(umin(smax(Y, 0), 2^n))))) pattern.339 340define <16 x i8> @us_maxmin_v8i16_to_v16i8(<8 x i8> %x, <8 x i16> %y) {341; CHECK-LABEL: us_maxmin_v8i16_to_v16i8:342; CHECK: // %bb.0: // %entry343; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0344; CHECK-NEXT: sqxtun2 v0.16b, v1.8h345; CHECK-NEXT: ret346entry:347 %max = call <8 x i16> @llvm.smax.v8i16(<8 x i16> %y, <8 x i16> zeroinitializer)348 %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>)349 %trunc = trunc <8 x i16> %min to <8 x i8>350 %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>351 ret <16 x i8> %shuffle352}353 354define <8 x i16> @us_maxmin_v4i32_to_v8i16(<4 x i16> %x, <4 x i32> %y) {355; CHECK-LABEL: us_maxmin_v4i32_to_v8i16:356; CHECK: // %bb.0: // %entry357; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0358; CHECK-NEXT: sqxtun2 v0.8h, v1.4s359; CHECK-NEXT: ret360entry:361 %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> zeroinitializer)362 %min = call <4 x i32> @llvm.umin.v4i32(<4 x i32> %max, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>)363 %trunc = trunc <4 x i32> %min to <4 x i16>364 %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>365 ret <8 x i16> %shuffle366}367 368define <4 x i32> @us_maxmin_v2i64_to_v4i32(<2 x i32> %x, <2 x i64> %y) {369; CHECK-LABEL: us_maxmin_v2i64_to_v4i32:370; CHECK: // %bb.0: // %entry371; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0372; CHECK-NEXT: sqxtun2 v0.4s, v1.2d373; CHECK-NEXT: ret374entry:375 %max = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> zeroinitializer)376 %min = call <2 x i64> @llvm.umin.v2i64(<2 x i64> %max, <2 x i64> <i64 4294967295, i64 4294967295>)377 %trunc = trunc <2 x i64> %min to <2 x i32>378 %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>379 ret <4 x i32> %shuffle380}381 382; Test the (concat_vectors (X), (trunc(smin(smax(Y, 0), 2^n))))) pattern.383 384define <16 x i8> @sminsmax_range_unsigned_i16_to_i8(<8 x i8> %x, <8 x i16> %y) {385; CHECK-LABEL: sminsmax_range_unsigned_i16_to_i8:386; CHECK: // %bb.0: // %entry387; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0388; CHECK-NEXT: sqxtun2 v0.16b, v1.8h389; CHECK-NEXT: ret390entry:391 %min = call <8 x i16> @llvm.smax.v8i16(<8 x i16> %y, <8 x i16> zeroinitializer)392 %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>)393 %trunc = trunc <8 x i16> %max to <8 x i8>394 %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>395 ret <16 x i8> %shuffle396}397 398define <8 x i16> @sminsmax_range_unsigned_i32_to_i16(<4 x i16> %x, <4 x i32> %y) {399; CHECK-LABEL: sminsmax_range_unsigned_i32_to_i16:400; CHECK: // %bb.0: // %entry401; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0402; CHECK-NEXT: sqxtun2 v0.8h, v1.4s403; CHECK-NEXT: ret404entry:405 %smax = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> zeroinitializer)406 %smin = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %smax, <4 x i32> <i32 65535, i32 65535, i32 65535, i32 65535>)407 %trunc = trunc <4 x i32> %smin to <4 x i16>408 %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>409 ret <8 x i16> %shuffle410}411 412define <4 x i32> @sminsmax_range_unsigned_i64_to_i32(<2 x i32> %x, <2 x i64> %y) {413; CHECK-LABEL: sminsmax_range_unsigned_i64_to_i32:414; CHECK: // %bb.0: // %entry415; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0416; CHECK-NEXT: sqxtun2 v0.4s, v1.2d417; CHECK-NEXT: ret418entry:419 %smax = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> zeroinitializer)420 %smin = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %smax, <2 x i64> <i64 4294967295, i64 4294967295>)421 %trunc = trunc <2 x i64> %smin to <2 x i32>422 %shuffle = shufflevector <2 x i32> %x, <2 x i32> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>423 ret <4 x i32> %shuffle424}425 426; Type support varification - not supported with saturated value427; i64 -> i16428define <4 x i16> @sminsmax_range_unsigned_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {429; CHECK-SD-LABEL: sminsmax_range_unsigned_i64_to_i16:430; CHECK-SD: // %bb.0: // %entry431; CHECK-SD-NEXT: cmgt v2.2d, v1.2d, #0432; CHECK-SD-NEXT: movi v3.2d, #0x0000000000ffff433; CHECK-SD-NEXT: and v1.16b, v1.16b, v2.16b434; CHECK-SD-NEXT: cmgt v2.2d, v3.2d, v1.2d435; CHECK-SD-NEXT: bif v1.16b, v3.16b, v2.16b436; CHECK-SD-NEXT: xtn v1.2s, v1.2d437; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h438; CHECK-SD-NEXT: ret439;440; CHECK-GI-LABEL: sminsmax_range_unsigned_i64_to_i16:441; CHECK-GI: // %bb.0: // %entry442; CHECK-GI-NEXT: cmgt v2.2d, v1.2d, #0443; CHECK-GI-NEXT: movi v3.2d, #0x0000000000ffff444; CHECK-GI-NEXT: and v1.16b, v1.16b, v2.16b445; CHECK-GI-NEXT: cmgt v2.2d, v3.2d, v1.2d446; CHECK-GI-NEXT: bif v1.16b, v3.16b, v2.16b447; CHECK-GI-NEXT: xtn v1.2s, v1.2d448; CHECK-GI-NEXT: uzp1 v1.4h, v1.4h, v0.4h449; CHECK-GI-NEXT: uzp1 v0.4h, v0.4h, v0.4h450; CHECK-GI-NEXT: fmov w8, s1451; CHECK-GI-NEXT: mov v0.s[1], w8452; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0453; CHECK-GI-NEXT: ret454entry:455 %smax = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> zeroinitializer)456 %smin = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %smax, <2 x i64> <i64 65535, i64 65535>)457 %trunc = trunc <2 x i64> %smin to <2 x i16>458 %shuffle = shufflevector <2 x i16> %x, <2 x i16> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>459 ret <4 x i16> %shuffle460}461 462define <4 x i16> @sminsmax_range_signed_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {463; CHECK-SD-LABEL: sminsmax_range_signed_i64_to_i16:464; CHECK-SD: // %bb.0: // %entry465; CHECK-SD-NEXT: mov x8, #-32768 // =0xffffffffffff8000466; CHECK-SD-NEXT: dup v2.2d, x8467; CHECK-SD-NEXT: mov w8, #32767 // =0x7fff468; CHECK-SD-NEXT: cmgt v3.2d, v1.2d, v2.2d469; CHECK-SD-NEXT: bif v1.16b, v2.16b, v3.16b470; CHECK-SD-NEXT: dup v2.2d, x8471; CHECK-SD-NEXT: cmgt v3.2d, v2.2d, v1.2d472; CHECK-SD-NEXT: bif v1.16b, v2.16b, v3.16b473; CHECK-SD-NEXT: xtn v1.2s, v1.2d474; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h475; CHECK-SD-NEXT: ret476;477; CHECK-GI-LABEL: sminsmax_range_signed_i64_to_i16:478; CHECK-GI: // %bb.0: // %entry479; CHECK-GI-NEXT: adrp x8, .LCPI31_1480; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI31_1]481; CHECK-GI-NEXT: adrp x8, .LCPI31_0482; CHECK-GI-NEXT: cmgt v3.2d, v1.2d, v2.2d483; CHECK-GI-NEXT: bif v1.16b, v2.16b, v3.16b484; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI31_0]485; CHECK-GI-NEXT: cmgt v3.2d, v2.2d, v1.2d486; CHECK-GI-NEXT: bif v1.16b, v2.16b, v3.16b487; CHECK-GI-NEXT: xtn v1.2s, v1.2d488; CHECK-GI-NEXT: uzp1 v1.4h, v1.4h, v0.4h489; CHECK-GI-NEXT: uzp1 v0.4h, v0.4h, v0.4h490; CHECK-GI-NEXT: fmov w8, s1491; CHECK-GI-NEXT: mov v0.s[1], w8492; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0493; CHECK-GI-NEXT: ret494entry:495 %smax = call <2 x i64> @llvm.smax.v2i64(<2 x i64> %y, <2 x i64> <i64 -32768, i64 -32768>)496 %smin = call <2 x i64> @llvm.smin.v2i64(<2 x i64> %smax, <2 x i64> <i64 32767, i64 32767>)497 %trunc = trunc <2 x i64> %smin to <2 x i16>498 %shuffle = shufflevector <2 x i16> %x, <2 x i16> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>499 ret <4 x i16> %shuffle500}501 502define <4 x i16> @umin_range_unsigned_i64_to_i16(<2 x i16> %x, <2 x i64> %y) {503; CHECK-SD-LABEL: umin_range_unsigned_i64_to_i16:504; CHECK-SD: // %bb.0: // %entry505; CHECK-SD-NEXT: movi v2.2d, #0x0000000000ffff506; CHECK-SD-NEXT: cmhi v3.2d, v2.2d, v1.2d507; CHECK-SD-NEXT: bif v1.16b, v2.16b, v3.16b508; CHECK-SD-NEXT: xtn v1.2s, v1.2d509; CHECK-SD-NEXT: uzp1 v0.4h, v0.4h, v1.4h510; CHECK-SD-NEXT: ret511;512; CHECK-GI-LABEL: umin_range_unsigned_i64_to_i16:513; CHECK-GI: // %bb.0: // %entry514; CHECK-GI-NEXT: movi v2.2d, #0x0000000000ffff515; CHECK-GI-NEXT: cmhi v3.2d, v2.2d, v1.2d516; CHECK-GI-NEXT: bif v1.16b, v2.16b, v3.16b517; CHECK-GI-NEXT: xtn v1.2s, v1.2d518; CHECK-GI-NEXT: uzp1 v1.4h, v1.4h, v0.4h519; CHECK-GI-NEXT: uzp1 v0.4h, v0.4h, v0.4h520; CHECK-GI-NEXT: fmov w8, s1521; CHECK-GI-NEXT: mov v0.s[1], w8522; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0523; CHECK-GI-NEXT: ret524entry:525 %umin = call <2 x i64> @llvm.umin.v2i64(<2 x i64> %y, <2 x i64> <i64 65535, i64 65535>)526 %trunc = trunc <2 x i64> %umin to <2 x i16>527 %shuffle = shufflevector <2 x i16> %x, <2 x i16> %trunc, <4 x i32> <i32 0, i32 1, i32 2, i32 3>528 ret <4 x i16> %shuffle529}530 531; i32 -> i8532define <8 x i8> @sminsmax_range_unsigned_i64_to_i8(<4 x i8> %x, <4 x i32> %y) {533; CHECK-SD-LABEL: sminsmax_range_unsigned_i64_to_i8:534; CHECK-SD: // %bb.0: // %entry535; CHECK-SD-NEXT: movi v2.2d, #0000000000000000536; CHECK-SD-NEXT: smax v1.4s, v1.4s, v2.4s537; CHECK-SD-NEXT: movi v2.2d, #0x0000ff000000ff538; CHECK-SD-NEXT: smin v1.4s, v1.4s, v2.4s539; CHECK-SD-NEXT: xtn v1.4h, v1.4s540; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b541; CHECK-SD-NEXT: ret542;543; CHECK-GI-LABEL: sminsmax_range_unsigned_i64_to_i8:544; CHECK-GI: // %bb.0: // %entry545; CHECK-GI-NEXT: movi v2.2d, #0000000000000000546; CHECK-GI-NEXT: movi v3.2d, #0x0000ff000000ff547; CHECK-GI-NEXT: smax v1.4s, v1.4s, v2.4s548; CHECK-GI-NEXT: smin v1.4s, v1.4s, v3.4s549; CHECK-GI-NEXT: xtn v1.4h, v1.4s550; CHECK-GI-NEXT: uzp1 v1.8b, v1.8b, v0.8b551; CHECK-GI-NEXT: uzp1 v0.8b, v0.8b, v0.8b552; CHECK-GI-NEXT: fmov w8, s1553; CHECK-GI-NEXT: mov v0.s[1], w8554; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0555; CHECK-GI-NEXT: ret556entry:557 %smax = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> zeroinitializer)558 %smin = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %smax, <4 x i32> <i32 255, i32 255, i32 255, i32 255>)559 %trunc = trunc <4 x i32> %smin to <4 x i8>560 %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>561 ret <8 x i8> %shuffle562}563 564define <8 x i8> @sminsmax_range_signed_i32_to_i8(<4 x i8> %x, <4 x i32> %y) {565; CHECK-SD-LABEL: sminsmax_range_signed_i32_to_i8:566; CHECK-SD: // %bb.0: // %entry567; CHECK-SD-NEXT: mvni v2.4s, #127568; CHECK-SD-NEXT: smax v1.4s, v1.4s, v2.4s569; CHECK-SD-NEXT: movi v2.4s, #127570; CHECK-SD-NEXT: smin v1.4s, v1.4s, v2.4s571; CHECK-SD-NEXT: xtn v1.4h, v1.4s572; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b573; CHECK-SD-NEXT: ret574;575; CHECK-GI-LABEL: sminsmax_range_signed_i32_to_i8:576; CHECK-GI: // %bb.0: // %entry577; CHECK-GI-NEXT: mvni v2.4s, #127578; CHECK-GI-NEXT: movi v3.4s, #127579; CHECK-GI-NEXT: smax v1.4s, v1.4s, v2.4s580; CHECK-GI-NEXT: smin v1.4s, v1.4s, v3.4s581; CHECK-GI-NEXT: xtn v1.4h, v1.4s582; CHECK-GI-NEXT: uzp1 v1.8b, v1.8b, v0.8b583; CHECK-GI-NEXT: uzp1 v0.8b, v0.8b, v0.8b584; CHECK-GI-NEXT: fmov w8, s1585; CHECK-GI-NEXT: mov v0.s[1], w8586; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0587; CHECK-GI-NEXT: ret588entry:589 %smax = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %y, <4 x i32> <i32 -128, i32 -128, i32 -128, i32 -128>)590 %smin = call <4 x i32> @llvm.smin.v4i32(<4 x i32> %smax, <4 x i32> <i32 127, i32 127, i32 127, i32 127>)591 %trunc = trunc <4 x i32> %smin to <4 x i8>592 %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>593 ret <8 x i8> %shuffle594}595 596define <8 x i8> @umin_range_unsigned_i32_to_i8(<4 x i8> %x, <4 x i32> %y) {597; CHECK-SD-LABEL: umin_range_unsigned_i32_to_i8:598; CHECK-SD: // %bb.0: // %entry599; CHECK-SD-NEXT: movi v2.2d, #0x0000ff000000ff600; CHECK-SD-NEXT: umin v1.4s, v1.4s, v2.4s601; CHECK-SD-NEXT: xtn v1.4h, v1.4s602; CHECK-SD-NEXT: uzp1 v0.8b, v0.8b, v1.8b603; CHECK-SD-NEXT: ret604;605; CHECK-GI-LABEL: umin_range_unsigned_i32_to_i8:606; CHECK-GI: // %bb.0: // %entry607; CHECK-GI-NEXT: movi v2.2d, #0x0000ff000000ff608; CHECK-GI-NEXT: umin v1.4s, v1.4s, v2.4s609; CHECK-GI-NEXT: xtn v1.4h, v1.4s610; CHECK-GI-NEXT: uzp1 v1.8b, v1.8b, v0.8b611; CHECK-GI-NEXT: uzp1 v0.8b, v0.8b, v0.8b612; CHECK-GI-NEXT: fmov w8, s1613; CHECK-GI-NEXT: mov v0.s[1], w8614; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0615; CHECK-GI-NEXT: ret616entry:617 %umin = call <4 x i32> @llvm.umin.v4i32(<4 x i32> %y, <4 x i32> <i32 255, i32 255, i32 255, i32 255>)618 %trunc = trunc <4 x i32> %umin to <4 x i8>619 %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>620 ret <8 x i8> %shuffle621}622