Home | History | Annotate | Download | only in CodeGen
      1 // REQUIRES: arm-registered-target
      2 // RUN: %clang_cc1 -Wall -Werror -triple thumbv8-linux-gnueabi -fno-signed-char -O3 -emit-llvm -o - %s | FileCheck %s
      3 // RUN: %clang_cc1 -Wall -Werror -triple arm64-apple-ios7.0 -O3 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-ARM64
      4 
      5 // Make sure the canonical use works before going into smaller details:
      6 int atomic_inc(int *addr) {
      7   int Failure, OldVal;
      8   do {
      9     OldVal = __builtin_arm_ldrex(addr);
     10     Failure = __builtin_arm_strex(OldVal + 1, addr);
     11   } while (Failure);
     12 
     13   return OldVal;
     14 }
     15 
     16 // CHECK-LABEL: @atomic_inc
     17 // CHECK:   [[OLDVAL:%.*]] = tail call i32 @llvm.arm.ldrex.p0i32(i32* %addr)
     18 // CHECK:   [[INC:%.*]] = add nsw i32 [[OLDVAL]], 1
     19 // CHECK:   [[FAILURE:%.*]] = tail call i32 @llvm.arm.strex.p0i32(i32 [[INC]], i32* %addr)
     20 // CHECK:   [[TST:%.*]] = icmp eq i32 [[FAILURE]], 0
     21 // CHECK:   br i1 [[TST]], label {{%[a-zA-Z0-9.]+}}, label {{%[a-zA-Z0-9.]+}}
     22 
     23 // CHECK-ARM64-LABEL: @atomic_inc
     24 // CHECK-ARM64:   [[OLDVAL:%.*]] = tail call i64 @llvm.aarch64.ldxr.p0i32(i32* %addr)
     25 // CHECK-ARM64:   [[INC:%.*]] = add i64 [[OLDVAL]], 1
     26 // CHECK-ARM64:   [[TRUNC:%.*]] = and i64 [[INC]], 4294967295
     27 // CHECK-ARM64:   [[FAILURE:%.*]] = tail call i32 @llvm.aarch64.stxr.p0i32(i64 [[TRUNC]], i32* %addr)
     28 // CHECK-ARM64:   [[TST:%.*]] = icmp eq i32 [[FAILURE]], 0
     29 // CHECK-ARM64:   br i1 [[TST]], label {{%[a-zA-Z0-9.]+}}, label {{%[a-zA-Z0-9.]+}}
     30 
     31 struct Simple {
     32   char a, b;
     33 };
     34 
     35 int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
     36 // CHECK-LABEL: @test_ldrex
     37 // CHECK-ARM64-LABEL: @test_ldrex
     38   int sum = 0;
     39   sum += __builtin_arm_ldrex(addr);
     40 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldrex.p0i8(i8* %addr)
     41 // CHECK: and i32 [[INTRES]], 255
     42 
     43 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
     44 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
     45 // CHECK-ARM64: [[SEXTTMP:%.*]] = shl i32 [[TRUNCRES]], 24
     46 // CHECK-ARM64: ashr exact i32 [[SEXTTMP]], 24
     47 
     48   sum += __builtin_arm_ldrex((short *)addr);
     49 // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
     50 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldrex.p0i16(i16* [[ADDR16]])
     51 // CHECK: [[TMPSEXT:%.*]] = shl i32 [[INTRES]], 16
     52 // CHECK: ashr exact i32 [[TMPSEXT]], 16
     53 
     54 // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
     55 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldxr.p0i16(i16* [[ADDR16]])
     56 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
     57 // CHECK-ARM64: [[TMPSEXT:%.*]] = shl i32 [[TRUNCRES]], 16
     58 // CHECK-ARM64: ashr exact i32 [[TMPSEXT]], 16
     59 
     60   sum += __builtin_arm_ldrex((int *)addr);
     61 // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
     62 // CHECK:  call i32 @llvm.arm.ldrex.p0i32(i32* [[ADDR32]])
     63 
     64 // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
     65 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldxr.p0i32(i32* [[ADDR32]])
     66 // CHECK-ARM64: trunc i64 [[INTRES]] to i32
     67 
     68   sum += __builtin_arm_ldrex((long long *)addr);
     69 // CHECK: call { i32, i32 } @llvm.arm.ldrexd(i8* %addr)
     70 
     71 // CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
     72 // CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i64(i64* [[ADDR64]])
     73 
     74   sum += __builtin_arm_ldrex(addr64);
     75 // CHECK: [[ADDR64_AS8:%.*]] = bitcast i64* %addr64 to i8*
     76 // CHECK: call { i32, i32 } @llvm.arm.ldrexd(i8* [[ADDR64_AS8]])
     77 
     78 // CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr64)
     79 
     80   sum += __builtin_arm_ldrex(addrfloat);
     81 // CHECK: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
     82 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldrex.p0i32(i32* [[INTADDR]])
     83 // CHECK: bitcast i32 [[INTRES]] to float
     84 
     85 // CHECK-ARM64: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
     86 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldxr.p0i32(i32* [[INTADDR]])
     87 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
     88 // CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float
     89 
     90   sum += __builtin_arm_ldrex((double *)addr);
     91 // CHECK: [[STRUCTRES:%.*]] = tail call { i32, i32 } @llvm.arm.ldrexd(i8* %addr)
     92 // CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
     93 // CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
     94 // CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
     95 // CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
     96 // CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
     97 // CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
     98 // CHECK: bitcast i64 [[INTRES]] to double
     99 
    100 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldxr.p0i64(i64* [[ADDR64]])
    101 // CHECK-ARM64: bitcast i64 [[INTRES]] to double
    102 
    103   sum += *__builtin_arm_ldrex((int **)addr);
    104 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldrex.p0i32(i32* [[ADDR32]])
    105 // CHECK: inttoptr i32 [[INTRES]] to i32*
    106 
    107 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldxr.p0i64(i64* [[ADDR64]])
    108 // CHECK-ARM64: inttoptr i64 [[INTRES]] to i32*
    109 
    110   sum += __builtin_arm_ldrex((struct Simple **)addr)->a;
    111 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldrex.p0i32(i32* [[ADDR32]])
    112 // CHECK: inttoptr i32 [[INTRES]] to %struct.Simple*
    113 
    114 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldxr.p0i64(i64* [[ADDR64]])
    115 // CHECK-ARM64: inttoptr i64 [[INTRES]] to %struct.Simple*
    116   return sum;
    117 }
    118 
    119 int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
    120 // CHECK-LABEL: @test_ldaex
    121 // CHECK-ARM64-LABEL: @test_ldaex
    122   int sum = 0;
    123   sum += __builtin_arm_ldaex(addr);
    124 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldaex.p0i8(i8* %addr)
    125 // CHECK: and i32 [[INTRES]], 255
    126 
    127 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
    128 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
    129 // CHECK-ARM64: [[SEXTTMP:%.*]] = shl i32 [[TRUNCRES]], 24
    130 // CHECK-ARM64: ashr exact i32 [[SEXTTMP]], 24
    131 
    132   sum += __builtin_arm_ldaex((short *)addr);
    133 // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
    134 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldaex.p0i16(i16* [[ADDR16]])
    135 // CHECK: [[TMPSEXT:%.*]] = shl i32 [[INTRES]], 16
    136 // CHECK: ashr exact i32 [[TMPSEXT]], 16
    137 
    138 // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
    139 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldaxr.p0i16(i16* [[ADDR16]])
    140 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
    141 // CHECK-ARM64: [[TMPSEXT:%.*]] = shl i32 [[TRUNCRES]], 16
    142 // CHECK-ARM64: ashr exact i32 [[TMPSEXT]], 16
    143 
    144   sum += __builtin_arm_ldaex((int *)addr);
    145 // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
    146 // CHECK:  call i32 @llvm.arm.ldaex.p0i32(i32* [[ADDR32]])
    147 
    148 // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
    149 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldaxr.p0i32(i32* [[ADDR32]])
    150 // CHECK-ARM64: trunc i64 [[INTRES]] to i32
    151 
    152   sum += __builtin_arm_ldaex((long long *)addr);
    153 // CHECK: call { i32, i32 } @llvm.arm.ldaexd(i8* %addr)
    154 
    155 // CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
    156 // CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[ADDR64]])
    157 
    158   sum += __builtin_arm_ldaex(addr64);
    159 // CHECK: [[ADDR64_AS8:%.*]] = bitcast i64* %addr64 to i8*
    160 // CHECK: call { i32, i32 } @llvm.arm.ldaexd(i8* [[ADDR64_AS8]])
    161 
    162 // CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr64)
    163 
    164   sum += __builtin_arm_ldaex(addrfloat);
    165 // CHECK: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
    166 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldaex.p0i32(i32* [[INTADDR]])
    167 // CHECK: bitcast i32 [[INTRES]] to float
    168 
    169 // CHECK-ARM64: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
    170 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldaxr.p0i32(i32* [[INTADDR]])
    171 // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
    172 // CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float
    173 
    174   sum += __builtin_arm_ldaex((double *)addr);
    175 // CHECK: [[STRUCTRES:%.*]] = tail call { i32, i32 } @llvm.arm.ldaexd(i8* %addr)
    176 // CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
    177 // CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
    178 // CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
    179 // CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
    180 // CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
    181 // CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
    182 // CHECK: bitcast i64 [[INTRES]] to double
    183 
    184 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[ADDR64]])
    185 // CHECK-ARM64: bitcast i64 [[INTRES]] to double
    186 
    187   sum += *__builtin_arm_ldaex((int **)addr);
    188 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldaex.p0i32(i32* [[ADDR32]])
    189 // CHECK: inttoptr i32 [[INTRES]] to i32*
    190 
    191 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[ADDR64]])
    192 // CHECK-ARM64: inttoptr i64 [[INTRES]] to i32*
    193 
    194   sum += __builtin_arm_ldaex((struct Simple **)addr)->a;
    195 // CHECK: [[INTRES:%.*]] = tail call i32 @llvm.arm.ldaex.p0i32(i32* [[ADDR32]])
    196 // CHECK: inttoptr i32 [[INTRES]] to %struct.Simple*
    197 
    198 // CHECK-ARM64: [[INTRES:%.*]] = tail call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[ADDR64]])
    199 // CHECK-ARM64: inttoptr i64 [[INTRES]] to %struct.Simple*
    200   return sum;
    201 }
    202 
    203 int test_strex(char *addr) {
    204 // CHECK-LABEL: @test_strex
    205 // CHECK-ARM64-LABEL: @test_strex
    206   int res = 0;
    207   struct Simple var = {0};
    208   res |= __builtin_arm_strex(4, addr);
    209 // CHECK: call i32 @llvm.arm.strex.p0i8(i32 4, i8* %addr)
    210 
    211 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i8(i64 4, i8* %addr)
    212 
    213   res |= __builtin_arm_strex(42, (short *)addr);
    214 // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
    215 // CHECK:  call i32 @llvm.arm.strex.p0i16(i32 42, i16* [[ADDR16]])
    216 
    217 // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
    218 // CHECK-ARM64:  call i32 @llvm.aarch64.stxr.p0i16(i64 42, i16* [[ADDR16]])
    219 
    220   res |= __builtin_arm_strex(42, (int *)addr);
    221 // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
    222 // CHECK: call i32 @llvm.arm.strex.p0i32(i32 42, i32* [[ADDR32]])
    223 
    224 // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
    225 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i32(i64 42, i32* [[ADDR32]])
    226 
    227   res |= __builtin_arm_strex(42, (long long *)addr);
    228 // CHECK: call i32 @llvm.arm.strexd(i32 42, i32 0, i8* %addr)
    229 
    230 // CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
    231 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 42, i64* [[ADDR64]])
    232 
    233   res |= __builtin_arm_strex(2.71828f, (float *)addr);
    234 // CHECK: call i32 @llvm.arm.strex.p0i32(i32 1076754509, i32* [[ADDR32]])
    235 
    236 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i32(i64 1076754509, i32* [[ADDR32]])
    237 
    238   res |= __builtin_arm_strex(3.14159, (double *)addr);
    239 // CHECK: call i32 @llvm.arm.strexd(i32 -266631570, i32 1074340345, i8* %addr)
    240 
    241 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 4614256650576692846, i64* [[ADDR64]])
    242 
    243   res |= __builtin_arm_strex(&var, (struct Simple **)addr);
    244 // CHECK: [[INTVAL:%.*]] = ptrtoint i16* %var to i32
    245 // CHECK: call i32 @llvm.arm.strex.p0i32(i32 [[INTVAL]], i32* [[ADDR32]])
    246 
    247 // CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint i16* %var to i64
    248 // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 [[INTVAL]], i64* [[ADDR64]])
    249 
    250   return res;
    251 }
    252 
    253 int test_stlex(char *addr) {
    254 // CHECK-LABEL: @test_stlex
    255 // CHECK-ARM64-LABEL: @test_stlex
    256   int res = 0;
    257   struct Simple var = {0};
    258   res |= __builtin_arm_stlex(4, addr);
    259 // CHECK: call i32 @llvm.arm.stlex.p0i8(i32 4, i8* %addr)
    260 
    261 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i8(i64 4, i8* %addr)
    262 
    263   res |= __builtin_arm_stlex(42, (short *)addr);
    264 // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
    265 // CHECK:  call i32 @llvm.arm.stlex.p0i16(i32 42, i16* [[ADDR16]])
    266 
    267 // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
    268 // CHECK-ARM64:  call i32 @llvm.aarch64.stlxr.p0i16(i64 42, i16* [[ADDR16]])
    269 
    270   res |= __builtin_arm_stlex(42, (int *)addr);
    271 // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
    272 // CHECK: call i32 @llvm.arm.stlex.p0i32(i32 42, i32* [[ADDR32]])
    273 
    274 // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
    275 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i32(i64 42, i32* [[ADDR32]])
    276 
    277   res |= __builtin_arm_stlex(42, (long long *)addr);
    278 // CHECK: call i32 @llvm.arm.stlexd(i32 42, i32 0, i8* %addr)
    279 
    280 // CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
    281 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 42, i64* [[ADDR64]])
    282 
    283   res |= __builtin_arm_stlex(2.71828f, (float *)addr);
    284 // CHECK: call i32 @llvm.arm.stlex.p0i32(i32 1076754509, i32* [[ADDR32]])
    285 
    286 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i32(i64 1076754509, i32* [[ADDR32]])
    287 
    288   res |= __builtin_arm_stlex(3.14159, (double *)addr);
    289 // CHECK: call i32 @llvm.arm.stlexd(i32 -266631570, i32 1074340345, i8* %addr)
    290 
    291 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 4614256650576692846, i64* [[ADDR64]])
    292 
    293   res |= __builtin_arm_stlex(&var, (struct Simple **)addr);
    294 // CHECK: [[INTVAL:%.*]] = ptrtoint i16* %var to i32
    295 // CHECK: call i32 @llvm.arm.stlex.p0i32(i32 [[INTVAL]], i32* [[ADDR32]])
    296 
    297 // CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint i16* %var to i64
    298 // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 [[INTVAL]], i64* [[ADDR64]])
    299 
    300   return res;
    301 }
    302 
    303 void test_clrex() {
    304 // CHECK-LABEL: @test_clrex
    305 // CHECK-ARM64-LABEL: @test_clrex
    306 
    307   __builtin_arm_clrex();
    308 // CHECK: call void @llvm.arm.clrex()
    309 // CHECK-ARM64: call void @llvm.aarch64.clrex()
    310 }
    311 
    312 #ifdef __aarch64__
    313 // 128-bit tests
    314 
    315 __int128 test_ldrex_128(__int128 *addr) {
    316 // CHECK-ARM64-LABEL: @test_ldrex_128
    317 
    318   return __builtin_arm_ldrex(addr);
    319 // CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
    320 // CHECK-ARM64: [[STRUCTRES:%.*]] = tail call { i64, i64 } @llvm.aarch64.ldxp(i8* [[ADDR8]])
    321 // CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1
    322 // CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0
    323 // CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128
    324 // CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128
    325 // CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64
    326 // CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]
    327 // CHECK-ARM64: ret i128 [[INTRES]]
    328 }
    329 
    330 int test_strex_128(__int128 *addr, __int128 val) {
    331 // CHECK-ARM64-LABEL: @test_strex_128
    332 
    333   return __builtin_arm_strex(val, addr);
    334 // CHECK-ARM64: [[VALLO:%.*]] = trunc i128 %val to i64
    335 // CHECK-ARM64: [[VALHI128:%.*]] = lshr i128 %val, 64
    336 // CHECK-ARM64: [[VALHI:%.*]] = trunc i128 [[VALHI128]] to i64
    337 // CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
    338 // CHECK-ARM64: [[RES:%.*]] = tail call i32 @llvm.aarch64.stxp(i64 [[VALLO]], i64 [[VALHI]], i8* [[ADDR8]])
    339 }
    340 
    341 __int128 test_ldaex_128(__int128 *addr) {
    342 // CHECK-ARM64-LABEL: @test_ldaex_128
    343 
    344   return __builtin_arm_ldaex(addr);
    345 // CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
    346 // CHECK-ARM64: [[STRUCTRES:%.*]] = tail call { i64, i64 } @llvm.aarch64.ldaxp(i8* [[ADDR8]])
    347 // CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1
    348 // CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0
    349 // CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128
    350 // CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128
    351 // CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64
    352 // CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]
    353 // CHECK-ARM64: ret i128 [[INTRES]]
    354 }
    355 
    356 int test_stlex_128(__int128 *addr, __int128 val) {
    357 // CHECK-ARM64-LABEL: @test_stlex_128
    358 
    359   return __builtin_arm_stlex(val, addr);
    360 // CHECK-ARM64: [[VALLO:%.*]] = trunc i128 %val to i64
    361 // CHECK-ARM64: [[VALHI128:%.*]] = lshr i128 %val, 64
    362 // CHECK-ARM64: [[VALHI:%.*]] = trunc i128 [[VALHI128]] to i64
    363 // CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
    364 // CHECK-ARM64: [[RES:%.*]] = tail call i32 @llvm.aarch64.stlxp(i64 [[VALLO]], i64 [[VALHI]], i8* [[ADDR8]])
    365 }
    366 
    367 #endif
    368