Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s
      2 
      3 ;
      4 ; Test that we only use the sign/zero extend in the address calculation when
      5 ; necessary.
      6 ;
      7 ; SHIFT
      8 ;
      9 define i64 @load_addr_shift_zext1(i32 %a, i64 %b) {
     10 ; CHECK-LABEL: load_addr_shift_zext1
     11 ; CHECK:       ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
     12   %1 = zext i32 %a to i64
     13   %2 = shl i64 %1, 3
     14   %3 = add i64 %b, %2
     15   %4 = inttoptr i64 %3 to i64*
     16   %5 = load i64, i64* %4
     17   ret i64 %5
     18 }
     19 
     20 define i64 @load_addr_shift_zext2(i32 zeroext %a, i64 %b) {
     21 ; CHECK-LABEL: load_addr_shift_zext2
     22 ; CHECK:       ldr {{x[0-9]+}}, [x1, x0, lsl #3]
     23   %1 = zext i32 %a to i64
     24   %2 = shl i64 %1, 3
     25   %3 = add i64 %b, %2
     26   %4 = inttoptr i64 %3 to i64*
     27   %5 = load i64, i64* %4
     28   ret i64 %5
     29 }
     30 
     31 define i64 @load_addr_shift_zext3(i32 signext %a, i64 %b) {
     32 ; CHECK-LABEL: load_addr_shift_zext3
     33 ; CHECK:       ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
     34   %1 = zext i32 %a to i64
     35   %2 = shl i64 %1, 3
     36   %3 = add i64 %b, %2
     37   %4 = inttoptr i64 %3 to i64*
     38   %5 = load i64, i64* %4
     39   ret i64 %5
     40 }
     41 
     42 define i64 @load_addr_shift_sext1(i32 %a, i64 %b) {
     43 ; CHECK-LABEL: load_addr_shift_sext1
     44 ; CHECK:       ldr {{x[0-9]+}}, [x1, w0, sxtw #3]
     45   %1 = sext i32 %a to i64
     46   %2 = shl i64 %1, 3
     47   %3 = add i64 %b, %2
     48   %4 = inttoptr i64 %3 to i64*
     49   %5 = load i64, i64* %4
     50   ret i64 %5
     51 }
     52 
     53 define i64 @load_addr_shift_sext2(i32 zeroext %a, i64 %b) {
     54 ; CHECK-LABEL: load_addr_shift_sext2
     55 ; CHECK:       ldr {{x[0-9]+}}, [x1, w0, sxtw #3]
     56   %1 = sext i32 %a to i64
     57   %2 = shl i64 %1, 3
     58   %3 = add i64 %b, %2
     59   %4 = inttoptr i64 %3 to i64*
     60   %5 = load i64, i64* %4
     61   ret i64 %5
     62 }
     63 
     64 define i64 @load_addr_shift_sext3(i32 signext %a, i64 %b) {
     65 ; CHECK-LABEL: load_addr_shift_sext3
     66 ; CHECK:       ldr {{x[0-9]+}}, [x1, x0, lsl #3]
     67   %1 = sext i32 %a to i64
     68   %2 = shl i64 %1, 3
     69   %3 = add i64 %b, %2
     70   %4 = inttoptr i64 %3 to i64*
     71   %5 = load i64, i64* %4
     72   ret i64 %5
     73 }
     74 
     75 ;
     76 ; MUL
     77 ;
     78 define i64 @load_addr_mul_zext1(i32 %a, i64 %b) {
     79 ; CHECK-LABEL: load_addr_mul_zext1
     80 ; CHECK:       ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
     81   %1 = zext i32 %a to i64
     82   %2 = mul i64 %1, 8
     83   %3 = add i64 %b, %2
     84   %4 = inttoptr i64 %3 to i64*
     85   %5 = load i64, i64* %4
     86   ret i64 %5
     87 }
     88 
     89 define i64 @load_addr_mul_zext2(i32 zeroext %a, i64 %b) {
     90 ; CHECK-LABEL: load_addr_mul_zext2
     91 ; CHECK:       ldr {{x[0-9]+}}, [x1, x0, lsl #3]
     92   %1 = zext i32 %a to i64
     93   %2 = mul i64 %1, 8
     94   %3 = add i64 %b, %2
     95   %4 = inttoptr i64 %3 to i64*
     96   %5 = load i64, i64* %4
     97   ret i64 %5
     98 }
     99 
    100 define i64 @load_addr_mul_zext3(i32 signext %a, i64 %b) {
    101 ; CHECK-LABEL: load_addr_mul_zext3
    102 ; CHECK:       ldr {{x[0-9]+}}, [x1, w0, uxtw #3]
    103   %1 = zext i32 %a to i64
    104   %2 = mul i64 %1, 8
    105   %3 = add i64 %b, %2
    106   %4 = inttoptr i64 %3 to i64*
    107   %5 = load i64, i64* %4
    108   ret i64 %5
    109 }
    110 
    111 define i64 @load_addr_mul_sext1(i32 %a, i64 %b) {
    112 ; CHECK-LABEL: load_addr_mul_sext1
    113 ; CHECK:       ldr {{x[0-9]+}}, [x1, w0, sxtw #3]
    114   %1 = sext i32 %a to i64
    115   %2 = mul i64 %1, 8
    116   %3 = add i64 %b, %2
    117   %4 = inttoptr i64 %3 to i64*
    118   %5 = load i64, i64* %4
    119   ret i64 %5
    120 }
    121 
    122 define i64 @load_addr_mul_sext2(i32 zeroext %a, i64 %b) {
    123 ; CHECK-LABEL: load_addr_mul_sext2
    124 ; CHECK:       ldr {{x[0-9]+}}, [x1, w0, sxtw #3]
    125   %1 = sext i32 %a to i64
    126   %2 = mul i64 %1, 8
    127   %3 = add i64 %b, %2
    128   %4 = inttoptr i64 %3 to i64*
    129   %5 = load i64, i64* %4
    130   ret i64 %5
    131 }
    132 
    133 define i64 @load_addr_mul_sext3(i32 signext %a, i64 %b) {
    134 ; CHECK-LABEL: load_addr_mul_sext3
    135 ; CHECK:       ldr {{x[0-9]+}}, [x1, x0, lsl #3]
    136   %1 = sext i32 %a to i64
    137   %2 = mul i64 %1, 8
    138   %3 = add i64 %b, %2
    139   %4 = inttoptr i64 %3 to i64*
    140   %5 = load i64, i64* %4
    141   ret i64 %5
    142 }
    143 
    144 
    145 ;
    146 ; Test folding of the sign-/zero-extend into the load instruction.
    147 ;
    148 
    149 ; Unscaled
    150 define i32 @load_unscaled_zext_i8_to_i32(i64 %a) {
    151 ; CHECK-LABEL: load_unscaled_zext_i8_to_i32
    152 ; CHECK:       ldurb w0, [x0, #-8]
    153 ; CHECK-NOT:   uxtb
    154   %1 = sub i64 %a, 8
    155   %2 = inttoptr i64 %1 to i8*
    156   %3 = load i8, i8* %2
    157   %4 = zext i8 %3 to i32
    158   ret i32 %4
    159 }
    160 
    161 define i32 @load_unscaled_zext_i16_to_i32(i64 %a) {
    162 ; CHECK-LABEL: load_unscaled_zext_i16_to_i32
    163 ; CHECK:       ldurh w0, [x0, #-8]
    164 ; CHECK-NOT:   uxth
    165   %1 = sub i64 %a, 8
    166   %2 = inttoptr i64 %1 to i16*
    167   %3 = load i16, i16* %2
    168   %4 = zext i16 %3 to i32
    169   ret i32 %4
    170 }
    171 
    172 define i64 @load_unscaled_zext_i8_to_i64(i64 %a) {
    173 ; CHECK-LABEL: load_unscaled_zext_i8_to_i64
    174 ; CHECK:       ldurb w0, [x0, #-8]
    175 ; CHECK-NOT:   uxtb
    176   %1 = sub i64 %a, 8
    177   %2 = inttoptr i64 %1 to i8*
    178   %3 = load i8, i8* %2
    179   %4 = zext i8 %3 to i64
    180   ret i64 %4
    181 }
    182 
    183 define i64 @load_unscaled_zext_i16_to_i64(i64 %a) {
    184 ; CHECK-LABEL: load_unscaled_zext_i16_to_i64
    185 ; CHECK:       ldurh w0, [x0, #-8]
    186 ; CHECK-NOT:   uxth
    187   %1 = sub i64 %a, 8
    188   %2 = inttoptr i64 %1 to i16*
    189   %3 = load i16, i16* %2
    190   %4 = zext i16 %3 to i64
    191   ret i64 %4
    192 }
    193 
    194 define i64 @load_unscaled_zext_i32_to_i64(i64 %a) {
    195 ; CHECK-LABEL: load_unscaled_zext_i32_to_i64
    196 ; CHECK:       ldur w0, [x0, #-8]
    197 ; CHECK-NOT:   uxtw
    198   %1 = sub i64 %a, 8
    199   %2 = inttoptr i64 %1 to i32*
    200   %3 = load i32, i32* %2
    201   %4 = zext i32 %3 to i64
    202   ret i64 %4
    203 }
    204 
    205 define i32 @load_unscaled_sext_i8_to_i32(i64 %a) {
    206 ; CHECK-LABEL: load_unscaled_sext_i8_to_i32
    207 ; CHECK:       ldursb w0, [x0, #-8]
    208 ; CHECK-NOT:   sxtb
    209   %1 = sub i64 %a, 8
    210   %2 = inttoptr i64 %1 to i8*
    211   %3 = load i8, i8* %2
    212   %4 = sext i8 %3 to i32
    213   ret i32 %4
    214 }
    215 
    216 define i32 @load_unscaled_sext_i16_to_i32(i64 %a) {
    217 ; CHECK-LABEL: load_unscaled_sext_i16_to_i32
    218 ; CHECK:       ldursh w0, [x0, #-8]
    219 ; CHECK-NOT:   sxth
    220   %1 = sub i64 %a, 8
    221   %2 = inttoptr i64 %1 to i16*
    222   %3 = load i16, i16* %2
    223   %4 = sext i16 %3 to i32
    224   ret i32 %4
    225 }
    226 
    227 define i64 @load_unscaled_sext_i8_to_i64(i64 %a) {
    228 ; CHECK-LABEL: load_unscaled_sext_i8_to_i64
    229 ; CHECK:       ldursb x0, [x0, #-8]
    230 ; CHECK-NOT:   sxtb
    231   %1 = sub i64 %a, 8
    232   %2 = inttoptr i64 %1 to i8*
    233   %3 = load i8, i8* %2
    234   %4 = sext i8 %3 to i64
    235   ret i64 %4
    236 }
    237 
    238 define i64 @load_unscaled_sext_i16_to_i64(i64 %a) {
    239 ; CHECK-LABEL: load_unscaled_sext_i16_to_i64
    240 ; CHECK:       ldursh x0, [x0, #-8]
    241 ; CHECK-NOT:   sxth
    242   %1 = sub i64 %a, 8
    243   %2 = inttoptr i64 %1 to i16*
    244   %3 = load i16, i16* %2
    245   %4 = sext i16 %3 to i64
    246   ret i64 %4
    247 }
    248 
    249 define i64 @load_unscaled_sext_i32_to_i64(i64 %a) {
    250 ; CHECK-LABEL: load_unscaled_sext_i32_to_i64
    251 ; CHECK:       ldursw x0, [x0, #-8]
    252 ; CHECK-NOT:   sxtw
    253   %1 = sub i64 %a, 8
    254   %2 = inttoptr i64 %1 to i32*
    255   %3 = load i32, i32* %2
    256   %4 = sext i32 %3 to i64
    257   ret i64 %4
    258 }
    259 
    260 ; Register
    261 define i32 @load_register_zext_i8_to_i32(i64 %a, i64 %b) {
    262 ; CHECK-LABEL: load_register_zext_i8_to_i32
    263 ; CHECK:       ldrb w0, [x0, x1]
    264 ; CHECK-NOT:   uxtb
    265   %1 = add i64 %a, %b
    266   %2 = inttoptr i64 %1 to i8*
    267   %3 = load i8, i8* %2
    268   %4 = zext i8 %3 to i32
    269   ret i32 %4
    270 }
    271 
    272 define i32 @load_register_zext_i16_to_i32(i64 %a, i64 %b) {
    273 ; CHECK-LABEL: load_register_zext_i16_to_i32
    274 ; CHECK:       ldrh w0, [x0, x1]
    275 ; CHECK-NOT:   uxth
    276   %1 = add i64 %a, %b
    277   %2 = inttoptr i64 %1 to i16*
    278   %3 = load i16, i16* %2
    279   %4 = zext i16 %3 to i32
    280   ret i32 %4
    281 }
    282 
    283 define i64 @load_register_zext_i8_to_i64(i64 %a, i64 %b) {
    284 ; CHECK-LABEL: load_register_zext_i8_to_i64
    285 ; CHECK:       ldrb w0, [x0, x1]
    286 ; CHECK-NOT:   uxtb
    287   %1 = add i64 %a, %b
    288   %2 = inttoptr i64 %1 to i8*
    289   %3 = load i8, i8* %2
    290   %4 = zext i8 %3 to i64
    291   ret i64 %4
    292 }
    293 
    294 define i64 @load_register_zext_i16_to_i64(i64 %a, i64 %b) {
    295 ; CHECK-LABEL: load_register_zext_i16_to_i64
    296 ; CHECK:       ldrh w0, [x0, x1]
    297 ; CHECK-NOT:   uxth
    298   %1 = add i64 %a, %b
    299   %2 = inttoptr i64 %1 to i16*
    300   %3 = load i16, i16* %2
    301   %4 = zext i16 %3 to i64
    302   ret i64 %4
    303 }
    304 
    305 define i64 @load_register_zext_i32_to_i64(i64 %a, i64 %b) {
    306 ; CHECK-LABEL: load_register_zext_i32_to_i64
    307 ; CHECK:       ldr w0, [x0, x1]
    308 ; CHECK-NOT:   uxtw
    309   %1 = add i64 %a, %b
    310   %2 = inttoptr i64 %1 to i32*
    311   %3 = load i32, i32* %2
    312   %4 = zext i32 %3 to i64
    313   ret i64 %4
    314 }
    315 
    316 define i32 @load_register_sext_i8_to_i32(i64 %a, i64 %b) {
    317 ; CHECK-LABEL: load_register_sext_i8_to_i32
    318 ; CHECK:       ldrsb w0, [x0, x1]
    319 ; CHECK-NOT:   sxtb
    320   %1 = add i64 %a, %b
    321   %2 = inttoptr i64 %1 to i8*
    322   %3 = load i8, i8* %2
    323   %4 = sext i8 %3 to i32
    324   ret i32 %4
    325 }
    326 
    327 define i32 @load_register_sext_i16_to_i32(i64 %a, i64 %b) {
    328 ; CHECK-LABEL: load_register_sext_i16_to_i32
    329 ; CHECK:       ldrsh w0, [x0, x1]
    330 ; CHECK-NOT:   sxth
    331   %1 = add i64 %a, %b
    332   %2 = inttoptr i64 %1 to i16*
    333   %3 = load i16, i16* %2
    334   %4 = sext i16 %3 to i32
    335   ret i32 %4
    336 }
    337 
    338 define i64 @load_register_sext_i8_to_i64(i64 %a, i64 %b) {
    339 ; CHECK-LABEL: load_register_sext_i8_to_i64
    340 ; CHECK:       ldrsb x0, [x0, x1]
    341 ; CHECK-NOT:   sxtb
    342   %1 = add i64 %a, %b
    343   %2 = inttoptr i64 %1 to i8*
    344   %3 = load i8, i8* %2
    345   %4 = sext i8 %3 to i64
    346   ret i64 %4
    347 }
    348 
    349 define i64 @load_register_sext_i16_to_i64(i64 %a, i64 %b) {
    350 ; CHECK-LABEL: load_register_sext_i16_to_i64
    351 ; CHECK:       ldrsh x0, [x0, x1]
    352 ; CHECK-NOT:   sxth
    353   %1 = add i64 %a, %b
    354   %2 = inttoptr i64 %1 to i16*
    355   %3 = load i16, i16* %2
    356   %4 = sext i16 %3 to i64
    357   ret i64 %4
    358 }
    359 
    360 define i64 @load_register_sext_i32_to_i64(i64 %a, i64 %b) {
    361 ; CHECK-LABEL: load_register_sext_i32_to_i64
    362 ; CHECK:       ldrsw x0, [x0, x1]
    363 ; CHECK-NOT:   sxtw
    364   %1 = add i64 %a, %b
    365   %2 = inttoptr i64 %1 to i32*
    366   %3 = load i32, i32* %2
    367   %4 = sext i32 %3 to i64
    368   ret i64 %4
    369 }
    370 
    371 ; Extend
    372 define i32 @load_extend_zext_i8_to_i32(i64 %a, i32 %b) {
    373 ; CHECK-LABEL: load_extend_zext_i8_to_i32
    374 ; CHECK:       ldrb w0, [x0, w1, sxtw]
    375 ; CHECK-NOT:   uxtb
    376   %1 = sext i32 %b to i64
    377   %2 = add i64 %a, %1
    378   %3 = inttoptr i64 %2 to i8*
    379   %4 = load i8, i8* %3
    380   %5 = zext i8 %4 to i32
    381   ret i32 %5
    382 }
    383 
    384 define i32 @load_extend_zext_i16_to_i32(i64 %a, i32 %b) {
    385 ; CHECK-LABEL: load_extend_zext_i16_to_i32
    386 ; CHECK:       ldrh w0, [x0, w1, sxtw]
    387 ; CHECK-NOT:   uxth
    388   %1 = sext i32 %b to i64
    389   %2 = add i64 %a, %1
    390   %3 = inttoptr i64 %2 to i16*
    391   %4 = load i16, i16* %3
    392   %5 = zext i16 %4 to i32
    393   ret i32 %5
    394 }
    395 
    396 define i64 @load_extend_zext_i8_to_i64(i64 %a, i32 %b) {
    397 ; CHECK-LABEL: load_extend_zext_i8_to_i64
    398 ; CHECK:       ldrb w0, [x0, w1, sxtw]
    399 ; CHECK-NOT:   uxtb
    400   %1 = sext i32 %b to i64
    401   %2 = add i64 %a, %1
    402   %3 = inttoptr i64 %2 to i8*
    403   %4 = load i8, i8* %3
    404   %5 = zext i8 %4 to i64
    405   ret i64 %5
    406 }
    407 
    408 define i64 @load_extend_zext_i16_to_i64(i64 %a, i32 %b) {
    409 ; CHECK-LABEL: load_extend_zext_i16_to_i64
    410 ; CHECK:       ldrh w0, [x0, w1, sxtw]
    411 ; CHECK-NOT:   uxth
    412   %1 = sext i32 %b to i64
    413   %2 = add i64 %a, %1
    414   %3 = inttoptr i64 %2 to i16*
    415   %4 = load i16, i16* %3
    416   %5 = zext i16 %4 to i64
    417   ret i64 %5
    418 }
    419 
    420 define i64 @load_extend_zext_i32_to_i64(i64 %a, i32 %b) {
    421 ; CHECK-LABEL: load_extend_zext_i32_to_i64
    422 ; CHECK:       ldr w0, [x0, w1, sxtw]
    423 ; CHECK-NOT:   uxtw
    424   %1 = sext i32 %b to i64
    425   %2 = add i64 %a, %1
    426   %3 = inttoptr i64 %2 to i32*
    427   %4 = load i32, i32* %3
    428   %5 = zext i32 %4 to i64
    429   ret i64 %5
    430 }
    431 
    432 define i32 @load_extend_sext_i8_to_i32(i64 %a, i32 %b) {
    433 ; CHECK-LABEL: load_extend_sext_i8_to_i32
    434 ; CHECK:       ldrsb w0, [x0, w1, sxtw]
    435 ; CHECK-NOT:   sxtb
    436   %1 = sext i32 %b to i64
    437   %2 = add i64 %a, %1
    438   %3 = inttoptr i64 %2 to i8*
    439   %4 = load i8, i8* %3
    440   %5 = sext i8 %4 to i32
    441   ret i32 %5
    442 }
    443 
    444 define i32 @load_extend_sext_i16_to_i32(i64 %a, i32 %b) {
    445 ; CHECK-LABEL: load_extend_sext_i16_to_i32
    446 ; CHECK:       ldrsh w0, [x0, w1, sxtw]
    447 ; CHECK-NOT:   sxth
    448   %1 = sext i32 %b to i64
    449   %2 = add i64 %a, %1
    450   %3 = inttoptr i64 %2 to i16*
    451   %4 = load i16, i16* %3
    452   %5 = sext i16 %4 to i32
    453   ret i32 %5
    454 }
    455 
    456 define i64 @load_extend_sext_i8_to_i64(i64 %a, i32 %b) {
    457 ; CHECK-LABEL: load_extend_sext_i8_to_i64
    458 ; CHECK:       ldrsb x0, [x0, w1, sxtw]
    459 ; CHECK-NOT:   sxtb
    460   %1 = sext i32 %b to i64
    461   %2 = add i64 %a, %1
    462   %3 = inttoptr i64 %2 to i8*
    463   %4 = load i8, i8* %3
    464   %5 = sext i8 %4 to i64
    465   ret i64 %5
    466 }
    467 
    468 define i64 @load_extend_sext_i16_to_i64(i64 %a, i32 %b) {
    469 ; CHECK-LABEL: load_extend_sext_i16_to_i64
    470 ; CHECK:       ldrsh x0, [x0, w1, sxtw]
    471 ; CHECK-NOT:   sxth
    472   %1 = sext i32 %b to i64
    473   %2 = add i64 %a, %1
    474   %3 = inttoptr i64 %2 to i16*
    475   %4 = load i16, i16* %3
    476   %5 = sext i16 %4 to i64
    477   ret i64 %5
    478 }
    479 
    480 define i64 @load_extend_sext_i32_to_i64(i64 %a, i32 %b) {
    481 ; CHECK-LABEL: load_extend_sext_i32_to_i64
    482 ; CHECK:       ldrsw x0, [x0, w1, sxtw]
    483 ; CHECK-NOT:   sxtw
    484   %1 = sext i32 %b to i64
    485   %2 = add i64 %a, %1
    486   %3 = inttoptr i64 %2 to i32*
    487   %4 = load i32, i32* %3
    488   %5 = sext i32 %4 to i64
    489   ret i64 %5
    490 }
    491 
    492