Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc < %s -mtriple=arm64-linux-gnu | FileCheck %s
      2 
      3 %0 = type { i64, i64 }
      4 
      5 define i128 @f0(i8* %p) nounwind readonly {
      6 ; CHECK-LABEL: f0:
      7 ; CHECK: ldxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
      8 entry:
      9   %ldrexd = tail call %0 @llvm.aarch64.ldxp(i8* %p)
     10   %0 = extractvalue %0 %ldrexd, 1
     11   %1 = extractvalue %0 %ldrexd, 0
     12   %2 = zext i64 %0 to i128
     13   %3 = zext i64 %1 to i128
     14   %shl = shl nuw i128 %2, 64
     15   %4 = or i128 %shl, %3
     16   ret i128 %4
     17 }
     18 
     19 define i32 @f1(i8* %ptr, i128 %val) nounwind {
     20 ; CHECK-LABEL: f1:
     21 ; CHECK: stxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
     22 entry:
     23   %tmp4 = trunc i128 %val to i64
     24   %tmp6 = lshr i128 %val, 64
     25   %tmp7 = trunc i128 %tmp6 to i64
     26   %strexd = tail call i32 @llvm.aarch64.stxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
     27   ret i32 %strexd
     28 }
     29 
     30 declare %0 @llvm.aarch64.ldxp(i8*) nounwind
     31 declare i32 @llvm.aarch64.stxp(i64, i64, i8*) nounwind
     32 
     33 @var = global i64 0, align 8
     34 
     35 define void @test_load_i8(i8* %addr) {
     36 ; CHECK-LABEL: test_load_i8:
     37 ; CHECK: ldxrb w[[LOADVAL:[0-9]+]], [x0]
     38 ; CHECK-NOT: uxtb
     39 ; CHECK-NOT: and
     40 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
     41 
     42   %val = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
     43   %shortval = trunc i64 %val to i8
     44   %extval = zext i8 %shortval to i64
     45   store i64 %extval, i64* @var, align 8
     46   ret void
     47 }
     48 
     49 define void @test_load_i16(i16* %addr) {
     50 ; CHECK-LABEL: test_load_i16:
     51 ; CHECK: ldxrh w[[LOADVAL:[0-9]+]], [x0]
     52 ; CHECK-NOT: uxth
     53 ; CHECK-NOT: and
     54 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
     55 
     56   %val = call i64 @llvm.aarch64.ldxr.p0i16(i16* %addr)
     57   %shortval = trunc i64 %val to i16
     58   %extval = zext i16 %shortval to i64
     59   store i64 %extval, i64* @var, align 8
     60   ret void
     61 }
     62 
     63 define void @test_load_i32(i32* %addr) {
     64 ; CHECK-LABEL: test_load_i32:
     65 ; CHECK: ldxr w[[LOADVAL:[0-9]+]], [x0]
     66 ; CHECK-NOT: uxtw
     67 ; CHECK-NOT: and
     68 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
     69 
     70   %val = call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
     71   %shortval = trunc i64 %val to i32
     72   %extval = zext i32 %shortval to i64
     73   store i64 %extval, i64* @var, align 8
     74   ret void
     75 }
     76 
     77 define void @test_load_i64(i64* %addr) {
     78 ; CHECK-LABEL: test_load_i64:
     79 ; CHECK: ldxr x[[LOADVAL:[0-9]+]], [x0]
     80 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
     81 
     82   %val = call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr)
     83   store i64 %val, i64* @var, align 8
     84   ret void
     85 }
     86 
     87 
     88 declare i64 @llvm.aarch64.ldxr.p0i8(i8*) nounwind
     89 declare i64 @llvm.aarch64.ldxr.p0i16(i16*) nounwind
     90 declare i64 @llvm.aarch64.ldxr.p0i32(i32*) nounwind
     91 declare i64 @llvm.aarch64.ldxr.p0i64(i64*) nounwind
     92 
     93 define i32 @test_store_i8(i32, i8 %val, i8* %addr) {
     94 ; CHECK-LABEL: test_store_i8:
     95 ; CHECK-NOT: uxtb
     96 ; CHECK-NOT: and
     97 ; CHECK: stxrb w0, w1, [x2]
     98   %extval = zext i8 %val to i64
     99   %res = call i32 @llvm.aarch64.stxr.p0i8(i64 %extval, i8* %addr)
    100   ret i32 %res
    101 }
    102 
    103 define i32 @test_store_i16(i32, i16 %val, i16* %addr) {
    104 ; CHECK-LABEL: test_store_i16:
    105 ; CHECK-NOT: uxth
    106 ; CHECK-NOT: and
    107 ; CHECK: stxrh w0, w1, [x2]
    108   %extval = zext i16 %val to i64
    109   %res = call i32 @llvm.aarch64.stxr.p0i16(i64 %extval, i16* %addr)
    110   ret i32 %res
    111 }
    112 
    113 define i32 @test_store_i32(i32, i32 %val, i32* %addr) {
    114 ; CHECK-LABEL: test_store_i32:
    115 ; CHECK-NOT: uxtw
    116 ; CHECK-NOT: and
    117 ; CHECK: stxr w0, w1, [x2]
    118   %extval = zext i32 %val to i64
    119   %res = call i32 @llvm.aarch64.stxr.p0i32(i64 %extval, i32* %addr)
    120   ret i32 %res
    121 }
    122 
    123 define i32 @test_store_i64(i32, i64 %val, i64* %addr) {
    124 ; CHECK-LABEL: test_store_i64:
    125 ; CHECK: stxr w0, x1, [x2]
    126   %res = call i32 @llvm.aarch64.stxr.p0i64(i64 %val, i64* %addr)
    127   ret i32 %res
    128 }
    129 
    130 declare i32 @llvm.aarch64.stxr.p0i8(i64, i8*) nounwind
    131 declare i32 @llvm.aarch64.stxr.p0i16(i64, i16*) nounwind
    132 declare i32 @llvm.aarch64.stxr.p0i32(i64, i32*) nounwind
    133 declare i32 @llvm.aarch64.stxr.p0i64(i64, i64*) nounwind
    134 
    135 ; CHECK: test_clear:
    136 ; CHECK: clrex
    137 define void @test_clear() {
    138   call void @llvm.aarch64.clrex()
    139   ret void
    140 }
    141 
    142 declare void @llvm.aarch64.clrex() nounwind
    143 
    144 define i128 @test_load_acquire_i128(i8* %p) nounwind readonly {
    145 ; CHECK-LABEL: test_load_acquire_i128:
    146 ; CHECK: ldaxp {{x[0-9]+}}, {{x[0-9]+}}, [x0]
    147 entry:
    148   %ldrexd = tail call %0 @llvm.aarch64.ldaxp(i8* %p)
    149   %0 = extractvalue %0 %ldrexd, 1
    150   %1 = extractvalue %0 %ldrexd, 0
    151   %2 = zext i64 %0 to i128
    152   %3 = zext i64 %1 to i128
    153   %shl = shl nuw i128 %2, 64
    154   %4 = or i128 %shl, %3
    155   ret i128 %4
    156 }
    157 
    158 define i32 @test_store_release_i128(i8* %ptr, i128 %val) nounwind {
    159 ; CHECK-LABEL: test_store_release_i128:
    160 ; CHECK: stlxp {{w[0-9]+}}, {{x[0-9]+}}, {{x[0-9]+}}, [x0]
    161 entry:
    162   %tmp4 = trunc i128 %val to i64
    163   %tmp6 = lshr i128 %val, 64
    164   %tmp7 = trunc i128 %tmp6 to i64
    165   %strexd = tail call i32 @llvm.aarch64.stlxp(i64 %tmp4, i64 %tmp7, i8* %ptr)
    166   ret i32 %strexd
    167 }
    168 
    169 declare %0 @llvm.aarch64.ldaxp(i8*) nounwind
    170 declare i32 @llvm.aarch64.stlxp(i64, i64, i8*) nounwind
    171 
    172 define void @test_load_acquire_i8(i8* %addr) {
    173 ; CHECK-LABEL: test_load_acquire_i8:
    174 ; CHECK: ldaxrb w[[LOADVAL:[0-9]+]], [x0]
    175 ; CHECK-NOT: uxtb
    176 ; CHECK-NOT: and
    177 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
    178 
    179   %val = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
    180   %shortval = trunc i64 %val to i8
    181   %extval = zext i8 %shortval to i64
    182   store i64 %extval, i64* @var, align 8
    183   ret void
    184 }
    185 
    186 define void @test_load_acquire_i16(i16* %addr) {
    187 ; CHECK-LABEL: test_load_acquire_i16:
    188 ; CHECK: ldaxrh w[[LOADVAL:[0-9]+]], [x0]
    189 ; CHECK-NOT: uxth
    190 ; CHECK-NOT: and
    191 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
    192 
    193   %val = call i64 @llvm.aarch64.ldaxr.p0i16(i16* %addr)
    194   %shortval = trunc i64 %val to i16
    195   %extval = zext i16 %shortval to i64
    196   store i64 %extval, i64* @var, align 8
    197   ret void
    198 }
    199 
    200 define void @test_load_acquire_i32(i32* %addr) {
    201 ; CHECK-LABEL: test_load_acquire_i32:
    202 ; CHECK: ldaxr w[[LOADVAL:[0-9]+]], [x0]
    203 ; CHECK-NOT: uxtw
    204 ; CHECK-NOT: and
    205 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
    206 
    207   %val = call i64 @llvm.aarch64.ldaxr.p0i32(i32* %addr)
    208   %shortval = trunc i64 %val to i32
    209   %extval = zext i32 %shortval to i64
    210   store i64 %extval, i64* @var, align 8
    211   ret void
    212 }
    213 
    214 define void @test_load_acquire_i64(i64* %addr) {
    215 ; CHECK-LABEL: test_load_acquire_i64:
    216 ; CHECK: ldaxr x[[LOADVAL:[0-9]+]], [x0]
    217 ; CHECK: str x[[LOADVAL]], [{{x[0-9]+}}, :lo12:var]
    218 
    219   %val = call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr)
    220   store i64 %val, i64* @var, align 8
    221   ret void
    222 }
    223 
    224 
    225 declare i64 @llvm.aarch64.ldaxr.p0i8(i8*) nounwind
    226 declare i64 @llvm.aarch64.ldaxr.p0i16(i16*) nounwind
    227 declare i64 @llvm.aarch64.ldaxr.p0i32(i32*) nounwind
    228 declare i64 @llvm.aarch64.ldaxr.p0i64(i64*) nounwind
    229 
    230 define i32 @test_store_release_i8(i32, i8 %val, i8* %addr) {
    231 ; CHECK-LABEL: test_store_release_i8:
    232 ; CHECK-NOT: uxtb
    233 ; CHECK-NOT: and
    234 ; CHECK: stlxrb w0, w1, [x2]
    235   %extval = zext i8 %val to i64
    236   %res = call i32 @llvm.aarch64.stlxr.p0i8(i64 %extval, i8* %addr)
    237   ret i32 %res
    238 }
    239 
    240 define i32 @test_store_release_i16(i32, i16 %val, i16* %addr) {
    241 ; CHECK-LABEL: test_store_release_i16:
    242 ; CHECK-NOT: uxth
    243 ; CHECK-NOT: and
    244 ; CHECK: stlxrh w0, w1, [x2]
    245   %extval = zext i16 %val to i64
    246   %res = call i32 @llvm.aarch64.stlxr.p0i16(i64 %extval, i16* %addr)
    247   ret i32 %res
    248 }
    249 
    250 define i32 @test_store_release_i32(i32, i32 %val, i32* %addr) {
    251 ; CHECK-LABEL: test_store_release_i32:
    252 ; CHECK-NOT: uxtw
    253 ; CHECK-NOT: and
    254 ; CHECK: stlxr w0, w1, [x2]
    255   %extval = zext i32 %val to i64
    256   %res = call i32 @llvm.aarch64.stlxr.p0i32(i64 %extval, i32* %addr)
    257   ret i32 %res
    258 }
    259 
    260 define i32 @test_store_release_i64(i32, i64 %val, i64* %addr) {
    261 ; CHECK-LABEL: test_store_release_i64:
    262 ; CHECK: stlxr w0, x1, [x2]
    263   %res = call i32 @llvm.aarch64.stlxr.p0i64(i64 %val, i64* %addr)
    264   ret i32 %res
    265 }
    266 
    267 declare i32 @llvm.aarch64.stlxr.p0i8(i64, i8*) nounwind
    268 declare i32 @llvm.aarch64.stlxr.p0i16(i64, i16*) nounwind
    269 declare i32 @llvm.aarch64.stlxr.p0i32(i64, i32*) nounwind
    270 declare i32 @llvm.aarch64.stlxr.p0i64(i64, i64*) nounwind
    271