Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s
      2 
      3 @var_8bit = global i8 0
      4 @var_16bit = global i16 0
      5 @var_32bit = global i32 0
      6 @var_64bit = global i64 0
      7 
      8 @var_float = global float 0.0
      9 @var_double = global double 0.0
     10 
     11 define void @ldst_8bit() {
     12 ; CHECK: ldst_8bit:
     13 
     14 ; No architectural support for loads to 16-bit or 8-bit since we
     15 ; promote i8 during lowering.
     16 
     17 ; match a sign-extending load 8-bit -> 32-bit
     18    %val8_sext32 = load volatile i8* @var_8bit
     19    %val32_signed = sext i8 %val8_sext32 to i32
     20    store volatile i32 %val32_signed, i32* @var_32bit
     21 ; CHECK: adrp {{x[0-9]+}}, var_8bit
     22 ; CHECK: ldrsb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
     23 
     24 ; match a zero-extending load volatile 8-bit -> 32-bit
     25   %val8_zext32 = load volatile i8* @var_8bit
     26   %val32_unsigned = zext i8 %val8_zext32 to i32
     27   store volatile i32 %val32_unsigned, i32* @var_32bit
     28 ; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
     29 
     30 ; match an any-extending load volatile 8-bit -> 32-bit
     31   %val8_anyext = load volatile i8* @var_8bit
     32   %newval8 = add i8 %val8_anyext, 1
     33   store volatile i8 %newval8, i8* @var_8bit
     34 ; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
     35 
     36 ; match a sign-extending load volatile 8-bit -> 64-bit
     37   %val8_sext64 = load volatile i8* @var_8bit
     38   %val64_signed = sext i8 %val8_sext64 to i64
     39   store volatile i64 %val64_signed, i64* @var_64bit
     40 ; CHECK: ldrsb {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
     41 
     42 ; match a zero-extending load volatile 8-bit -> 64-bit.
     43 ; This uses the fact that ldrb w0, [x0] will zero out the high 32-bits
     44 ; of x0 so it's identical to load volatileing to 32-bits.
     45   %val8_zext64 = load volatile i8* @var_8bit
     46   %val64_unsigned = zext i8 %val8_zext64 to i64
     47   store volatile i64 %val64_unsigned, i64* @var_64bit
     48 ; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
     49 
     50 ; truncating store volatile 32-bits to 8-bits
     51   %val32 = load volatile i32* @var_32bit
     52   %val8_trunc32 = trunc i32 %val32 to i8
     53   store volatile i8 %val8_trunc32, i8* @var_8bit
     54 ; CHECK: strb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
     55 
     56 ; truncating store volatile 64-bits to 8-bits
     57   %val64 = load volatile i64* @var_64bit
     58   %val8_trunc64 = trunc i64 %val64 to i8
     59   store volatile i8 %val8_trunc64, i8* @var_8bit
     60 ; CHECK: strb {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_8bit]
     61 
     62    ret void
     63 }
     64 
     65 define void @ldst_16bit() {
     66 ; CHECK: ldst_16bit:
     67 
     68 ; No architectural support for load volatiles to 16-bit promote i16 during
     69 ; lowering.
     70 
     71 ; match a sign-extending load volatile 16-bit -> 32-bit
     72   %val16_sext32 = load volatile i16* @var_16bit
     73   %val32_signed = sext i16 %val16_sext32 to i32
     74   store volatile i32 %val32_signed, i32* @var_32bit
     75 ; CHECK: adrp {{x[0-9]+}}, var_16bit
     76 ; CHECK: ldrsh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
     77 
     78 ; match a zero-extending load volatile 16-bit -> 32-bit
     79   %val16_zext32 = load volatile i16* @var_16bit
     80   %val32_unsigned = zext i16 %val16_zext32 to i32
     81   store volatile i32 %val32_unsigned, i32* @var_32bit
     82 ; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
     83 
     84 ; match an any-extending load volatile 16-bit -> 32-bit
     85   %val16_anyext = load volatile i16* @var_16bit
     86   %newval16 = add i16 %val16_anyext, 1
     87   store volatile i16 %newval16, i16* @var_16bit
     88 ; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
     89 
     90 ; match a sign-extending load volatile 16-bit -> 64-bit
     91   %val16_sext64 = load volatile i16* @var_16bit
     92   %val64_signed = sext i16 %val16_sext64 to i64
     93   store volatile i64 %val64_signed, i64* @var_64bit
     94 ; CHECK: ldrsh {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
     95 
     96 ; match a zero-extending load volatile 16-bit -> 64-bit.
     97 ; This uses the fact that ldrb w0, [x0] will zero out the high 32-bits
     98 ; of x0 so it's identical to load volatileing to 32-bits.
     99   %val16_zext64 = load volatile i16* @var_16bit
    100   %val64_unsigned = zext i16 %val16_zext64 to i64
    101   store volatile i64 %val64_unsigned, i64* @var_64bit
    102 ; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
    103 
    104 ; truncating store volatile 32-bits to 16-bits
    105   %val32 = load volatile i32* @var_32bit
    106   %val16_trunc32 = trunc i32 %val32 to i16
    107   store volatile i16 %val16_trunc32, i16* @var_16bit
    108 ; CHECK: strh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
    109 
    110 ; truncating store volatile 64-bits to 16-bits
    111   %val64 = load volatile i64* @var_64bit
    112   %val16_trunc64 = trunc i64 %val64 to i16
    113   store volatile i16 %val16_trunc64, i16* @var_16bit
    114 ; CHECK: strh {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_16bit]
    115 
    116   ret void
    117 }
    118 
    119 define void @ldst_32bit() {
    120 ; CHECK: ldst_32bit:
    121 
    122 ; Straight 32-bit load/store
    123   %val32_noext = load volatile i32* @var_32bit
    124   store volatile i32 %val32_noext, i32* @var_32bit
    125 ; CHECK: adrp {{x[0-9]+}}, var_32bit
    126 ; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
    127 ; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
    128 
    129 ; Zero-extension to 64-bits
    130   %val32_zext = load volatile i32* @var_32bit
    131   %val64_unsigned = zext i32 %val32_zext to i64
    132   store volatile i64 %val64_unsigned, i64* @var_64bit
    133 ; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
    134 ; CHECK: str {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_64bit]
    135 
    136 ; Sign-extension to 64-bits
    137   %val32_sext = load volatile i32* @var_32bit
    138   %val64_signed = sext i32 %val32_sext to i64
    139   store volatile i64 %val64_signed, i64* @var_64bit
    140 ; CHECK: ldrsw {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
    141 ; CHECK: str {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_64bit]
    142 
    143 ; Truncation from 64-bits
    144   %val64_trunc = load volatile i64* @var_64bit
    145   %val32_trunc = trunc i64 %val64_trunc to i32
    146   store volatile i32 %val32_trunc, i32* @var_32bit
    147 ; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_64bit]
    148 ; CHECK: str {{w[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_32bit]
    149 
    150   ret void
    151 }
    152 
    153 @arr8 = global i8* null
    154 @arr16 = global i16* null
    155 @arr32 = global i32* null
    156 @arr64 = global i64* null
    157 
    158 ; Now check that our selection copes with accesses more complex than a
    159 ; single symbol. Permitted offsets should be folded into the loads and
    160 ; stores. Since all forms use the same Operand it's only necessary to
    161 ; check the various access-sizes involved.
    162 
    163 define void @ldst_complex_offsets() {
    164 ; CHECK: ldst_complex_offsets
    165   %arr8_addr = load volatile i8** @arr8
    166 ; CHECK: adrp {{x[0-9]+}}, arr8
    167 ; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:arr8]
    168 
    169   %arr8_sub1_addr = getelementptr i8* %arr8_addr, i64 1
    170   %arr8_sub1 = load volatile i8* %arr8_sub1_addr
    171   store volatile i8 %arr8_sub1, i8* @var_8bit
    172 ; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #1]
    173 
    174   %arr8_sub4095_addr = getelementptr i8* %arr8_addr, i64 4095
    175   %arr8_sub4095 = load volatile i8* %arr8_sub4095_addr
    176   store volatile i8 %arr8_sub4095, i8* @var_8bit
    177 ; CHECK: ldrb {{w[0-9]+}}, [{{x[0-9]+}}, #4095]
    178 
    179 
    180   %arr16_addr = load volatile i16** @arr16
    181 ; CHECK: adrp {{x[0-9]+}}, arr16
    182 ; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:arr16]
    183 
    184   %arr16_sub1_addr = getelementptr i16* %arr16_addr, i64 1
    185   %arr16_sub1 = load volatile i16* %arr16_sub1_addr
    186   store volatile i16 %arr16_sub1, i16* @var_16bit
    187 ; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #2]
    188 
    189   %arr16_sub4095_addr = getelementptr i16* %arr16_addr, i64 4095
    190   %arr16_sub4095 = load volatile i16* %arr16_sub4095_addr
    191   store volatile i16 %arr16_sub4095, i16* @var_16bit
    192 ; CHECK: ldrh {{w[0-9]+}}, [{{x[0-9]+}}, #8190]
    193 
    194 
    195   %arr32_addr = load volatile i32** @arr32
    196 ; CHECK: adrp {{x[0-9]+}}, arr32
    197 ; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:arr32]
    198 
    199   %arr32_sub1_addr = getelementptr i32* %arr32_addr, i64 1
    200   %arr32_sub1 = load volatile i32* %arr32_sub1_addr
    201   store volatile i32 %arr32_sub1, i32* @var_32bit
    202 ; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}, #4]
    203 
    204   %arr32_sub4095_addr = getelementptr i32* %arr32_addr, i64 4095
    205   %arr32_sub4095 = load volatile i32* %arr32_sub4095_addr
    206   store volatile i32 %arr32_sub4095, i32* @var_32bit
    207 ; CHECK: ldr {{w[0-9]+}}, [{{x[0-9]+}}, #16380]
    208 
    209 
    210   %arr64_addr = load volatile i64** @arr64
    211 ; CHECK: adrp {{x[0-9]+}}, arr64
    212 ; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #:lo12:arr64]
    213 
    214   %arr64_sub1_addr = getelementptr i64* %arr64_addr, i64 1
    215   %arr64_sub1 = load volatile i64* %arr64_sub1_addr
    216   store volatile i64 %arr64_sub1, i64* @var_64bit
    217 ; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #8]
    218 
    219   %arr64_sub4095_addr = getelementptr i64* %arr64_addr, i64 4095
    220   %arr64_sub4095 = load volatile i64* %arr64_sub4095_addr
    221   store volatile i64 %arr64_sub4095, i64* @var_64bit
    222 ; CHECK: ldr {{x[0-9]+}}, [{{x[0-9]+}}, #32760]
    223 
    224   ret void
    225 }
    226 
    227 define void @ldst_float() {
    228 ; CHECK: ldst_float:
    229 
    230    %valfp = load volatile float* @var_float
    231 ; CHECK: adrp {{x[0-9]+}}, var_float
    232 ; CHECK: ldr {{s[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_float]
    233 
    234   store volatile float %valfp, float* @var_float
    235 ; CHECK: str {{s[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_float]
    236 
    237    ret void
    238 }
    239 
    240 define void @ldst_double() {
    241 ; CHECK: ldst_double:
    242 
    243    %valfp = load volatile double* @var_double
    244 ; CHECK: adrp {{x[0-9]+}}, var_double
    245 ; CHECK: ldr {{d[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_double]
    246 
    247   store volatile double %valfp, double* @var_double
    248 ; CHECK: str {{d[0-9]+}}, [{{x[0-9]+}}, #:lo12:var_double]
    249 
    250    ret void
    251 }
    252