711 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s --check-prefixes=CHECK,CHECK-SD3; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI4 5define <8 x i8> @v_dup8(i8 %A) nounwind {6; CHECK-LABEL: v_dup8:7; CHECK: // %bb.0:8; CHECK-NEXT: dup.8b v0, w09; CHECK-NEXT: ret10 %tmp1 = insertelement <8 x i8> zeroinitializer, i8 %A, i32 011 %tmp2 = insertelement <8 x i8> %tmp1, i8 %A, i32 112 %tmp3 = insertelement <8 x i8> %tmp2, i8 %A, i32 213 %tmp4 = insertelement <8 x i8> %tmp3, i8 %A, i32 314 %tmp5 = insertelement <8 x i8> %tmp4, i8 %A, i32 415 %tmp6 = insertelement <8 x i8> %tmp5, i8 %A, i32 516 %tmp7 = insertelement <8 x i8> %tmp6, i8 %A, i32 617 %tmp8 = insertelement <8 x i8> %tmp7, i8 %A, i32 718 ret <8 x i8> %tmp819}20 21define <4 x i16> @v_dup16(i16 %A) nounwind {22; CHECK-LABEL: v_dup16:23; CHECK: // %bb.0:24; CHECK-NEXT: dup.4h v0, w025; CHECK-NEXT: ret26 %tmp1 = insertelement <4 x i16> zeroinitializer, i16 %A, i32 027 %tmp2 = insertelement <4 x i16> %tmp1, i16 %A, i32 128 %tmp3 = insertelement <4 x i16> %tmp2, i16 %A, i32 229 %tmp4 = insertelement <4 x i16> %tmp3, i16 %A, i32 330 ret <4 x i16> %tmp431}32 33define <2 x i32> @v_dup32(i32 %A) nounwind {34; CHECK-LABEL: v_dup32:35; CHECK: // %bb.0:36; CHECK-NEXT: dup.2s v0, w037; CHECK-NEXT: ret38 %tmp1 = insertelement <2 x i32> zeroinitializer, i32 %A, i32 039 %tmp2 = insertelement <2 x i32> %tmp1, i32 %A, i32 140 ret <2 x i32> %tmp241}42 43define <2 x float> @v_dupfloat(float %A) nounwind {44; CHECK-LABEL: v_dupfloat:45; CHECK: // %bb.0:46; CHECK-NEXT: // kill: def $s0 killed $s0 def $q047; CHECK-NEXT: dup.2s v0, v0[0]48; CHECK-NEXT: ret49 %tmp1 = insertelement <2 x float> zeroinitializer, float %A, i32 050 %tmp2 = insertelement <2 x float> %tmp1, float %A, i32 151 ret <2 x float> %tmp252}53 54define <16 x i8> @v_dupQ8(i8 %A) nounwind {55; CHECK-LABEL: v_dupQ8:56; CHECK: // %bb.0:57; CHECK-NEXT: dup.16b v0, w058; CHECK-NEXT: ret59 %tmp1 = insertelement <16 x i8> zeroinitializer, i8 %A, i32 060 %tmp2 = insertelement <16 x i8> %tmp1, i8 %A, i32 161 %tmp3 = insertelement <16 x i8> %tmp2, i8 %A, i32 262 %tmp4 = insertelement <16 x i8> %tmp3, i8 %A, i32 363 %tmp5 = insertelement <16 x i8> %tmp4, i8 %A, i32 464 %tmp6 = insertelement <16 x i8> %tmp5, i8 %A, i32 565 %tmp7 = insertelement <16 x i8> %tmp6, i8 %A, i32 666 %tmp8 = insertelement <16 x i8> %tmp7, i8 %A, i32 767 %tmp9 = insertelement <16 x i8> %tmp8, i8 %A, i32 868 %tmp10 = insertelement <16 x i8> %tmp9, i8 %A, i32 969 %tmp11 = insertelement <16 x i8> %tmp10, i8 %A, i32 1070 %tmp12 = insertelement <16 x i8> %tmp11, i8 %A, i32 1171 %tmp13 = insertelement <16 x i8> %tmp12, i8 %A, i32 1272 %tmp14 = insertelement <16 x i8> %tmp13, i8 %A, i32 1373 %tmp15 = insertelement <16 x i8> %tmp14, i8 %A, i32 1474 %tmp16 = insertelement <16 x i8> %tmp15, i8 %A, i32 1575 ret <16 x i8> %tmp1676}77 78define <8 x i16> @v_dupQ16(i16 %A) nounwind {79; CHECK-LABEL: v_dupQ16:80; CHECK: // %bb.0:81; CHECK-NEXT: dup.8h v0, w082; CHECK-NEXT: ret83 %tmp1 = insertelement <8 x i16> zeroinitializer, i16 %A, i32 084 %tmp2 = insertelement <8 x i16> %tmp1, i16 %A, i32 185 %tmp3 = insertelement <8 x i16> %tmp2, i16 %A, i32 286 %tmp4 = insertelement <8 x i16> %tmp3, i16 %A, i32 387 %tmp5 = insertelement <8 x i16> %tmp4, i16 %A, i32 488 %tmp6 = insertelement <8 x i16> %tmp5, i16 %A, i32 589 %tmp7 = insertelement <8 x i16> %tmp6, i16 %A, i32 690 %tmp8 = insertelement <8 x i16> %tmp7, i16 %A, i32 791 ret <8 x i16> %tmp892}93 94define <4 x i32> @v_dupQ32(i32 %A) nounwind {95; CHECK-LABEL: v_dupQ32:96; CHECK: // %bb.0:97; CHECK-NEXT: dup.4s v0, w098; CHECK-NEXT: ret99 %tmp1 = insertelement <4 x i32> zeroinitializer, i32 %A, i32 0100 %tmp2 = insertelement <4 x i32> %tmp1, i32 %A, i32 1101 %tmp3 = insertelement <4 x i32> %tmp2, i32 %A, i32 2102 %tmp4 = insertelement <4 x i32> %tmp3, i32 %A, i32 3103 ret <4 x i32> %tmp4104}105 106define <4 x i16> @v_dup16_const(i16 %y, ptr %p) {107; CHECK-LABEL: v_dup16_const:108; CHECK: // %bb.0:109; CHECK-NEXT: movi.4h v0, #10110; CHECK-NEXT: mov w8, #10 // =0xa111; CHECK-NEXT: strh w8, [x1]112; CHECK-NEXT: ret113 %i = insertelement <4 x i16> undef, i16 10, i32 0114 %lo = shufflevector <4 x i16> %i, <4 x i16> undef, <4 x i32> zeroinitializer115 store i16 10, ptr %p116 ret <4 x i16> %lo117}118 119define <4 x float> @v_dupQfloat(float %A) nounwind {120; CHECK-LABEL: v_dupQfloat:121; CHECK: // %bb.0:122; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0123; CHECK-NEXT: dup.4s v0, v0[0]124; CHECK-NEXT: ret125 %tmp1 = insertelement <4 x float> zeroinitializer, float %A, i32 0126 %tmp2 = insertelement <4 x float> %tmp1, float %A, i32 1127 %tmp3 = insertelement <4 x float> %tmp2, float %A, i32 2128 %tmp4 = insertelement <4 x float> %tmp3, float %A, i32 3129 ret <4 x float> %tmp4130}131 132; Check to make sure it works with shuffles, too.133 134define <8 x i8> @v_shuffledup8(i8 %A) nounwind {135; CHECK-LABEL: v_shuffledup8:136; CHECK: // %bb.0:137; CHECK-NEXT: dup.8b v0, w0138; CHECK-NEXT: ret139 %tmp1 = insertelement <8 x i8> undef, i8 %A, i32 0140 %tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> zeroinitializer141 ret <8 x i8> %tmp2142}143 144define <4 x i16> @v_shuffledup16(i16 %A) nounwind {145; CHECK-LABEL: v_shuffledup16:146; CHECK: // %bb.0:147; CHECK-NEXT: dup.4h v0, w0148; CHECK-NEXT: ret149 %tmp1 = insertelement <4 x i16> undef, i16 %A, i32 0150 %tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> zeroinitializer151 ret <4 x i16> %tmp2152}153 154define <2 x i32> @v_shuffledup32(i32 %A) nounwind {155; CHECK-LABEL: v_shuffledup32:156; CHECK: // %bb.0:157; CHECK-NEXT: dup.2s v0, w0158; CHECK-NEXT: ret159 %tmp1 = insertelement <2 x i32> undef, i32 %A, i32 0160 %tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <2 x i32> zeroinitializer161 ret <2 x i32> %tmp2162}163 164define <2 x float> @v_shuffledupfloat(float %A) nounwind {165; CHECK-LABEL: v_shuffledupfloat:166; CHECK: // %bb.0:167; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0168; CHECK-NEXT: dup.2s v0, v0[0]169; CHECK-NEXT: ret170 %tmp1 = insertelement <2 x float> undef, float %A, i32 0171 %tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <2 x i32> zeroinitializer172 ret <2 x float> %tmp2173}174 175define <16 x i8> @v_shuffledupQ8(i8 %A) nounwind {176; CHECK-LABEL: v_shuffledupQ8:177; CHECK: // %bb.0:178; CHECK-NEXT: dup.16b v0, w0179; CHECK-NEXT: ret180 %tmp1 = insertelement <16 x i8> undef, i8 %A, i32 0181 %tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> zeroinitializer182 ret <16 x i8> %tmp2183}184 185define <8 x i16> @v_shuffledupQ16(i16 %A) nounwind {186; CHECK-LABEL: v_shuffledupQ16:187; CHECK: // %bb.0:188; CHECK-NEXT: dup.8h v0, w0189; CHECK-NEXT: ret190 %tmp1 = insertelement <8 x i16> undef, i16 %A, i32 0191 %tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> zeroinitializer192 ret <8 x i16> %tmp2193}194 195define <4 x i32> @v_shuffledupQ32(i32 %A) nounwind {196; CHECK-LABEL: v_shuffledupQ32:197; CHECK: // %bb.0:198; CHECK-NEXT: dup.4s v0, w0199; CHECK-NEXT: ret200 %tmp1 = insertelement <4 x i32> undef, i32 %A, i32 0201 %tmp2 = shufflevector <4 x i32> %tmp1, <4 x i32> undef, <4 x i32> zeroinitializer202 ret <4 x i32> %tmp2203}204 205define <4 x float> @v_shuffledupQfloat(float %A) nounwind {206; CHECK-LABEL: v_shuffledupQfloat:207; CHECK: // %bb.0:208; CHECK-NEXT: // kill: def $s0 killed $s0 def $q0209; CHECK-NEXT: dup.4s v0, v0[0]210; CHECK-NEXT: ret211 %tmp1 = insertelement <4 x float> undef, float %A, i32 0212 %tmp2 = shufflevector <4 x float> %tmp1, <4 x float> undef, <4 x i32> zeroinitializer213 ret <4 x float> %tmp2214}215 216define <8 x i8> @vduplane8(<8 x i8> %A) nounwind {217; CHECK-LABEL: vduplane8:218; CHECK: // %bb.0:219; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0220; CHECK-NEXT: dup.8b v0, v0[1]221; CHECK-NEXT: ret222 %tmp2 = shufflevector <8 x i8> %A, <8 x i8> undef, <8 x i32> < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >223 ret <8 x i8> %tmp2224}225 226define <4 x i16> @vduplane16(<4 x i16> %A) nounwind {227; CHECK-LABEL: vduplane16:228; CHECK: // %bb.0:229; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0230; CHECK-NEXT: dup.4h v0, v0[1]231; CHECK-NEXT: ret232 %tmp2 = shufflevector <4 x i16> %A, <4 x i16> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >233 ret <4 x i16> %tmp2234}235 236define <2 x i32> @vduplane32(<2 x i32> %A) nounwind {237; CHECK-LABEL: vduplane32:238; CHECK: // %bb.0:239; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0240; CHECK-NEXT: dup.2s v0, v0[1]241; CHECK-NEXT: ret242 %tmp2 = shufflevector <2 x i32> %A, <2 x i32> undef, <2 x i32> < i32 1, i32 1 >243 ret <2 x i32> %tmp2244}245 246define <2 x float> @vduplanefloat(<2 x float> %A) nounwind {247; CHECK-LABEL: vduplanefloat:248; CHECK: // %bb.0:249; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0250; CHECK-NEXT: dup.2s v0, v0[1]251; CHECK-NEXT: ret252 %tmp2 = shufflevector <2 x float> %A, <2 x float> undef, <2 x i32> < i32 1, i32 1 >253 ret <2 x float> %tmp2254}255 256define <16 x i8> @vduplaneQ8(<8 x i8> %A) nounwind {257; CHECK-LABEL: vduplaneQ8:258; CHECK: // %bb.0:259; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0260; CHECK-NEXT: dup.16b v0, v0[1]261; CHECK-NEXT: ret262 %tmp2 = shufflevector <8 x i8> %A, <8 x i8> undef, <16 x i32> < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >263 ret <16 x i8> %tmp2264}265 266define <8 x i16> @vduplaneQ16(<4 x i16> %A) nounwind {267; CHECK-LABEL: vduplaneQ16:268; CHECK: // %bb.0:269; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0270; CHECK-NEXT: dup.8h v0, v0[1]271; CHECK-NEXT: ret272 %tmp2 = shufflevector <4 x i16> %A, <4 x i16> undef, <8 x i32> < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >273 ret <8 x i16> %tmp2274}275 276define <4 x i32> @vduplaneQ32(<2 x i32> %A) nounwind {277; CHECK-LABEL: vduplaneQ32:278; CHECK: // %bb.0:279; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0280; CHECK-NEXT: dup.4s v0, v0[1]281; CHECK-NEXT: ret282 %tmp2 = shufflevector <2 x i32> %A, <2 x i32> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >283 ret <4 x i32> %tmp2284}285 286define <4 x float> @vduplaneQfloat(<2 x float> %A) nounwind {287; CHECK-LABEL: vduplaneQfloat:288; CHECK: // %bb.0:289; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0290; CHECK-NEXT: dup.4s v0, v0[1]291; CHECK-NEXT: ret292 %tmp2 = shufflevector <2 x float> %A, <2 x float> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >293 ret <4 x float> %tmp2294}295 296define <2 x i64> @foo(<2 x i64> %arg0_int64x1_t) nounwind readnone {297; CHECK-LABEL: foo:298; CHECK: // %bb.0: // %entry299; CHECK-NEXT: dup.2d v0, v0[1]300; CHECK-NEXT: ret301entry:302 %0 = shufflevector <2 x i64> %arg0_int64x1_t, <2 x i64> undef, <2 x i32> <i32 1, i32 1>303 ret <2 x i64> %0304}305 306define <2 x i64> @bar(<2 x i64> %arg0_int64x1_t) nounwind readnone {307; CHECK-LABEL: bar:308; CHECK: // %bb.0: // %entry309; CHECK-NEXT: dup.2d v0, v0[0]310; CHECK-NEXT: ret311entry:312 %0 = shufflevector <2 x i64> %arg0_int64x1_t, <2 x i64> undef, <2 x i32> <i32 0, i32 0>313 ret <2 x i64> %0314}315 316define <2 x double> @baz(<2 x double> %arg0_int64x1_t) nounwind readnone {317; CHECK-LABEL: baz:318; CHECK: // %bb.0: // %entry319; CHECK-NEXT: dup.2d v0, v0[1]320; CHECK-NEXT: ret321entry:322 %0 = shufflevector <2 x double> %arg0_int64x1_t, <2 x double> undef, <2 x i32> <i32 1, i32 1>323 ret <2 x double> %0324}325 326define <2 x double> @qux(<2 x double> %arg0_int64x1_t) nounwind readnone {327; CHECK-LABEL: qux:328; CHECK: // %bb.0: // %entry329; CHECK-NEXT: dup.2d v0, v0[0]330; CHECK-NEXT: ret331entry:332 %0 = shufflevector <2 x double> %arg0_int64x1_t, <2 x double> undef, <2 x i32> <i32 0, i32 0>333 ret <2 x double> %0334}335 336define <2 x i32> @f(i32 %a, i32 %b) nounwind readnone {337; CHECK-LABEL: f:338; CHECK: // %bb.0:339; CHECK-NEXT: fmov s0, w0340; CHECK-NEXT: mov.s v0[1], w1341; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0342; CHECK-NEXT: ret343 %vecinit = insertelement <2 x i32> undef, i32 %a, i32 0344 %vecinit1 = insertelement <2 x i32> %vecinit, i32 %b, i32 1345 ret <2 x i32> %vecinit1346}347 348define <4 x i32> @g(i32 %a, i32 %b) nounwind readnone {349; CHECK-LABEL: g:350; CHECK: // %bb.0:351; CHECK-NEXT: fmov s0, w0352; CHECK-NEXT: mov.s v0[1], w1353; CHECK-NEXT: mov.s v0[2], w1354; CHECK-NEXT: mov.s v0[3], w0355; CHECK-NEXT: ret356 %vecinit = insertelement <4 x i32> undef, i32 %a, i32 0357 %vecinit1 = insertelement <4 x i32> %vecinit, i32 %b, i32 1358 %vecinit2 = insertelement <4 x i32> %vecinit1, i32 %b, i32 2359 %vecinit3 = insertelement <4 x i32> %vecinit2, i32 %a, i32 3360 ret <4 x i32> %vecinit3361}362 363define <2 x i64> @h(i64 %a, i64 %b) nounwind readnone {364; CHECK-LABEL: h:365; CHECK: // %bb.0:366; CHECK-NEXT: fmov d0, x0367; CHECK-NEXT: mov.d v0[1], x1368; CHECK-NEXT: ret369 %vecinit = insertelement <2 x i64> undef, i64 %a, i32 0370 %vecinit1 = insertelement <2 x i64> %vecinit, i64 %b, i32 1371 ret <2 x i64> %vecinit1372}373 374; We used to spot this as a BUILD_VECTOR implementable by dup, but assume that375; the single value needed was of the same type as the vector. This is false if376; the scalar corresponding to the vector type is illegal (e.g. a <4 x i16>377; BUILD_VECTOR will have an i32 as its source). In that case, the operation is378; not a simple "dup vD.4h, vN.h[idx]" after all, and we crashed.379;380; *However*, it is a dup vD.4h, vN.h[2*idx].381define <4 x i16> @test_build_illegal(<4 x i32> %in) {382; CHECK-SD-LABEL: test_build_illegal:383; CHECK-SD: // %bb.0:384; CHECK-SD-NEXT: dup.4h v0, v0[6]385; CHECK-SD-NEXT: ret386;387; CHECK-GI-LABEL: test_build_illegal:388; CHECK-GI: // %bb.0:389; CHECK-GI-NEXT: mov.s w8, v0[3]390; CHECK-GI-NEXT: mov.h v0[3], w8391; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0392; CHECK-GI-NEXT: ret393 %val = extractelement <4 x i32> %in, i32 3394 %smallval = trunc i32 %val to i16395 %vec = insertelement <4x i16> undef, i16 %smallval, i32 3396 397 ret <4 x i16> %vec398}399 400; We used to inherit an already extract_subvectored v4i16 from401; SelectionDAGBuilder here. We then added a DUPLANE on top of that, preventing402; the formation of an indexed-by-7 MLS.403define <4 x i16> @test_high_splat(<4 x i16> %a, <4 x i16> %b, <8 x i16> %v) #0 {404; CHECK-LABEL: test_high_splat:405; CHECK: // %bb.0: // %entry406; CHECK-NEXT: mls.4h v0, v1, v2[7]407; CHECK-NEXT: ret408entry:409 %shuffle = shufflevector <8 x i16> %v, <8 x i16> undef, <4 x i32> <i32 7, i32 7, i32 7, i32 7>410 %mul = mul <4 x i16> %shuffle, %b411 %sub = sub <4 x i16> %a, %mul412 ret <4 x i16> %sub413}414 415; Also test the DUP path in the PerfectShuffle generator.416 417define <4 x i16> @test_perfectshuffle_dupext_v4i16(<4 x i16> %a, <4 x i16> %b) nounwind {418; CHECK-SD-LABEL: test_perfectshuffle_dupext_v4i16:419; CHECK-SD: // %bb.0:420; CHECK-SD-NEXT: trn1.4h v0, v0, v0421; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1422; CHECK-SD-NEXT: mov.s v0[1], v1[0]423; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0424; CHECK-SD-NEXT: ret425;426; CHECK-GI-LABEL: test_perfectshuffle_dupext_v4i16:427; CHECK-GI: // %bb.0:428; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0429; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1430; CHECK-GI-NEXT: adrp x8, .LCPI34_0431; CHECK-GI-NEXT: mov.d v0[1], v1[0]432; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI34_0]433; CHECK-GI-NEXT: tbl.16b v0, { v0 }, v1434; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0435; CHECK-GI-NEXT: ret436 %r = shufflevector <4 x i16> %a, <4 x i16> %b, <4 x i32> <i32 0, i32 0, i32 4, i32 5>437 ret <4 x i16> %r438}439 440define <4 x half> @test_perfectshuffle_dupext_v4f16(<4 x half> %a, <4 x half> %b) nounwind {441; CHECK-SD-LABEL: test_perfectshuffle_dupext_v4f16:442; CHECK-SD: // %bb.0:443; CHECK-SD-NEXT: trn1.4h v0, v0, v0444; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1445; CHECK-SD-NEXT: mov.s v0[1], v1[0]446; CHECK-SD-NEXT: // kill: def $d0 killed $d0 killed $q0447; CHECK-SD-NEXT: ret448;449; CHECK-GI-LABEL: test_perfectshuffle_dupext_v4f16:450; CHECK-GI: // %bb.0:451; CHECK-GI-NEXT: // kill: def $d0 killed $d0 def $q0452; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1453; CHECK-GI-NEXT: adrp x8, .LCPI35_0454; CHECK-GI-NEXT: mov.d v0[1], v1[0]455; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI35_0]456; CHECK-GI-NEXT: tbl.16b v0, { v0 }, v1457; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0458; CHECK-GI-NEXT: ret459 %r = shufflevector <4 x half> %a, <4 x half> %b, <4 x i32> <i32 0, i32 0, i32 4, i32 5>460 ret <4 x half> %r461}462 463define <4 x i32> @test_perfectshuffle_dupext_v4i32(<4 x i32> %a, <4 x i32> %b) nounwind {464; CHECK-SD-LABEL: test_perfectshuffle_dupext_v4i32:465; CHECK-SD: // %bb.0:466; CHECK-SD-NEXT: trn1.4s v0, v0, v0467; CHECK-SD-NEXT: mov.d v0[1], v1[0]468; CHECK-SD-NEXT: ret469;470; CHECK-GI-LABEL: test_perfectshuffle_dupext_v4i32:471; CHECK-GI: // %bb.0:472; CHECK-GI-NEXT: adrp x8, .LCPI36_0473; CHECK-GI-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1474; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI36_0]475; CHECK-GI-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1476; CHECK-GI-NEXT: tbl.16b v0, { v0, v1 }, v2477; CHECK-GI-NEXT: ret478 %r = shufflevector <4 x i32> %a, <4 x i32> %b, <4 x i32> <i32 0, i32 0, i32 4, i32 5>479 ret <4 x i32> %r480}481 482define <4 x float> @test_perfectshuffle_dupext_v4f32(<4 x float> %a, <4 x float> %b) nounwind {483; CHECK-SD-LABEL: test_perfectshuffle_dupext_v4f32:484; CHECK-SD: // %bb.0:485; CHECK-SD-NEXT: trn1.4s v0, v0, v0486; CHECK-SD-NEXT: mov.d v0[1], v1[0]487; CHECK-SD-NEXT: ret488;489; CHECK-GI-LABEL: test_perfectshuffle_dupext_v4f32:490; CHECK-GI: // %bb.0:491; CHECK-GI-NEXT: adrp x8, .LCPI37_0492; CHECK-GI-NEXT: // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1493; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI37_0]494; CHECK-GI-NEXT: // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1495; CHECK-GI-NEXT: tbl.16b v0, { v0, v1 }, v2496; CHECK-GI-NEXT: ret497 %r = shufflevector <4 x float> %a, <4 x float> %b, <4 x i32> <i32 0, i32 0, i32 4, i32 5>498 ret <4 x float> %r499}500 501define void @disguised_dup(<4 x float> %x, ptr %p1, ptr %p2) {502; CHECK-SD-LABEL: disguised_dup:503; CHECK-SD: // %bb.0:504; CHECK-SD-NEXT: ext.16b v1, v0, v0, #4505; CHECK-SD-NEXT: mov.s v1[2], v0[0]506; CHECK-SD-NEXT: dup.4s v0, v0[0]507; CHECK-SD-NEXT: str q1, [x0]508; CHECK-SD-NEXT: str q0, [x1]509; CHECK-SD-NEXT: ret510;511; CHECK-GI-LABEL: disguised_dup:512; CHECK-GI: // %bb.0:513; CHECK-GI-NEXT: adrp x8, .LCPI38_1514; CHECK-GI-NEXT: // kill: def $q0 killed $q0 def $q0_q1515; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI38_1]516; CHECK-GI-NEXT: adrp x8, .LCPI38_0517; CHECK-GI-NEXT: tbl.16b v0, { v0, v1 }, v2518; CHECK-GI-NEXT: ldr q2, [x8, :lo12:.LCPI38_0]519; CHECK-GI-NEXT: tbl.16b v2, { v0, v1 }, v2520; CHECK-GI-NEXT: str q0, [x0]521; CHECK-GI-NEXT: str q2, [x1]522; CHECK-GI-NEXT: ret523 %shuf = shufflevector <4 x float> %x, <4 x float> undef, <4 x i32> <i32 1, i32 2, i32 0, i32 0>524 %dup = shufflevector <4 x float> %shuf, <4 x float> undef, <4 x i32> <i32 3, i32 2, i32 2, i32 3>525 store <4 x float> %shuf, ptr %p1, align 8526 store <4 x float> %dup, ptr %p2, align 8527 ret void528}529 530define <2 x i32> @dup_const2(<2 x i32> %A) nounwind {531; CHECK-SD-LABEL: dup_const2:532; CHECK-SD: // %bb.0:533; CHECK-SD-NEXT: mov w8, #32770 // =0x8002534; CHECK-SD-NEXT: movk w8, #128, lsl #16535; CHECK-SD-NEXT: dup.2s v1, w8536; CHECK-SD-NEXT: add.2s v0, v0, v1537; CHECK-SD-NEXT: ret538;539; CHECK-GI-LABEL: dup_const2:540; CHECK-GI: // %bb.0:541; CHECK-GI-NEXT: adrp x8, .LCPI39_0542; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI39_0]543; CHECK-GI-NEXT: add.2s v0, v0, v1544; CHECK-GI-NEXT: ret545 %tmp2 = add <2 x i32> %A, <i32 8421378, i32 8421378>546 ret <2 x i32> %tmp2547}548 549define <2 x i32> @dup_const4_ext(<4 x i32> %A) nounwind {550; CHECK-SD-LABEL: dup_const4_ext:551; CHECK-SD: // %bb.0:552; CHECK-SD-NEXT: mov w8, #32769 // =0x8001553; CHECK-SD-NEXT: movk w8, #128, lsl #16554; CHECK-SD-NEXT: dup.2s v1, w8555; CHECK-SD-NEXT: add.2s v0, v0, v1556; CHECK-SD-NEXT: ret557;558; CHECK-GI-LABEL: dup_const4_ext:559; CHECK-GI: // %bb.0:560; CHECK-GI-NEXT: adrp x8, .LCPI40_0561; CHECK-GI-NEXT: ldr q1, [x8, :lo12:.LCPI40_0]562; CHECK-GI-NEXT: add.4s v0, v0, v1563; CHECK-GI-NEXT: // kill: def $d0 killed $d0 killed $q0564; CHECK-GI-NEXT: ret565 %tmp1 = add <4 x i32> %A, <i32 8421377, i32 8421377, i32 8421377, i32 8421377>566 %tmp2 = shufflevector <4 x i32> %tmp1, <4 x i32> undef, <2 x i32> <i32 0, i32 1>567 ret <2 x i32> %tmp2568}569 570define <4 x i32> @dup_const24(<2 x i32> %A, <2 x i32> %B, <4 x i32> %C) nounwind {571; CHECK-SD-LABEL: dup_const24:572; CHECK-SD: // %bb.0:573; CHECK-SD-NEXT: mov w8, #32768 // =0x8000574; CHECK-SD-NEXT: // kill: def $d1 killed $d1 def $q1575; CHECK-SD-NEXT: movk w8, #128, lsl #16576; CHECK-SD-NEXT: dup.4s v3, w8577; CHECK-SD-NEXT: add.2s v0, v0, v3578; CHECK-SD-NEXT: mov.d v0[1], v1[0]579; CHECK-SD-NEXT: add.4s v1, v2, v3580; CHECK-SD-NEXT: eor.16b v0, v1, v0581; CHECK-SD-NEXT: ret582;583; CHECK-GI-LABEL: dup_const24:584; CHECK-GI: // %bb.0:585; CHECK-GI-NEXT: adrp x8, .LCPI41_1586; CHECK-GI-NEXT: // kill: def $d1 killed $d1 def $q1587; CHECK-GI-NEXT: ldr d3, [x8, :lo12:.LCPI41_1]588; CHECK-GI-NEXT: adrp x8, .LCPI41_0589; CHECK-GI-NEXT: add.2s v0, v0, v3590; CHECK-GI-NEXT: ldr q3, [x8, :lo12:.LCPI41_0]591; CHECK-GI-NEXT: mov.d v0[1], v1[0]592; CHECK-GI-NEXT: add.4s v1, v2, v3593; CHECK-GI-NEXT: eor.16b v0, v1, v0594; CHECK-GI-NEXT: ret595 %tmp1 = add <2 x i32> %A, <i32 8421376, i32 8421376>596 %tmp4 = shufflevector <2 x i32> %tmp1, <2 x i32> %B, <4 x i32> <i32 0, i32 1, i32 2, i32 3>597 %tmp3 = add <4 x i32> %C, <i32 8421376, i32 8421376, i32 8421376, i32 8421376>598 %tmp5 = xor <4 x i32> %tmp3, %tmp4599 ret <4 x i32> %tmp5600}601 602define <8 x i16> @bitcast_i64_v8i16(i64 %a) {603; CHECK-SD-LABEL: bitcast_i64_v8i16:604; CHECK-SD: // %bb.0:605; CHECK-SD-NEXT: dup.8h v0, w0606; CHECK-SD-NEXT: ret607;608; CHECK-GI-LABEL: bitcast_i64_v8i16:609; CHECK-GI: // %bb.0:610; CHECK-GI-NEXT: fmov d0, x0611; CHECK-GI-NEXT: dup.8h v0, v0[0]612; CHECK-GI-NEXT: ret613 %b = bitcast i64 %a to <4 x i16>614 %r = shufflevector <4 x i16> %b, <4 x i16> poison, <8 x i32> zeroinitializer615 ret <8 x i16> %r616}617 618define <8 x i16> @bitcast_i64_v8i16_lane1(i64 %a) {619; CHECK-LABEL: bitcast_i64_v8i16_lane1:620; CHECK: // %bb.0:621; CHECK-NEXT: fmov d0, x0622; CHECK-NEXT: dup.8h v0, v0[1]623; CHECK-NEXT: ret624 %b = bitcast i64 %a to <4 x i16>625 %r = shufflevector <4 x i16> %b, <4 x i16> poison, <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>626 ret <8 x i16> %r627}628 629define <8 x i16> @bitcast_f64_v8i16(double %a) {630; CHECK-LABEL: bitcast_f64_v8i16:631; CHECK: // %bb.0:632; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0633; CHECK-NEXT: dup.8h v0, v0[0]634; CHECK-NEXT: ret635 %b = bitcast double %a to <4 x i16>636 %r = shufflevector <4 x i16> %b, <4 x i16> poison, <8 x i32> zeroinitializer637 ret <8 x i16> %r638}639 640define <8 x half> @bitcast_i64_v8f16(i64 %a) {641; CHECK-LABEL: bitcast_i64_v8f16:642; CHECK: // %bb.0:643; CHECK-NEXT: fmov d0, x0644; CHECK-NEXT: dup.8h v0, v0[0]645; CHECK-NEXT: ret646 %b = bitcast i64 %a to <4 x half>647 %r = shufflevector <4 x half> %b, <4 x half> poison, <8 x i32> zeroinitializer648 ret <8 x half> %r649}650 651define <2 x i64> @bitcast_i64_v2f64(i64 %a) {652; CHECK-SD-LABEL: bitcast_i64_v2f64:653; CHECK-SD: // %bb.0:654; CHECK-SD-NEXT: fmov d0, x0655; CHECK-SD-NEXT: dup.2d v0, v0[0]656; CHECK-SD-NEXT: ret657;658; CHECK-GI-LABEL: bitcast_i64_v2f64:659; CHECK-GI: // %bb.0:660; CHECK-GI-NEXT: dup.2d v0, x0661; CHECK-GI-NEXT: ret662 %b = bitcast i64 %a to <1 x i64>663 %r = shufflevector <1 x i64> %b, <1 x i64> poison, <2 x i32> zeroinitializer664 ret <2 x i64> %r665}666 667define <2 x i64> @bitcast_v2f64_v2i64(<2 x double> %a) {668; CHECK-LABEL: bitcast_v2f64_v2i64:669; CHECK: // %bb.0:670; CHECK-NEXT: dup.2d v0, v0[0]671; CHECK-NEXT: ret672 %b = bitcast <2 x double> %a to <2 x i64>673 %r = shufflevector <2 x i64> %b, <2 x i64> poison, <2 x i32> zeroinitializer674 ret <2 x i64> %r675}676 677define <2 x i64> @bitcast_v8i16_v2i64(<8 x i16> %a) {678; CHECK-LABEL: bitcast_v8i16_v2i64:679; CHECK: // %bb.0:680; CHECK-NEXT: dup.2d v0, v0[0]681; CHECK-NEXT: ret682 %b = bitcast <8 x i16> %a to <2 x i64>683 %r = shufflevector <2 x i64> %b, <2 x i64> poison, <2 x i32> zeroinitializer684 ret <2 x i64> %r685}686 687define <8 x i16> @bitcast_v2f64_v8i16(<2 x i64> %a) {688; CHECK-LABEL: bitcast_v2f64_v8i16:689; CHECK: // %bb.0:690; CHECK-NEXT: dup.8h v0, v0[0]691; CHECK-NEXT: ret692 %b = bitcast <2 x i64> %a to <8 x i16>693 %r = shufflevector <8 x i16> %b, <8 x i16> poison, <8 x i32> zeroinitializer694 ret <8 x i16> %r695}696 697define <4 x i16> @dup_i16_v4i16_constant() {698; CHECK-SD-LABEL: dup_i16_v4i16_constant:699; CHECK-SD: // %bb.0:700; CHECK-SD-NEXT: mov w8, #9211 // =0x23fb701; CHECK-SD-NEXT: dup.4h v0, w8702; CHECK-SD-NEXT: ret703;704; CHECK-GI-LABEL: dup_i16_v4i16_constant:705; CHECK-GI: // %bb.0:706; CHECK-GI-NEXT: adrp x8, .LCPI50_0707; CHECK-GI-NEXT: ldr d0, [x8, :lo12:.LCPI50_0]708; CHECK-GI-NEXT: ret709 ret <4 x i16> <i16 9211, i16 9211, i16 9211, i16 9211>710}711