Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -verify-machineinstrs -o - %s -mtriple=aarch64-linux-gnu | FileCheck %s
      2 ; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -mattr=-fp-armv8 | FileCheck --check-prefix=CHECK-NOFP %s
      3 
      4 @var_8bit = global i8 0
      5 @var_16bit = global i16 0
      6 @var_32bit = global i32 0
      7 @var_64bit = global i64 0
      8 
      9 @var_float = global float 0.0
     10 @var_double = global double 0.0
     11 
     12 @varptr = global i8* null
     13 
     14 define void @ldst_8bit() {
     15 ; CHECK-LABEL: ldst_8bit:
     16 
     17 ; No architectural support for loads to 16-bit or 8-bit since we
     18 ; promote i8 during lowering.
     19   %addr_8bit = load i8*, i8** @varptr
     20 
     21 ; match a sign-extending load 8-bit -> 32-bit
     22    %addr_sext32 = getelementptr i8, i8* %addr_8bit, i64 -256
     23    %val8_sext32 = load volatile i8, i8* %addr_sext32
     24    %val32_signed = sext i8 %val8_sext32 to i32
     25    store volatile i32 %val32_signed, i32* @var_32bit
     26 ; CHECK: ldursb {{w[0-9]+}}, [{{x[0-9]+}}, #-256]
     27 
     28 ; match a zero-extending load volatile 8-bit -> 32-bit
     29   %addr_zext32 = getelementptr i8, i8* %addr_8bit, i64 -12
     30   %val8_zext32 = load volatile i8, i8* %addr_zext32
     31   %val32_unsigned = zext i8 %val8_zext32 to i32
     32   store volatile i32 %val32_unsigned, i32* @var_32bit
     33 ; CHECK: ldurb {{w[0-9]+}}, [{{x[0-9]+}}, #-12]
     34 
     35 ; match an any-extending load volatile 8-bit -> 32-bit
     36   %addr_anyext = getelementptr i8, i8* %addr_8bit, i64 -1
     37   %val8_anyext = load volatile i8, i8* %addr_anyext
     38   %newval8 = add i8 %val8_anyext, 1
     39   store volatile i8 %newval8, i8* @var_8bit
     40 ; CHECK: ldurb {{w[0-9]+}}, [{{x[0-9]+}}, #-1]
     41 
     42 ; match a sign-extending load volatile 8-bit -> 64-bit
     43   %addr_sext64 = getelementptr i8, i8* %addr_8bit, i64 -5
     44   %val8_sext64 = load volatile i8, i8* %addr_sext64
     45   %val64_signed = sext i8 %val8_sext64 to i64
     46   store volatile i64 %val64_signed, i64* @var_64bit
     47 ; CHECK: ldursb {{x[0-9]+}}, [{{x[0-9]+}}, #-5]
     48 
     49 ; match a zero-extending load volatile 8-bit -> 64-bit.
     50 ; This uses the fact that ldrb w0, [x0] will zero out the high 32-bits
     51 ; of x0 so it's identical to load volatileing to 32-bits.
     52   %addr_zext64 = getelementptr i8, i8* %addr_8bit, i64 -9
     53   %val8_zext64 = load volatile i8, i8* %addr_zext64
     54   %val64_unsigned = zext i8 %val8_zext64 to i64
     55   store volatile i64 %val64_unsigned, i64* @var_64bit
     56 ; CHECK: ldurb {{w[0-9]+}}, [{{x[0-9]+}}, #-9]
     57 
     58 ; truncating store volatile 32-bits to 8-bits
     59   %addr_trunc32 = getelementptr i8, i8* %addr_8bit, i64 -256
     60   %val32 = load volatile i32, i32* @var_32bit
     61   %val8_trunc32 = trunc i32 %val32 to i8
     62   store volatile i8 %val8_trunc32, i8* %addr_trunc32
     63 ; CHECK: sturb {{w[0-9]+}}, [{{x[0-9]+}}, #-256]
     64 
     65 ; truncating store volatile 64-bits to 8-bits
     66   %addr_trunc64 = getelementptr i8, i8* %addr_8bit, i64 -1
     67   %val64 = load volatile i64, i64* @var_64bit
     68   %val8_trunc64 = trunc i64 %val64 to i8
     69   store volatile i8 %val8_trunc64, i8* %addr_trunc64
     70 ; CHECK: sturb {{w[0-9]+}}, [{{x[0-9]+}}, #-1]
     71 
     72    ret void
     73 }
     74 
     75 define void @ldst_16bit() {
     76 ; CHECK-LABEL: ldst_16bit:
     77 
     78 ; No architectural support for loads to 16-bit or 16-bit since we
     79 ; promote i16 during lowering.
     80   %addr_8bit = load i8*, i8** @varptr
     81 
     82 ; match a sign-extending load 16-bit -> 32-bit
     83    %addr8_sext32 = getelementptr i8, i8* %addr_8bit, i64 -256
     84    %addr_sext32 = bitcast i8* %addr8_sext32 to i16*
     85    %val16_sext32 = load volatile i16, i16* %addr_sext32
     86    %val32_signed = sext i16 %val16_sext32 to i32
     87    store volatile i32 %val32_signed, i32* @var_32bit
     88 ; CHECK: ldursh {{w[0-9]+}}, [{{x[0-9]+}}, #-256]
     89 
     90 ; match a zero-extending load volatile 16-bit -> 32-bit. With offset that would be unaligned.
     91   %addr8_zext32 = getelementptr i8, i8* %addr_8bit, i64 15
     92   %addr_zext32 = bitcast i8* %addr8_zext32 to i16*
     93   %val16_zext32 = load volatile i16, i16* %addr_zext32
     94   %val32_unsigned = zext i16 %val16_zext32 to i32
     95   store volatile i32 %val32_unsigned, i32* @var_32bit
     96 ; CHECK: ldurh {{w[0-9]+}}, [{{x[0-9]+}}, #15]
     97 
     98 ; match an any-extending load volatile 16-bit -> 32-bit
     99   %addr8_anyext = getelementptr i8, i8* %addr_8bit, i64 -1
    100   %addr_anyext = bitcast i8* %addr8_anyext to i16*
    101   %val16_anyext = load volatile i16, i16* %addr_anyext
    102   %newval16 = add i16 %val16_anyext, 1
    103   store volatile i16 %newval16, i16* @var_16bit
    104 ; CHECK: ldurh {{w[0-9]+}}, [{{x[0-9]+}}, #-1]
    105 
    106 ; match a sign-extending load volatile 16-bit -> 64-bit
    107   %addr8_sext64 = getelementptr i8, i8* %addr_8bit, i64 -5
    108   %addr_sext64 = bitcast i8* %addr8_sext64 to i16*
    109   %val16_sext64 = load volatile i16, i16* %addr_sext64
    110   %val64_signed = sext i16 %val16_sext64 to i64
    111   store volatile i64 %val64_signed, i64* @var_64bit
    112 ; CHECK: ldursh {{x[0-9]+}}, [{{x[0-9]+}}, #-5]
    113 
    114 ; match a zero-extending load volatile 16-bit -> 64-bit.
    115 ; This uses the fact that ldrb w0, [x0] will zero out the high 32-bits
    116 ; of x0 so it's identical to load volatileing to 32-bits.
    117   %addr8_zext64 = getelementptr i8, i8* %addr_8bit, i64 9
    118   %addr_zext64 = bitcast i8* %addr8_zext64 to i16*
    119   %val16_zext64 = load volatile i16, i16* %addr_zext64
    120   %val64_unsigned = zext i16 %val16_zext64 to i64
    121   store volatile i64 %val64_unsigned, i64* @var_64bit
    122 ; CHECK: ldurh {{w[0-9]+}}, [{{x[0-9]+}}, #9]
    123 
    124 ; truncating store volatile 32-bits to 16-bits
    125   %addr8_trunc32 = getelementptr i8, i8* %addr_8bit, i64 -256
    126   %addr_trunc32 = bitcast i8* %addr8_trunc32 to i16*
    127   %val32 = load volatile i32, i32* @var_32bit
    128   %val16_trunc32 = trunc i32 %val32 to i16
    129   store volatile i16 %val16_trunc32, i16* %addr_trunc32
    130 ; CHECK: sturh {{w[0-9]+}}, [{{x[0-9]+}}, #-256]
    131 
    132 ; truncating store volatile 64-bits to 16-bits
    133   %addr8_trunc64 = getelementptr i8, i8* %addr_8bit, i64 -1
    134   %addr_trunc64 = bitcast i8* %addr8_trunc64 to i16*
    135   %val64 = load volatile i64, i64* @var_64bit
    136   %val16_trunc64 = trunc i64 %val64 to i16
    137   store volatile i16 %val16_trunc64, i16* %addr_trunc64
    138 ; CHECK: sturh {{w[0-9]+}}, [{{x[0-9]+}}, #-1]
    139 
    140    ret void
    141 }
    142 
    143 define void @ldst_32bit() {
    144 ; CHECK-LABEL: ldst_32bit:
    145 
    146   %addr_8bit = load i8*, i8** @varptr
    147 
    148 ; Straight 32-bit load/store
    149   %addr32_8_noext = getelementptr i8, i8* %addr_8bit, i64 1
    150   %addr32_noext = bitcast i8* %addr32_8_noext to i32*
    151   %val32_noext = load volatile i32, i32* %addr32_noext
    152   store volatile i32 %val32_noext, i32* %addr32_noext
    153 ; CHECK: ldur {{w[0-9]+}}, [{{x[0-9]+}}, #1]
    154 ; CHECK: stur {{w[0-9]+}}, [{{x[0-9]+}}, #1]
    155 
    156 ; Zero-extension to 64-bits
    157   %addr32_8_zext = getelementptr i8, i8* %addr_8bit, i64 -256
    158   %addr32_zext = bitcast i8* %addr32_8_zext to i32*
    159   %val32_zext = load volatile i32, i32* %addr32_zext
    160   %val64_unsigned = zext i32 %val32_zext to i64
    161   store volatile i64 %val64_unsigned, i64* @var_64bit
    162 ; CHECK: ldur {{w[0-9]+}}, [{{x[0-9]+}}, #-256]
    163 ; CHECK: str {{x[0-9]+}}, [{{x[0-9]+}}, {{#?}}:lo12:var_64bit]
    164 
    165 ; Sign-extension to 64-bits
    166   %addr32_8_sext = getelementptr i8, i8* %addr_8bit, i64 -12
    167   %addr32_sext = bitcast i8* %addr32_8_sext to i32*
    168   %val32_sext = load volatile i32, i32* %addr32_sext
    169   %val64_signed = sext i32 %val32_sext to i64
    170   store volatile i64 %val64_signed, i64* @var_64bit
    171 ; CHECK: ldursw {{x[0-9]+}}, [{{x[0-9]+}}, #-12]
    172 ; CHECK: str {{x[0-9]+}}, [{{x[0-9]+}}, {{#?}}:lo12:var_64bit]
    173 
    174 ; Truncation from 64-bits
    175   %addr64_8_trunc = getelementptr i8, i8* %addr_8bit, i64 255
    176   %addr64_trunc = bitcast i8* %addr64_8_trunc to i64*
    177   %addr32_8_trunc = getelementptr i8, i8* %addr_8bit, i64 -20
    178   %addr32_trunc = bitcast i8* %addr32_8_trunc to i32*
    179 
    180   %val64_trunc = load volatile i64, i64* %addr64_trunc
    181   %val32_trunc = trunc i64 %val64_trunc to i32
    182   store volatile i32 %val32_trunc, i32* %addr32_trunc
    183 ; CHECK: ldur {{x[0-9]+}}, [{{x[0-9]+}}, #255]
    184 ; CHECK: stur {{w[0-9]+}}, [{{x[0-9]+}}, #-20]
    185 
    186   ret void
    187 }
    188 
    189 define void @ldst_float() {
    190 ; CHECK-LABEL: ldst_float:
    191 
    192   %addr_8bit = load i8*, i8** @varptr
    193   %addrfp_8 = getelementptr i8, i8* %addr_8bit, i64 -5
    194   %addrfp = bitcast i8* %addrfp_8 to float*
    195 
    196   %valfp = load volatile float, float* %addrfp
    197 ; CHECK: ldur {{s[0-9]+}}, [{{x[0-9]+}}, #-5]
    198 ; CHECK-NOFP-NOT: ldur {{s[0-9]+}},
    199 
    200   store volatile float %valfp, float* %addrfp
    201 ; CHECK: stur {{s[0-9]+}}, [{{x[0-9]+}}, #-5]
    202 ; CHECK-NOFP-NOT: stur {{s[0-9]+}},
    203 
    204   ret void
    205 }
    206 
    207 define void @ldst_double() {
    208 ; CHECK-LABEL: ldst_double:
    209 
    210   %addr_8bit = load i8*, i8** @varptr
    211   %addrfp_8 = getelementptr i8, i8* %addr_8bit, i64 4
    212   %addrfp = bitcast i8* %addrfp_8 to double*
    213 
    214   %valfp = load volatile double, double* %addrfp
    215 ; CHECK: ldur {{d[0-9]+}}, [{{x[0-9]+}}, #4]
    216 ; CHECK-NOFP-NOT: ldur {{d[0-9]+}},
    217 
    218   store volatile double %valfp, double* %addrfp
    219 ; CHECK: stur {{d[0-9]+}}, [{{x[0-9]+}}, #4]
    220 ; CHECK-NOFP-NOT: stur {{d[0-9]+}},
    221 
    222    ret void
    223 }
    224