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