Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -o - %s | FileCheck %s
      2 
      3 ; This file contains tests for the AArch64 load/store optimizer.
      4 
      5 %padding = type { i8*, i8*, i8*, i8* }
      6 %s.byte = type { i8, i8 }
      7 %s.halfword = type { i16, i16 }
      8 %s.word = type { i32, i32 }
      9 %s.doubleword = type { i64, i32 }
     10 %s.quadword = type { fp128, i32 }
     11 %s.float = type { float, i32 }
     12 %s.double = type { double, i32 }
     13 %struct.byte = type { %padding, %s.byte }
     14 %struct.halfword = type { %padding, %s.halfword }
     15 %struct.word = type { %padding, %s.word }
     16 %struct.doubleword = type { %padding, %s.doubleword }
     17 %struct.quadword = type { %padding, %s.quadword }
     18 %struct.float = type { %padding, %s.float }
     19 %struct.double = type { %padding, %s.double }
     20 
     21 ; Check the following transform:
     22 ;
     23 ; (ldr|str) X, [x0, #32]
     24 ;  ...
     25 ; add x0, x0, #32
     26 ;  ->
     27 ; (ldr|str) X, [x0, #32]!
     28 ;
     29 ; with X being either w1, x1, s0, d0 or q0.
     30 
     31 declare void @bar_byte(%s.byte*, i8)
     32 
     33 define void @load-pre-indexed-byte(%struct.byte* %ptr) nounwind {
     34 ; CHECK-LABEL: load-pre-indexed-byte
     35 ; CHECK: ldrb w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
     36 entry:
     37   %a = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1, i32 0
     38   %add = load i8, i8* %a, align 4
     39   br label %bar
     40 bar:
     41   %c = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1
     42   tail call void @bar_byte(%s.byte* %c, i8 %add)
     43   ret void
     44 }
     45 
     46 define void @store-pre-indexed-byte(%struct.byte* %ptr, i8 %val) nounwind {
     47 ; CHECK-LABEL: store-pre-indexed-byte
     48 ; CHECK: strb w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
     49 entry:
     50   %a = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1, i32 0
     51   store i8 %val, i8* %a, align 4
     52   br label %bar
     53 bar:
     54   %c = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1
     55   tail call void @bar_byte(%s.byte* %c, i8 %val)
     56   ret void
     57 }
     58 
     59 declare void @bar_halfword(%s.halfword*, i16)
     60 
     61 define void @load-pre-indexed-halfword(%struct.halfword* %ptr) nounwind {
     62 ; CHECK-LABEL: load-pre-indexed-halfword
     63 ; CHECK: ldrh w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
     64 entry:
     65   %a = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1, i32 0
     66   %add = load i16, i16* %a, align 4
     67   br label %bar
     68 bar:
     69   %c = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1
     70   tail call void @bar_halfword(%s.halfword* %c, i16 %add)
     71   ret void
     72 }
     73 
     74 define void @store-pre-indexed-halfword(%struct.halfword* %ptr, i16 %val) nounwind {
     75 ; CHECK-LABEL: store-pre-indexed-halfword
     76 ; CHECK: strh w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
     77 entry:
     78   %a = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1, i32 0
     79   store i16 %val, i16* %a, align 4
     80   br label %bar
     81 bar:
     82   %c = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1
     83   tail call void @bar_halfword(%s.halfword* %c, i16 %val)
     84   ret void
     85 }
     86 
     87 declare void @bar_word(%s.word*, i32)
     88 
     89 define void @load-pre-indexed-word(%struct.word* %ptr) nounwind {
     90 ; CHECK-LABEL: load-pre-indexed-word
     91 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
     92 entry:
     93   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
     94   %add = load i32, i32* %a, align 4
     95   br label %bar
     96 bar:
     97   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
     98   tail call void @bar_word(%s.word* %c, i32 %add)
     99   ret void
    100 }
    101 
    102 define void @store-pre-indexed-word(%struct.word* %ptr, i32 %val) nounwind {
    103 ; CHECK-LABEL: store-pre-indexed-word
    104 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    105 entry:
    106   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
    107   store i32 %val, i32* %a, align 4
    108   br label %bar
    109 bar:
    110   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
    111   tail call void @bar_word(%s.word* %c, i32 %val)
    112   ret void
    113 }
    114 
    115 declare void @bar_doubleword(%s.doubleword*, i64)
    116 
    117 define void @load-pre-indexed-doubleword(%struct.doubleword* %ptr) nounwind {
    118 ; CHECK-LABEL: load-pre-indexed-doubleword
    119 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    120 entry:
    121   %a = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1, i32 0
    122   %add = load i64, i64* %a, align 4
    123   br label %bar
    124 bar:
    125   %c = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1
    126   tail call void @bar_doubleword(%s.doubleword* %c, i64 %add)
    127   ret void
    128 }
    129 
    130 define void @store-pre-indexed-doubleword(%struct.doubleword* %ptr, i64 %val) nounwind {
    131 ; CHECK-LABEL: store-pre-indexed-doubleword
    132 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    133 entry:
    134   %a = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1, i32 0
    135   store i64 %val, i64* %a, align 4
    136   br label %bar
    137 bar:
    138   %c = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1
    139   tail call void @bar_doubleword(%s.doubleword* %c, i64 %val)
    140   ret void
    141 }
    142 
    143 declare void @bar_quadword(%s.quadword*, fp128)
    144 
    145 define void @load-pre-indexed-quadword(%struct.quadword* %ptr) nounwind {
    146 ; CHECK-LABEL: load-pre-indexed-quadword
    147 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    148 entry:
    149   %a = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1, i32 0
    150   %add = load fp128, fp128* %a, align 4
    151   br label %bar
    152 bar:
    153   %c = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1
    154   tail call void @bar_quadword(%s.quadword* %c, fp128 %add)
    155   ret void
    156 }
    157 
    158 define void @store-pre-indexed-quadword(%struct.quadword* %ptr, fp128 %val) nounwind {
    159 ; CHECK-LABEL: store-pre-indexed-quadword
    160 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    161 entry:
    162   %a = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1, i32 0
    163   store fp128 %val, fp128* %a, align 4
    164   br label %bar
    165 bar:
    166   %c = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1
    167   tail call void @bar_quadword(%s.quadword* %c, fp128 %val)
    168   ret void
    169 }
    170 
    171 declare void @bar_float(%s.float*, float)
    172 
    173 define void @load-pre-indexed-float(%struct.float* %ptr) nounwind {
    174 ; CHECK-LABEL: load-pre-indexed-float
    175 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    176 entry:
    177   %a = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1, i32 0
    178   %add = load float, float* %a, align 4
    179   br label %bar
    180 bar:
    181   %c = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1
    182   tail call void @bar_float(%s.float* %c, float %add)
    183   ret void
    184 }
    185 
    186 define void @store-pre-indexed-float(%struct.float* %ptr, float %val) nounwind {
    187 ; CHECK-LABEL: store-pre-indexed-float
    188 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    189 entry:
    190   %a = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1, i32 0
    191   store float %val, float* %a, align 4
    192   br label %bar
    193 bar:
    194   %c = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1
    195   tail call void @bar_float(%s.float* %c, float %val)
    196   ret void
    197 }
    198 
    199 declare void @bar_double(%s.double*, double)
    200 
    201 define void @load-pre-indexed-double(%struct.double* %ptr) nounwind {
    202 ; CHECK-LABEL: load-pre-indexed-double
    203 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    204 entry:
    205   %a = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1, i32 0
    206   %add = load double, double* %a, align 4
    207   br label %bar
    208 bar:
    209   %c = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1
    210   tail call void @bar_double(%s.double* %c, double %add)
    211   ret void
    212 }
    213 
    214 define void @store-pre-indexed-double(%struct.double* %ptr, double %val) nounwind {
    215 ; CHECK-LABEL: store-pre-indexed-double
    216 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    217 entry:
    218   %a = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1, i32 0
    219   store double %val, double* %a, align 4
    220   br label %bar
    221 bar:
    222   %c = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1
    223   tail call void @bar_double(%s.double* %c, double %val)
    224   ret void
    225 }
    226 
    227 ; Check the following transform:
    228 ;
    229 ; (ldp|stp) w1, w2 [x0, #32]
    230 ;  ...
    231 ; add x0, x0, #32
    232 ;  ->
    233 ; (ldp|stp) w1, w2, [x0, #32]!
    234 ;
    235 
    236 define void @load-pair-pre-indexed-word(%struct.word* %ptr) nounwind {
    237 ; CHECK-LABEL: load-pair-pre-indexed-word
    238 ; CHECK: ldp w{{[0-9]+}}, w{{[0-9]+}}, [x0, #32]!
    239 ; CHECK-NOT: add x0, x0, #32
    240 entry:
    241   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
    242   %a1 = load i32, i32* %a, align 4
    243   %b = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 1
    244   %b1 = load i32, i32* %b, align 4
    245   %add = add i32 %a1, %b1
    246   br label %bar
    247 bar:
    248   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
    249   tail call void @bar_word(%s.word* %c, i32 %add)
    250   ret void
    251 }
    252 
    253 define void @store-pair-pre-indexed-word(%struct.word* %ptr, i32 %val) nounwind {
    254 ; CHECK-LABEL: store-pair-pre-indexed-word
    255 ; CHECK: stp w{{[0-9]+}}, w{{[0-9]+}}, [x0, #32]!
    256 ; CHECK-NOT: add x0, x0, #32
    257 entry:
    258   %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0
    259   store i32 %val, i32* %a, align 4
    260   %b = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 1
    261   store i32 %val, i32* %b, align 4
    262   br label %bar
    263 bar:
    264   %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1
    265   tail call void @bar_word(%s.word* %c, i32 %val)
    266   ret void
    267 }
    268 
    269 ; Check the following transform:
    270 ;
    271 ; add x8, x8, #16
    272 ;  ...
    273 ; ldr X, [x8]
    274 ;  ->
    275 ; ldr X, [x8, #16]!
    276 ;
    277 ; with X being either w0, x0, s0, d0 or q0.
    278 
    279 %pre.struct.i32 = type { i32, i32, i32, i32, i32}
    280 %pre.struct.i64 = type { i32, i64, i64, i64, i64}
    281 %pre.struct.i128 = type { i32, <2 x i64>, <2 x i64>, <2 x i64>}
    282 %pre.struct.float = type { i32, float, float, float}
    283 %pre.struct.double = type { i32, double, double, double}
    284 
    285 define i32 @load-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond,
    286                                    %pre.struct.i32* %load2) nounwind {
    287 ; CHECK-LABEL: load-pre-indexed-word2
    288 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #4]!
    289   br i1 %cond, label %if.then, label %if.end
    290 if.then:
    291   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
    292   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 1
    293   br label %return
    294 if.end:
    295   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2
    296   br label %return
    297 return:
    298   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
    299   %ret = load i32, i32* %retptr
    300   ret i32 %ret
    301 }
    302 
    303 define i64 @load-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond,
    304                                          %pre.struct.i64* %load2) nounwind {
    305 ; CHECK-LABEL: load-pre-indexed-doubleword2
    306 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #8]!
    307   br i1 %cond, label %if.then, label %if.end
    308 if.then:
    309   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
    310   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 1
    311   br label %return
    312 if.end:
    313   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2
    314   br label %return
    315 return:
    316   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
    317   %ret = load i64, i64* %retptr
    318   ret i64 %ret
    319 }
    320 
    321 define <2 x i64> @load-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond,
    322                                              %pre.struct.i128* %load2) nounwind {
    323 ; CHECK-LABEL: load-pre-indexed-quadword2
    324 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #16]!
    325   br i1 %cond, label %if.then, label %if.end
    326 if.then:
    327   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
    328   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 1
    329   br label %return
    330 if.end:
    331   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2
    332   br label %return
    333 return:
    334   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
    335   %ret = load <2 x i64>, <2 x i64>* %retptr
    336   ret <2 x i64> %ret
    337 }
    338 
    339 define float @load-pre-indexed-float2(%pre.struct.float** %this, i1 %cond,
    340                                       %pre.struct.float* %load2) nounwind {
    341 ; CHECK-LABEL: load-pre-indexed-float2
    342 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #4]!
    343   br i1 %cond, label %if.then, label %if.end
    344 if.then:
    345   %load1 = load %pre.struct.float*, %pre.struct.float** %this
    346   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 1
    347   br label %return
    348 if.end:
    349   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2
    350   br label %return
    351 return:
    352   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
    353   %ret = load float, float* %retptr
    354   ret float %ret
    355 }
    356 
    357 define double @load-pre-indexed-double2(%pre.struct.double** %this, i1 %cond,
    358                                         %pre.struct.double* %load2) nounwind {
    359 ; CHECK-LABEL: load-pre-indexed-double2
    360 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #8]!
    361   br i1 %cond, label %if.then, label %if.end
    362 if.then:
    363   %load1 = load %pre.struct.double*, %pre.struct.double** %this
    364   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 1
    365   br label %return
    366 if.end:
    367   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2
    368   br label %return
    369 return:
    370   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
    371   %ret = load double, double* %retptr
    372   ret double %ret
    373 }
    374 
    375 define i32 @load-pre-indexed-word3(%pre.struct.i32** %this, i1 %cond,
    376                                    %pre.struct.i32* %load2) nounwind {
    377 ; CHECK-LABEL: load-pre-indexed-word3
    378 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #12]!
    379   br i1 %cond, label %if.then, label %if.end
    380 if.then:
    381   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
    382   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 3
    383   br label %return
    384 if.end:
    385   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4
    386   br label %return
    387 return:
    388   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
    389   %ret = load i32, i32* %retptr
    390   ret i32 %ret
    391 }
    392 
    393 define i64 @load-pre-indexed-doubleword3(%pre.struct.i64** %this, i1 %cond,
    394                                          %pre.struct.i64* %load2) nounwind {
    395 ; CHECK-LABEL: load-pre-indexed-doubleword3
    396 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #16]!
    397   br i1 %cond, label %if.then, label %if.end
    398 if.then:
    399   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
    400   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 2
    401   br label %return
    402 if.end:
    403   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 3
    404   br label %return
    405 return:
    406   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
    407   %ret = load i64, i64* %retptr
    408   ret i64 %ret
    409 }
    410 
    411 define <2 x i64> @load-pre-indexed-quadword3(%pre.struct.i128** %this, i1 %cond,
    412                                              %pre.struct.i128* %load2) nounwind {
    413 ; CHECK-LABEL: load-pre-indexed-quadword3
    414 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    415   br i1 %cond, label %if.then, label %if.end
    416 if.then:
    417   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
    418   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 2
    419   br label %return
    420 if.end:
    421   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3
    422   br label %return
    423 return:
    424   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
    425   %ret = load <2 x i64>, <2 x i64>* %retptr
    426   ret <2 x i64> %ret
    427 }
    428 
    429 define float @load-pre-indexed-float3(%pre.struct.float** %this, i1 %cond,
    430                                       %pre.struct.float* %load2) nounwind {
    431 ; CHECK-LABEL: load-pre-indexed-float3
    432 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #8]!
    433   br i1 %cond, label %if.then, label %if.end
    434 if.then:
    435   %load1 = load %pre.struct.float*, %pre.struct.float** %this
    436   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 2
    437   br label %return
    438 if.end:
    439   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3
    440   br label %return
    441 return:
    442   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
    443   %ret = load float, float* %retptr
    444   ret float %ret
    445 }
    446 
    447 define double @load-pre-indexed-double3(%pre.struct.double** %this, i1 %cond,
    448                                         %pre.struct.double* %load2) nounwind {
    449 ; CHECK-LABEL: load-pre-indexed-double3
    450 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #16]!
    451   br i1 %cond, label %if.then, label %if.end
    452 if.then:
    453   %load1 = load %pre.struct.double*, %pre.struct.double** %this
    454   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 2
    455   br label %return
    456 if.end:
    457   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3
    458   br label %return
    459 return:
    460   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
    461   %ret = load double, double* %retptr
    462   ret double %ret
    463 }
    464 
    465 ; Check the following transform:
    466 ;
    467 ; add x8, x8, #16
    468 ;  ...
    469 ; str X, [x8]
    470 ;  ->
    471 ; str X, [x8, #16]!
    472 ;
    473 ; with X being either w0, x0, s0, d0 or q0.
    474 
    475 define void @store-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond,
    476                                      %pre.struct.i32* %load2,
    477                                      i32 %val) nounwind {
    478 ; CHECK-LABEL: store-pre-indexed-word2
    479 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #4]!
    480   br i1 %cond, label %if.then, label %if.end
    481 if.then:
    482   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
    483   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 1
    484   br label %return
    485 if.end:
    486   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2
    487   br label %return
    488 return:
    489   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
    490   store i32 %val, i32* %retptr
    491   ret void
    492 }
    493 
    494 define void @store-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond,
    495                                            %pre.struct.i64* %load2,
    496                                            i64 %val) nounwind {
    497 ; CHECK-LABEL: store-pre-indexed-doubleword2
    498 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #8]!
    499   br i1 %cond, label %if.then, label %if.end
    500 if.then:
    501   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
    502   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 1
    503   br label %return
    504 if.end:
    505   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2
    506   br label %return
    507 return:
    508   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
    509   store i64 %val, i64* %retptr
    510   ret void
    511 }
    512 
    513 define void @store-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond,
    514                                          %pre.struct.i128* %load2,
    515                                          <2 x i64> %val) nounwind {
    516 ; CHECK-LABEL: store-pre-indexed-quadword2
    517 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #16]!
    518   br i1 %cond, label %if.then, label %if.end
    519 if.then:
    520   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
    521   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 1
    522   br label %return
    523 if.end:
    524   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2
    525   br label %return
    526 return:
    527   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
    528   store <2 x i64> %val, <2 x i64>* %retptr
    529   ret void
    530 }
    531 
    532 define void @store-pre-indexed-float2(%pre.struct.float** %this, i1 %cond,
    533                                       %pre.struct.float* %load2,
    534                                       float %val) nounwind {
    535 ; CHECK-LABEL: store-pre-indexed-float2
    536 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #4]!
    537   br i1 %cond, label %if.then, label %if.end
    538 if.then:
    539   %load1 = load %pre.struct.float*, %pre.struct.float** %this
    540   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 1
    541   br label %return
    542 if.end:
    543   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2
    544   br label %return
    545 return:
    546   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
    547   store float %val, float* %retptr
    548   ret void
    549 }
    550 
    551 define void @store-pre-indexed-double2(%pre.struct.double** %this, i1 %cond,
    552                                       %pre.struct.double* %load2,
    553                                       double %val) nounwind {
    554 ; CHECK-LABEL: store-pre-indexed-double2
    555 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #8]!
    556   br i1 %cond, label %if.then, label %if.end
    557 if.then:
    558   %load1 = load %pre.struct.double*, %pre.struct.double** %this
    559   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 1
    560   br label %return
    561 if.end:
    562   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2
    563   br label %return
    564 return:
    565   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
    566   store double %val, double* %retptr
    567   ret void
    568 }
    569 
    570 define void @store-pre-indexed-word3(%pre.struct.i32** %this, i1 %cond,
    571                                      %pre.struct.i32* %load2,
    572                                      i32 %val) nounwind {
    573 ; CHECK-LABEL: store-pre-indexed-word3
    574 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #12]!
    575   br i1 %cond, label %if.then, label %if.end
    576 if.then:
    577   %load1 = load %pre.struct.i32*, %pre.struct.i32** %this
    578   %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 3
    579   br label %return
    580 if.end:
    581   %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4
    582   br label %return
    583 return:
    584   %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ]
    585   store i32 %val, i32* %retptr
    586   ret void
    587 }
    588 
    589 define void @store-pre-indexed-doubleword3(%pre.struct.i64** %this, i1 %cond,
    590                                            %pre.struct.i64* %load2,
    591                                            i64 %val) nounwind {
    592 ; CHECK-LABEL: store-pre-indexed-doubleword3
    593 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #24]!
    594   br i1 %cond, label %if.then, label %if.end
    595 if.then:
    596   %load1 = load %pre.struct.i64*, %pre.struct.i64** %this
    597   %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 3
    598   br label %return
    599 if.end:
    600   %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 4
    601   br label %return
    602 return:
    603   %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ]
    604   store i64 %val, i64* %retptr
    605   ret void
    606 }
    607 
    608 define void @store-pre-indexed-quadword3(%pre.struct.i128** %this, i1 %cond,
    609                                          %pre.struct.i128* %load2,
    610                                          <2 x i64> %val) nounwind {
    611 ; CHECK-LABEL: store-pre-indexed-quadword3
    612 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]!
    613   br i1 %cond, label %if.then, label %if.end
    614 if.then:
    615   %load1 = load %pre.struct.i128*, %pre.struct.i128** %this
    616   %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 2
    617   br label %return
    618 if.end:
    619   %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3
    620   br label %return
    621 return:
    622   %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ]
    623   store <2 x i64> %val, <2 x i64>* %retptr
    624   ret void
    625 }
    626 
    627 define void @store-pre-indexed-float3(%pre.struct.float** %this, i1 %cond,
    628                                       %pre.struct.float* %load2,
    629                                       float %val) nounwind {
    630 ; CHECK-LABEL: store-pre-indexed-float3
    631 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #8]!
    632   br i1 %cond, label %if.then, label %if.end
    633 if.then:
    634   %load1 = load %pre.struct.float*, %pre.struct.float** %this
    635   %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 2
    636   br label %return
    637 if.end:
    638   %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3
    639   br label %return
    640 return:
    641   %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ]
    642   store float %val, float* %retptr
    643   ret void
    644 }
    645 
    646 define void @store-pre-indexed-double3(%pre.struct.double** %this, i1 %cond,
    647                                       %pre.struct.double* %load2,
    648                                       double %val) nounwind {
    649 ; CHECK-LABEL: store-pre-indexed-double3
    650 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #16]!
    651   br i1 %cond, label %if.then, label %if.end
    652 if.then:
    653   %load1 = load %pre.struct.double*, %pre.struct.double** %this
    654   %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 2
    655   br label %return
    656 if.end:
    657   %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3
    658   br label %return
    659 return:
    660   %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ]
    661   store double %val, double* %retptr
    662   ret void
    663 }
    664 
    665 ; Check the following transform:
    666 ;
    667 ; ldr X, [x20]
    668 ;  ...
    669 ; add x20, x20, #32
    670 ;  ->
    671 ; ldr X, [x20], #32
    672 ;
    673 ; with X being either w0, x0, s0, d0 or q0.
    674 
    675 define void @load-post-indexed-byte(i8* %array, i64 %count) nounwind {
    676 ; CHECK-LABEL: load-post-indexed-byte
    677 ; CHECK: ldrb w{{[0-9]+}}, [x{{[0-9]+}}], #4
    678 entry:
    679   %gep1 = getelementptr i8, i8* %array, i64 2
    680   br label %body
    681 
    682 body:
    683   %iv2 = phi i8* [ %gep3, %body ], [ %gep1, %entry ]
    684   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    685   %gep2 = getelementptr i8, i8* %iv2, i64 -1
    686   %load = load i8, i8* %gep2
    687   call void @use-byte(i8 %load)
    688   %load2 = load i8, i8* %iv2
    689   call void @use-byte(i8 %load2)
    690   %iv.next = add i64 %iv, -4
    691   %gep3 = getelementptr i8, i8* %iv2, i64 4
    692   %cond = icmp eq i64 %iv.next, 0
    693   br i1 %cond, label %exit, label %body
    694 
    695 exit:
    696   ret void
    697 }
    698 
    699 define void @load-post-indexed-halfword(i16* %array, i64 %count) nounwind {
    700 ; CHECK-LABEL: load-post-indexed-halfword
    701 ; CHECK: ldrh w{{[0-9]+}}, [x{{[0-9]+}}], #8
    702 entry:
    703   %gep1 = getelementptr i16, i16* %array, i64 2
    704   br label %body
    705 
    706 body:
    707   %iv2 = phi i16* [ %gep3, %body ], [ %gep1, %entry ]
    708   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    709   %gep2 = getelementptr i16, i16* %iv2, i64 -1
    710   %load = load i16, i16* %gep2
    711   call void @use-halfword(i16 %load)
    712   %load2 = load i16, i16* %iv2
    713   call void @use-halfword(i16 %load2)
    714   %iv.next = add i64 %iv, -4
    715   %gep3 = getelementptr i16, i16* %iv2, i64 4
    716   %cond = icmp eq i64 %iv.next, 0
    717   br i1 %cond, label %exit, label %body
    718 
    719 exit:
    720   ret void
    721 }
    722 
    723 define void @load-post-indexed-word(i32* %array, i64 %count) nounwind {
    724 ; CHECK-LABEL: load-post-indexed-word
    725 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #16
    726 entry:
    727   %gep1 = getelementptr i32, i32* %array, i64 2
    728   br label %body
    729 
    730 body:
    731   %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
    732   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    733   %gep2 = getelementptr i32, i32* %iv2, i64 -1
    734   %load = load i32, i32* %gep2
    735   call void @use-word(i32 %load)
    736   %load2 = load i32, i32* %iv2
    737   call void @use-word(i32 %load2)
    738   %iv.next = add i64 %iv, -4
    739   %gep3 = getelementptr i32, i32* %iv2, i64 4
    740   %cond = icmp eq i64 %iv.next, 0
    741   br i1 %cond, label %exit, label %body
    742 
    743 exit:
    744   ret void
    745 }
    746 
    747 define void @load-post-indexed-doubleword(i64* %array, i64 %count) nounwind {
    748 ; CHECK-LABEL: load-post-indexed-doubleword
    749 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #32
    750 entry:
    751   %gep1 = getelementptr i64, i64* %array, i64 2
    752   br label %body
    753 
    754 body:
    755   %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
    756   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    757   %gep2 = getelementptr i64, i64* %iv2, i64 -1
    758   %load = load i64, i64* %gep2
    759   call void @use-doubleword(i64 %load)
    760   %load2 = load i64, i64* %iv2
    761   call void @use-doubleword(i64 %load2)
    762   %iv.next = add i64 %iv, -4
    763   %gep3 = getelementptr i64, i64* %iv2, i64 4
    764   %cond = icmp eq i64 %iv.next, 0
    765   br i1 %cond, label %exit, label %body
    766 
    767 exit:
    768   ret void
    769 }
    770 
    771 define void @load-post-indexed-quadword(<2 x i64>* %array, i64 %count) nounwind {
    772 ; CHECK-LABEL: load-post-indexed-quadword
    773 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #64
    774 entry:
    775   %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2
    776   br label %body
    777 
    778 body:
    779   %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ]
    780   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    781   %gep2 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 -1
    782   %load = load <2 x i64>, <2 x i64>* %gep2
    783   call void @use-quadword(<2 x i64> %load)
    784   %load2 = load <2 x i64>, <2 x i64>* %iv2
    785   call void @use-quadword(<2 x i64> %load2)
    786   %iv.next = add i64 %iv, -4
    787   %gep3 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 4
    788   %cond = icmp eq i64 %iv.next, 0
    789   br i1 %cond, label %exit, label %body
    790 
    791 exit:
    792   ret void
    793 }
    794 
    795 define void @load-post-indexed-float(float* %array, i64 %count) nounwind {
    796 ; CHECK-LABEL: load-post-indexed-float
    797 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #16
    798 entry:
    799   %gep1 = getelementptr float, float* %array, i64 2
    800   br label %body
    801 
    802 body:
    803   %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
    804   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    805   %gep2 = getelementptr float, float* %iv2, i64 -1
    806   %load = load float, float* %gep2
    807   call void @use-float(float %load)
    808   %load2 = load float, float* %iv2
    809   call void @use-float(float %load2)
    810   %iv.next = add i64 %iv, -4
    811   %gep3 = getelementptr float, float* %iv2, i64 4
    812   %cond = icmp eq i64 %iv.next, 0
    813   br i1 %cond, label %exit, label %body
    814 
    815 exit:
    816   ret void
    817 }
    818 
    819 define void @load-post-indexed-double(double* %array, i64 %count) nounwind {
    820 ; CHECK-LABEL: load-post-indexed-double
    821 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #32
    822 entry:
    823   %gep1 = getelementptr double, double* %array, i64 2
    824   br label %body
    825 
    826 body:
    827   %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
    828   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    829   %gep2 = getelementptr double, double* %iv2, i64 -1
    830   %load = load double, double* %gep2
    831   call void @use-double(double %load)
    832   %load2 = load double, double* %iv2
    833   call void @use-double(double %load2)
    834   %iv.next = add i64 %iv, -4
    835   %gep3 = getelementptr double, double* %iv2, i64 4
    836   %cond = icmp eq i64 %iv.next, 0
    837   br i1 %cond, label %exit, label %body
    838 
    839 exit:
    840   ret void
    841 }
    842 
    843 ; Check the following transform:
    844 ;
    845 ; str X, [x20]
    846 ;  ...
    847 ; add x20, x20, #32
    848 ;  ->
    849 ; str X, [x20], #32
    850 ;
    851 ; with X being either w0, x0, s0, d0 or q0.
    852 
    853 define void @store-post-indexed-byte(i8* %array, i64 %count, i8 %val) nounwind {
    854 ; CHECK-LABEL: store-post-indexed-byte
    855 ; CHECK: strb w{{[0-9]+}}, [x{{[0-9]+}}], #4
    856 entry:
    857   %gep1 = getelementptr i8, i8* %array, i64 2
    858   br label %body
    859 
    860 body:
    861   %iv2 = phi i8* [ %gep3, %body ], [ %gep1, %entry ]
    862   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    863   %gep2 = getelementptr i8, i8* %iv2, i64 -1
    864   %load = load i8, i8* %gep2
    865   call void @use-byte(i8 %load)
    866   store i8 %val, i8* %iv2
    867   %iv.next = add i64 %iv, -4
    868   %gep3 = getelementptr i8, i8* %iv2, i64 4
    869   %cond = icmp eq i64 %iv.next, 0
    870   br i1 %cond, label %exit, label %body
    871 
    872 exit:
    873   ret void
    874 }
    875 
    876 define void @store-post-indexed-halfword(i16* %array, i64 %count, i16 %val) nounwind {
    877 ; CHECK-LABEL: store-post-indexed-halfword
    878 ; CHECK: strh w{{[0-9]+}}, [x{{[0-9]+}}], #8
    879 entry:
    880   %gep1 = getelementptr i16, i16* %array, i64 2
    881   br label %body
    882 
    883 body:
    884   %iv2 = phi i16* [ %gep3, %body ], [ %gep1, %entry ]
    885   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    886   %gep2 = getelementptr i16, i16* %iv2, i64 -1
    887   %load = load i16, i16* %gep2
    888   call void @use-halfword(i16 %load)
    889   store i16 %val, i16* %iv2
    890   %iv.next = add i64 %iv, -4
    891   %gep3 = getelementptr i16, i16* %iv2, i64 4
    892   %cond = icmp eq i64 %iv.next, 0
    893   br i1 %cond, label %exit, label %body
    894 
    895 exit:
    896   ret void
    897 }
    898 
    899 define void @store-post-indexed-word(i32* %array, i64 %count, i32 %val) nounwind {
    900 ; CHECK-LABEL: store-post-indexed-word
    901 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #16
    902 entry:
    903   %gep1 = getelementptr i32, i32* %array, i64 2
    904   br label %body
    905 
    906 body:
    907   %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ]
    908   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    909   %gep2 = getelementptr i32, i32* %iv2, i64 -1
    910   %load = load i32, i32* %gep2
    911   call void @use-word(i32 %load)
    912   store i32 %val, i32* %iv2
    913   %iv.next = add i64 %iv, -4
    914   %gep3 = getelementptr i32, i32* %iv2, i64 4
    915   %cond = icmp eq i64 %iv.next, 0
    916   br i1 %cond, label %exit, label %body
    917 
    918 exit:
    919   ret void
    920 }
    921 
    922 define void @store-post-indexed-doubleword(i64* %array, i64 %count, i64 %val) nounwind {
    923 ; CHECK-LABEL: store-post-indexed-doubleword
    924 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #32
    925 entry:
    926   %gep1 = getelementptr i64, i64* %array, i64 2
    927   br label %body
    928 
    929 body:
    930   %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ]
    931   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    932   %gep2 = getelementptr i64, i64* %iv2, i64 -1
    933   %load = load i64, i64* %gep2
    934   call void @use-doubleword(i64 %load)
    935   store i64 %val, i64* %iv2
    936   %iv.next = add i64 %iv, -4
    937   %gep3 = getelementptr i64, i64* %iv2, i64 4
    938   %cond = icmp eq i64 %iv.next, 0
    939   br i1 %cond, label %exit, label %body
    940 
    941 exit:
    942   ret void
    943 }
    944 
    945 define void @store-post-indexed-quadword(<2 x i64>* %array, i64 %count, <2 x i64> %val) nounwind {
    946 ; CHECK-LABEL: store-post-indexed-quadword
    947 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #64
    948 entry:
    949   %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2
    950   br label %body
    951 
    952 body:
    953   %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ]
    954   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    955   %gep2 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 -1
    956   %load = load <2 x i64>, <2 x i64>* %gep2
    957   call void @use-quadword(<2 x i64> %load)
    958   store <2 x i64> %val, <2 x i64>* %iv2
    959   %iv.next = add i64 %iv, -4
    960   %gep3 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 4
    961   %cond = icmp eq i64 %iv.next, 0
    962   br i1 %cond, label %exit, label %body
    963 
    964 exit:
    965   ret void
    966 }
    967 
    968 define void @store-post-indexed-float(float* %array, i64 %count, float %val) nounwind {
    969 ; CHECK-LABEL: store-post-indexed-float
    970 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #16
    971 entry:
    972   %gep1 = getelementptr float, float* %array, i64 2
    973   br label %body
    974 
    975 body:
    976   %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ]
    977   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
    978   %gep2 = getelementptr float, float* %iv2, i64 -1
    979   %load = load float, float* %gep2
    980   call void @use-float(float %load)
    981   store float %val, float* %iv2
    982   %iv.next = add i64 %iv, -4
    983   %gep3 = getelementptr float, float* %iv2, i64 4
    984   %cond = icmp eq i64 %iv.next, 0
    985   br i1 %cond, label %exit, label %body
    986 
    987 exit:
    988   ret void
    989 }
    990 
    991 define void @store-post-indexed-double(double* %array, i64 %count, double %val) nounwind {
    992 ; CHECK-LABEL: store-post-indexed-double
    993 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #32
    994 entry:
    995   %gep1 = getelementptr double, double* %array, i64 2
    996   br label %body
    997 
    998 body:
    999   %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ]
   1000   %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]
   1001   %gep2 = getelementptr double, double* %iv2, i64 -1
   1002   %load = load double, double* %gep2
   1003   call void @use-double(double %load)
   1004   store double %val, double* %iv2
   1005   %iv.next = add i64 %iv, -4
   1006   %gep3 = getelementptr double, double* %iv2, i64 4
   1007   %cond = icmp eq i64 %iv.next, 0
   1008   br i1 %cond, label %exit, label %body
   1009 
   1010 exit:
   1011   ret void
   1012 }
   1013 
   1014 declare void @use-byte(i8)
   1015 declare void @use-halfword(i16)
   1016 declare void @use-word(i32)
   1017 declare void @use-doubleword(i64)
   1018 declare void @use-quadword(<2 x i64>)
   1019 declare void @use-float(float)
   1020 declare void @use-double(double)
   1021 
   1022 ; Check the following transform:
   1023 ;
   1024 ; stp w0, [x20]
   1025 ;  ...
   1026 ; add x20, x20, #32
   1027 ;  ->
   1028 ; stp w0, [x20], #32
   1029 
   1030 define void @store-pair-post-indexed-word() nounwind {
   1031 ; CHECK-LABEL: store-pair-post-indexed-word
   1032 ; CHECK: stp w{{[0-9]+}}, w{{[0-9]+}}, [sp], #16
   1033 ; CHECK: ret
   1034   %src = alloca { i32, i32 }, align 8
   1035   %dst = alloca { i32, i32 }, align 8
   1036 
   1037   %src.realp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %src, i32 0, i32 0
   1038   %src.real = load i32, i32* %src.realp
   1039   %src.imagp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %src, i32 0, i32 1
   1040   %src.imag = load i32, i32* %src.imagp
   1041 
   1042   %dst.realp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %dst, i32 0, i32 0
   1043   %dst.imagp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %dst, i32 0, i32 1
   1044   store i32 %src.real, i32* %dst.realp
   1045   store i32 %src.imag, i32* %dst.imagp
   1046   ret void
   1047 }
   1048 
   1049 define void @store-pair-post-indexed-doubleword() nounwind {
   1050 ; CHECK-LABEL: store-pair-post-indexed-doubleword
   1051 ; CHECK: stp x{{[0-9]+}}, x{{[0-9]+}}, [sp], #32
   1052 ; CHECK: ret
   1053   %src = alloca { i64, i64 }, align 8
   1054   %dst = alloca { i64, i64 }, align 8
   1055 
   1056   %src.realp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %src, i32 0, i32 0
   1057   %src.real = load i64, i64* %src.realp
   1058   %src.imagp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %src, i32 0, i32 1
   1059   %src.imag = load i64, i64* %src.imagp
   1060 
   1061   %dst.realp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %dst, i32 0, i32 0
   1062   %dst.imagp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %dst, i32 0, i32 1
   1063   store i64 %src.real, i64* %dst.realp
   1064   store i64 %src.imag, i64* %dst.imagp
   1065   ret void
   1066 }
   1067 
   1068 define void @store-pair-post-indexed-float() nounwind {
   1069 ; CHECK-LABEL: store-pair-post-indexed-float
   1070 ; CHECK: stp s{{[0-9]+}}, s{{[0-9]+}}, [sp], #16
   1071 ; CHECK: ret
   1072   %src = alloca { float, float }, align 8
   1073   %dst = alloca { float, float }, align 8
   1074 
   1075   %src.realp = getelementptr inbounds { float, float }, { float, float }* %src, i32 0, i32 0
   1076   %src.real = load float, float* %src.realp
   1077   %src.imagp = getelementptr inbounds { float, float }, { float, float }* %src, i32 0, i32 1
   1078   %src.imag = load float, float* %src.imagp
   1079 
   1080   %dst.realp = getelementptr inbounds { float, float }, { float, float }* %dst, i32 0, i32 0
   1081   %dst.imagp = getelementptr inbounds { float, float }, { float, float }* %dst, i32 0, i32 1
   1082   store float %src.real, float* %dst.realp
   1083   store float %src.imag, float* %dst.imagp
   1084   ret void
   1085 }
   1086 
   1087 define void @store-pair-post-indexed-double() nounwind {
   1088 ; CHECK-LABEL: store-pair-post-indexed-double
   1089 ; CHECK: stp d{{[0-9]+}}, d{{[0-9]+}}, [sp], #32
   1090 ; CHECK: ret
   1091   %src = alloca { double, double }, align 8
   1092   %dst = alloca { double, double }, align 8
   1093 
   1094   %src.realp = getelementptr inbounds { double, double }, { double, double }* %src, i32 0, i32 0
   1095   %src.real = load double, double* %src.realp
   1096   %src.imagp = getelementptr inbounds { double, double }, { double, double }* %src, i32 0, i32 1
   1097   %src.imag = load double, double* %src.imagp
   1098 
   1099   %dst.realp = getelementptr inbounds { double, double }, { double, double }* %dst, i32 0, i32 0
   1100   %dst.imagp = getelementptr inbounds { double, double }, { double, double }* %dst, i32 0, i32 1
   1101   store double %src.real, double* %dst.realp
   1102   store double %src.imag, double* %dst.imagp
   1103   ret void
   1104 }
   1105 
   1106 ; Check the following transform:
   1107 ;
   1108 ; (ldr|str) X, [x20]
   1109 ;  ...
   1110 ; sub x20, x20, #16
   1111 ;  ->
   1112 ; (ldr|str) X, [x20], #-16
   1113 ;
   1114 ; with X being either w0, x0, s0, d0 or q0.
   1115 
   1116 define void @post-indexed-sub-word(i32* %a, i32* %b, i64 %count) nounwind {
   1117 ; CHECK-LABEL: post-indexed-sub-word
   1118 ; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #-8
   1119 ; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #-8
   1120   br label %for.body
   1121 for.body:
   1122   %phi1 = phi i32* [ %gep4, %for.body ], [ %b, %0 ]
   1123   %phi2 = phi i32* [ %gep3, %for.body ], [ %a, %0 ]
   1124   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
   1125   %gep1 = getelementptr i32, i32* %phi1, i64 -1
   1126   %load1 = load i32, i32* %gep1
   1127   %gep2 = getelementptr i32, i32* %phi2, i64 -1
   1128   store i32 %load1, i32* %gep2
   1129   %load2 = load i32, i32* %phi1
   1130   store i32 %load2, i32* %phi2
   1131   %dec.i = add nsw i64 %i, -1
   1132   %gep3 = getelementptr i32, i32* %phi2, i64 -2
   1133   %gep4 = getelementptr i32, i32* %phi1, i64 -2
   1134   %cond = icmp sgt i64 %dec.i, 0
   1135   br i1 %cond, label %for.body, label %end
   1136 end:
   1137   ret void
   1138 }
   1139 
   1140 define void @post-indexed-sub-doubleword(i64* %a, i64* %b, i64 %count) nounwind {
   1141 ; CHECK-LABEL: post-indexed-sub-doubleword
   1142 ; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #-16
   1143 ; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #-16
   1144   br label %for.body
   1145 for.body:
   1146   %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ]
   1147   %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ]
   1148   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
   1149   %gep1 = getelementptr i64, i64* %phi1, i64 -1
   1150   %load1 = load i64, i64* %gep1
   1151   %gep2 = getelementptr i64, i64* %phi2, i64 -1
   1152   store i64 %load1, i64* %gep2
   1153   %load2 = load i64, i64* %phi1
   1154   store i64 %load2, i64* %phi2
   1155   %dec.i = add nsw i64 %i, -1
   1156   %gep3 = getelementptr i64, i64* %phi2, i64 -2
   1157   %gep4 = getelementptr i64, i64* %phi1, i64 -2
   1158   %cond = icmp sgt i64 %dec.i, 0
   1159   br i1 %cond, label %for.body, label %end
   1160 end:
   1161   ret void
   1162 }
   1163 
   1164 define void @post-indexed-sub-quadword(<2 x i64>* %a, <2 x i64>* %b, i64 %count) nounwind {
   1165 ; CHECK-LABEL: post-indexed-sub-quadword
   1166 ; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #-32
   1167 ; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #-32
   1168   br label %for.body
   1169 for.body:
   1170   %phi1 = phi <2 x i64>* [ %gep4, %for.body ], [ %b, %0 ]
   1171   %phi2 = phi <2 x i64>* [ %gep3, %for.body ], [ %a, %0 ]
   1172   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
   1173   %gep1 = getelementptr <2 x i64>, <2 x i64>* %phi1, i64 -1
   1174   %load1 = load <2 x i64>, <2 x i64>* %gep1
   1175   %gep2 = getelementptr <2 x i64>, <2 x i64>* %phi2, i64 -1
   1176   store <2 x i64> %load1, <2 x i64>* %gep2
   1177   %load2 = load <2 x i64>, <2 x i64>* %phi1
   1178   store <2 x i64> %load2, <2 x i64>* %phi2
   1179   %dec.i = add nsw i64 %i, -1
   1180   %gep3 = getelementptr <2 x i64>, <2 x i64>* %phi2, i64 -2
   1181   %gep4 = getelementptr <2 x i64>, <2 x i64>* %phi1, i64 -2
   1182   %cond = icmp sgt i64 %dec.i, 0
   1183   br i1 %cond, label %for.body, label %end
   1184 end:
   1185   ret void
   1186 }
   1187 
   1188 define void @post-indexed-sub-float(float* %a, float* %b, i64 %count) nounwind {
   1189 ; CHECK-LABEL: post-indexed-sub-float
   1190 ; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #-8
   1191 ; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #-8
   1192   br label %for.body
   1193 for.body:
   1194   %phi1 = phi float* [ %gep4, %for.body ], [ %b, %0 ]
   1195   %phi2 = phi float* [ %gep3, %for.body ], [ %a, %0 ]
   1196   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
   1197   %gep1 = getelementptr float, float* %phi1, i64 -1
   1198   %load1 = load float, float* %gep1
   1199   %gep2 = getelementptr float, float* %phi2, i64 -1
   1200   store float %load1, float* %gep2
   1201   %load2 = load float, float* %phi1
   1202   store float %load2, float* %phi2
   1203   %dec.i = add nsw i64 %i, -1
   1204   %gep3 = getelementptr float, float* %phi2, i64 -2
   1205   %gep4 = getelementptr float, float* %phi1, i64 -2
   1206   %cond = icmp sgt i64 %dec.i, 0
   1207   br i1 %cond, label %for.body, label %end
   1208 end:
   1209   ret void
   1210 }
   1211 
   1212 define void @post-indexed-sub-double(double* %a, double* %b, i64 %count) nounwind {
   1213 ; CHECK-LABEL: post-indexed-sub-double
   1214 ; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #-16
   1215 ; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #-16
   1216   br label %for.body
   1217 for.body:
   1218   %phi1 = phi double* [ %gep4, %for.body ], [ %b, %0 ]
   1219   %phi2 = phi double* [ %gep3, %for.body ], [ %a, %0 ]
   1220   %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]
   1221   %gep1 = getelementptr double, double* %phi1, i64 -1
   1222   %load1 = load double, double* %gep1
   1223   %gep2 = getelementptr double, double* %phi2, i64 -1
   1224   store double %load1, double* %gep2
   1225   %load2 = load double, double* %phi1
   1226   store double %load2, double* %phi2
   1227   %dec.i = add nsw i64 %i, -1
   1228   %gep3 = getelementptr double, double* %phi2, i64 -2
   1229   %gep4 = getelementptr double, double* %phi1, i64 -2
   1230   %cond = icmp sgt i64 %dec.i, 0
   1231   br i1 %cond, label %for.body, label %end
   1232 end:
   1233   ret void
   1234 }
   1235