Home | History | Annotate | Download | only in ARM
      1 ; RUN: llc < %s -march=arm -mattr=+neon | FileCheck %s
      2 
      3 define <8 x i8> @v_dup8(i8 %A) nounwind {
      4 ;CHECK-LABEL: v_dup8:
      5 ;CHECK: vdup.8
      6 	%tmp1 = insertelement <8 x i8> zeroinitializer, i8 %A, i32 0
      7 	%tmp2 = insertelement <8 x i8> %tmp1, i8 %A, i32 1
      8 	%tmp3 = insertelement <8 x i8> %tmp2, i8 %A, i32 2
      9 	%tmp4 = insertelement <8 x i8> %tmp3, i8 %A, i32 3
     10 	%tmp5 = insertelement <8 x i8> %tmp4, i8 %A, i32 4
     11 	%tmp6 = insertelement <8 x i8> %tmp5, i8 %A, i32 5
     12 	%tmp7 = insertelement <8 x i8> %tmp6, i8 %A, i32 6
     13 	%tmp8 = insertelement <8 x i8> %tmp7, i8 %A, i32 7
     14 	ret <8 x i8> %tmp8
     15 }
     16 
     17 define <4 x i16> @v_dup16(i16 %A) nounwind {
     18 ;CHECK-LABEL: v_dup16:
     19 ;CHECK: vdup.16
     20 	%tmp1 = insertelement <4 x i16> zeroinitializer, i16 %A, i32 0
     21 	%tmp2 = insertelement <4 x i16> %tmp1, i16 %A, i32 1
     22 	%tmp3 = insertelement <4 x i16> %tmp2, i16 %A, i32 2
     23 	%tmp4 = insertelement <4 x i16> %tmp3, i16 %A, i32 3
     24 	ret <4 x i16> %tmp4
     25 }
     26 
     27 define <2 x i32> @v_dup32(i32 %A) nounwind {
     28 ;CHECK-LABEL: v_dup32:
     29 ;CHECK: vdup.32
     30 	%tmp1 = insertelement <2 x i32> zeroinitializer, i32 %A, i32 0
     31 	%tmp2 = insertelement <2 x i32> %tmp1, i32 %A, i32 1
     32 	ret <2 x i32> %tmp2
     33 }
     34 
     35 define <2 x float> @v_dupfloat(float %A) nounwind {
     36 ;CHECK-LABEL: v_dupfloat:
     37 ;CHECK: vdup.32
     38 	%tmp1 = insertelement <2 x float> zeroinitializer, float %A, i32 0
     39 	%tmp2 = insertelement <2 x float> %tmp1, float %A, i32 1
     40 	ret <2 x float> %tmp2
     41 }
     42 
     43 define <16 x i8> @v_dupQ8(i8 %A) nounwind {
     44 ;CHECK-LABEL: v_dupQ8:
     45 ;CHECK: vdup.8
     46 	%tmp1 = insertelement <16 x i8> zeroinitializer, i8 %A, i32 0
     47 	%tmp2 = insertelement <16 x i8> %tmp1, i8 %A, i32 1
     48 	%tmp3 = insertelement <16 x i8> %tmp2, i8 %A, i32 2
     49 	%tmp4 = insertelement <16 x i8> %tmp3, i8 %A, i32 3
     50 	%tmp5 = insertelement <16 x i8> %tmp4, i8 %A, i32 4
     51 	%tmp6 = insertelement <16 x i8> %tmp5, i8 %A, i32 5
     52 	%tmp7 = insertelement <16 x i8> %tmp6, i8 %A, i32 6
     53 	%tmp8 = insertelement <16 x i8> %tmp7, i8 %A, i32 7
     54 	%tmp9 = insertelement <16 x i8> %tmp8, i8 %A, i32 8
     55 	%tmp10 = insertelement <16 x i8> %tmp9, i8 %A, i32 9
     56 	%tmp11 = insertelement <16 x i8> %tmp10, i8 %A, i32 10
     57 	%tmp12 = insertelement <16 x i8> %tmp11, i8 %A, i32 11
     58 	%tmp13 = insertelement <16 x i8> %tmp12, i8 %A, i32 12
     59 	%tmp14 = insertelement <16 x i8> %tmp13, i8 %A, i32 13
     60 	%tmp15 = insertelement <16 x i8> %tmp14, i8 %A, i32 14
     61 	%tmp16 = insertelement <16 x i8> %tmp15, i8 %A, i32 15
     62 	ret <16 x i8> %tmp16
     63 }
     64 
     65 define <8 x i16> @v_dupQ16(i16 %A) nounwind {
     66 ;CHECK-LABEL: v_dupQ16:
     67 ;CHECK: vdup.16
     68 	%tmp1 = insertelement <8 x i16> zeroinitializer, i16 %A, i32 0
     69 	%tmp2 = insertelement <8 x i16> %tmp1, i16 %A, i32 1
     70 	%tmp3 = insertelement <8 x i16> %tmp2, i16 %A, i32 2
     71 	%tmp4 = insertelement <8 x i16> %tmp3, i16 %A, i32 3
     72 	%tmp5 = insertelement <8 x i16> %tmp4, i16 %A, i32 4
     73 	%tmp6 = insertelement <8 x i16> %tmp5, i16 %A, i32 5
     74 	%tmp7 = insertelement <8 x i16> %tmp6, i16 %A, i32 6
     75 	%tmp8 = insertelement <8 x i16> %tmp7, i16 %A, i32 7
     76 	ret <8 x i16> %tmp8
     77 }
     78 
     79 define <4 x i32> @v_dupQ32(i32 %A) nounwind {
     80 ;CHECK-LABEL: v_dupQ32:
     81 ;CHECK: vdup.32
     82 	%tmp1 = insertelement <4 x i32> zeroinitializer, i32 %A, i32 0
     83 	%tmp2 = insertelement <4 x i32> %tmp1, i32 %A, i32 1
     84 	%tmp3 = insertelement <4 x i32> %tmp2, i32 %A, i32 2
     85 	%tmp4 = insertelement <4 x i32> %tmp3, i32 %A, i32 3
     86 	ret <4 x i32> %tmp4
     87 }
     88 
     89 define <4 x float> @v_dupQfloat(float %A) nounwind {
     90 ;CHECK-LABEL: v_dupQfloat:
     91 ;CHECK: vdup.32
     92 	%tmp1 = insertelement <4 x float> zeroinitializer, float %A, i32 0
     93 	%tmp2 = insertelement <4 x float> %tmp1, float %A, i32 1
     94 	%tmp3 = insertelement <4 x float> %tmp2, float %A, i32 2
     95 	%tmp4 = insertelement <4 x float> %tmp3, float %A, i32 3
     96 	ret <4 x float> %tmp4
     97 }
     98 
     99 ; Check to make sure it works with shuffles, too.
    100 
    101 define <8 x i8> @v_shuffledup8(i8 %A) nounwind {
    102 ;CHECK-LABEL: v_shuffledup8:
    103 ;CHECK: vdup.8
    104 	%tmp1 = insertelement <8 x i8> undef, i8 %A, i32 0
    105 	%tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> zeroinitializer
    106 	ret <8 x i8> %tmp2
    107 }
    108 
    109 define <4 x i16> @v_shuffledup16(i16 %A) nounwind {
    110 ;CHECK-LABEL: v_shuffledup16:
    111 ;CHECK: vdup.16
    112 	%tmp1 = insertelement <4 x i16> undef, i16 %A, i32 0
    113 	%tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> zeroinitializer
    114 	ret <4 x i16> %tmp2
    115 }
    116 
    117 define <2 x i32> @v_shuffledup32(i32 %A) nounwind {
    118 ;CHECK-LABEL: v_shuffledup32:
    119 ;CHECK: vdup.32
    120 	%tmp1 = insertelement <2 x i32> undef, i32 %A, i32 0
    121 	%tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <2 x i32> zeroinitializer
    122 	ret <2 x i32> %tmp2
    123 }
    124 
    125 define <2 x float> @v_shuffledupfloat(float %A) nounwind {
    126 ;CHECK-LABEL: v_shuffledupfloat:
    127 ;CHECK: vdup.32
    128 	%tmp1 = insertelement <2 x float> undef, float %A, i32 0
    129 	%tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <2 x i32> zeroinitializer
    130 	ret <2 x float> %tmp2
    131 }
    132 
    133 define <16 x i8> @v_shuffledupQ8(i8 %A) nounwind {
    134 ;CHECK-LABEL: v_shuffledupQ8:
    135 ;CHECK: vdup.8
    136 	%tmp1 = insertelement <16 x i8> undef, i8 %A, i32 0
    137 	%tmp2 = shufflevector <16 x i8> %tmp1, <16 x i8> undef, <16 x i32> zeroinitializer
    138 	ret <16 x i8> %tmp2
    139 }
    140 
    141 define <8 x i16> @v_shuffledupQ16(i16 %A) nounwind {
    142 ;CHECK-LABEL: v_shuffledupQ16:
    143 ;CHECK: vdup.16
    144 	%tmp1 = insertelement <8 x i16> undef, i16 %A, i32 0
    145 	%tmp2 = shufflevector <8 x i16> %tmp1, <8 x i16> undef, <8 x i32> zeroinitializer
    146 	ret <8 x i16> %tmp2
    147 }
    148 
    149 define <4 x i32> @v_shuffledupQ32(i32 %A) nounwind {
    150 ;CHECK-LABEL: v_shuffledupQ32:
    151 ;CHECK: vdup.32
    152 	%tmp1 = insertelement <4 x i32> undef, i32 %A, i32 0
    153 	%tmp2 = shufflevector <4 x i32> %tmp1, <4 x i32> undef, <4 x i32> zeroinitializer
    154 	ret <4 x i32> %tmp2
    155 }
    156 
    157 define <4 x float> @v_shuffledupQfloat(float %A) nounwind {
    158 ;CHECK-LABEL: v_shuffledupQfloat:
    159 ;CHECK: vdup.32
    160 	%tmp1 = insertelement <4 x float> undef, float %A, i32 0
    161 	%tmp2 = shufflevector <4 x float> %tmp1, <4 x float> undef, <4 x i32> zeroinitializer
    162 	ret <4 x float> %tmp2
    163 }
    164 
    165 define <8 x i8> @vduplane8(<8 x i8>* %A) nounwind {
    166 ;CHECK-LABEL: vduplane8:
    167 ;CHECK: vdup.8
    168 	%tmp1 = load <8 x i8>* %A
    169 	%tmp2 = shufflevector <8 x i8> %tmp1, <8 x i8> undef, <8 x i32> < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >
    170 	ret <8 x i8> %tmp2
    171 }
    172 
    173 define <4 x i16> @vduplane16(<4 x i16>* %A) nounwind {
    174 ;CHECK-LABEL: vduplane16:
    175 ;CHECK: vdup.16
    176 	%tmp1 = load <4 x i16>* %A
    177 	%tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >
    178 	ret <4 x i16> %tmp2
    179 }
    180 
    181 define <2 x i32> @vduplane32(<2 x i32>* %A) nounwind {
    182 ;CHECK-LABEL: vduplane32:
    183 ;CHECK: vdup.32
    184 	%tmp1 = load <2 x i32>* %A
    185 	%tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <2 x i32> < i32 1, i32 1 >
    186 	ret <2 x i32> %tmp2
    187 }
    188 
    189 define <2 x float> @vduplanefloat(<2 x float>* %A) nounwind {
    190 ;CHECK-LABEL: vduplanefloat:
    191 ;CHECK: vdup.32
    192 	%tmp1 = load <2 x float>* %A
    193 	%tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <2 x i32> < i32 1, i32 1 >
    194 	ret <2 x float> %tmp2
    195 }
    196 
    197 define <16 x i8> @vduplaneQ8(<8 x i8>* %A) nounwind {
    198 ;CHECK-LABEL: vduplaneQ8:
    199 ;CHECK: vdup.8
    200 	%tmp1 = load <8 x i8>* %A
    201 	%tmp2 = shufflevector <8 x i8> %tmp1, <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 >
    202 	ret <16 x i8> %tmp2
    203 }
    204 
    205 define <8 x i16> @vduplaneQ16(<4 x i16>* %A) nounwind {
    206 ;CHECK-LABEL: vduplaneQ16:
    207 ;CHECK: vdup.16
    208 	%tmp1 = load <4 x i16>* %A
    209 	%tmp2 = shufflevector <4 x i16> %tmp1, <4 x i16> undef, <8 x i32> < i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1 >
    210 	ret <8 x i16> %tmp2
    211 }
    212 
    213 define <4 x i32> @vduplaneQ32(<2 x i32>* %A) nounwind {
    214 ;CHECK-LABEL: vduplaneQ32:
    215 ;CHECK: vdup.32
    216 	%tmp1 = load <2 x i32>* %A
    217 	%tmp2 = shufflevector <2 x i32> %tmp1, <2 x i32> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >
    218 	ret <4 x i32> %tmp2
    219 }
    220 
    221 define <4 x float> @vduplaneQfloat(<2 x float>* %A) nounwind {
    222 ;CHECK-LABEL: vduplaneQfloat:
    223 ;CHECK: vdup.32
    224 	%tmp1 = load <2 x float>* %A
    225 	%tmp2 = shufflevector <2 x float> %tmp1, <2 x float> undef, <4 x i32> < i32 1, i32 1, i32 1, i32 1 >
    226 	ret <4 x float> %tmp2
    227 }
    228 
    229 define <2 x i64> @foo(<2 x i64> %arg0_int64x1_t) nounwind readnone {
    230 entry:
    231   %0 = shufflevector <2 x i64> %arg0_int64x1_t, <2 x i64> undef, <2 x i32> <i32 1, i32 1>
    232   ret <2 x i64> %0
    233 }
    234 
    235 define <2 x i64> @bar(<2 x i64> %arg0_int64x1_t) nounwind readnone {
    236 entry:
    237   %0 = shufflevector <2 x i64> %arg0_int64x1_t, <2 x i64> undef, <2 x i32> <i32 0, i32 0>
    238   ret <2 x i64> %0
    239 }
    240 
    241 define <2 x double> @baz(<2 x double> %arg0_int64x1_t) nounwind readnone {
    242 entry:
    243   %0 = shufflevector <2 x double> %arg0_int64x1_t, <2 x double> undef, <2 x i32> <i32 1, i32 1>
    244   ret <2 x double> %0
    245 }
    246 
    247 define <2 x double> @qux(<2 x double> %arg0_int64x1_t) nounwind readnone {
    248 entry:
    249   %0 = shufflevector <2 x double> %arg0_int64x1_t, <2 x double> undef, <2 x i32> <i32 0, i32 0>
    250   ret <2 x double> %0
    251 }
    252 
    253 ; Radar 7373643
    254 ;CHECK-LABEL: redundantVdup:
    255 ;CHECK: vmov.i8
    256 ;CHECK-NOT: vdup.8
    257 ;CHECK: vstr
    258 define void @redundantVdup(<8 x i8>* %ptr) nounwind {
    259   %1 = insertelement <8 x i8> undef, i8 -128, i32 0
    260   %2 = shufflevector <8 x i8> %1, <8 x i8> undef, <8 x i32> zeroinitializer
    261   store <8 x i8> %2, <8 x i8>* %ptr, align 8
    262   ret void
    263 }
    264 
    265 define <4 x i32> @tdupi(i32 %x, i32 %y) {
    266 ;CHECK-LABEL: tdupi:
    267 ;CHECK: vdup.32
    268   %1 = insertelement <4 x i32> undef, i32 %x, i32 0
    269   %2 = insertelement <4 x i32> %1, i32 %x, i32 1
    270   %3 = insertelement <4 x i32> %2, i32 %x, i32 2
    271   %4 = insertelement <4 x i32> %3, i32 %y, i32 3
    272   ret <4 x i32> %4
    273 }
    274 
    275 define <4 x float> @tdupf(float %x, float %y) {
    276 ;CHECK-LABEL: tdupf:
    277 ;CHECK: vdup.32
    278   %1 = insertelement <4 x float> undef, float %x, i32 0
    279   %2 = insertelement <4 x float> %1, float %x, i32 1
    280   %3 = insertelement <4 x float> %2, float %x, i32 2
    281   %4 = insertelement <4 x float> %3, float %y, i32 3
    282   ret <4 x float> %4
    283 }
    284 
    285 ; This test checks that when splatting an element from a vector into another,
    286 ; the value isn't moved out to GPRs first.
    287 define <4 x i32> @tduplane(<4 x i32> %invec) {
    288 ;CHECK-LABEL: tduplane:
    289 ;CHECK-NOT: vmov {{.*}}, d16[1]
    290 ;CHECK: vdup.32 {{.*}}, d16[1]
    291   %in = extractelement <4 x i32> %invec, i32 1
    292   %1 = insertelement <4 x i32> undef, i32 %in, i32 0
    293   %2 = insertelement <4 x i32> %1, i32 %in, i32 1
    294   %3 = insertelement <4 x i32> %2, i32 %in, i32 2
    295   %4 = insertelement <4 x i32> %3, i32 255, i32 3
    296   ret <4 x i32> %4
    297 }
    298 
    299 define <2 x float> @check_f32(<4 x float> %v) nounwind {
    300 ;CHECK-LABEL: check_f32:
    301 ;CHECK: vdup.32 {{.*}}, d{{..}}[1]
    302   %x = extractelement <4 x float> %v, i32 3
    303   %1 = insertelement  <2 x float> undef, float %x, i32 0
    304   %2 = insertelement  <2 x float> %1, float %x, i32 1
    305   ret <2 x float> %2
    306 }
    307 
    308 define <2 x i32> @check_i32(<4 x i32> %v) nounwind {
    309 ;CHECK-LABEL: check_i32:
    310 ;CHECK: vdup.32 {{.*}}, d{{..}}[1]
    311   %x = extractelement <4 x i32> %v, i32 3
    312   %1 = insertelement  <2 x i32> undef, i32 %x, i32 0
    313   %2 = insertelement  <2 x i32> %1, i32 %x, i32 1
    314   ret <2 x i32> %2
    315 }
    316 
    317 define <4 x i16> @check_i16(<8 x i16> %v) nounwind {
    318 ;CHECK-LABEL: check_i16:
    319 ;CHECK: vdup.16 {{.*}}, d{{..}}[3]
    320   %x = extractelement <8 x i16> %v, i32 3
    321   %1 = insertelement  <4 x i16> undef, i16 %x, i32 0
    322   %2 = insertelement  <4 x i16> %1, i16 %x, i32 1
    323   ret <4 x i16> %2
    324 }
    325 
    326 define <8 x i8> @check_i8(<16 x i8> %v) nounwind {
    327 ;CHECK-LABEL: check_i8:
    328 ;CHECK: vdup.8 {{.*}}, d{{..}}[3]
    329   %x = extractelement <16 x i8> %v, i32 3
    330   %1 = insertelement  <8  x i8> undef, i8 %x, i32 0
    331   %2 = insertelement  <8  x i8> %1, i8 %x, i32 1
    332   ret <8 x i8> %2
    333 }
    334