361 lines · c
1// RUN: %clang_cc1 -Wall -Werror -triple thumbv8-linux-gnueabi -fno-signed-char -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg | FileCheck %s2// RUN: %clang_cc1 -Wall -Werror -triple arm64-apple-ios7.0 -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg | FileCheck %s --check-prefix=CHECK-ARM643 4struct Simple {5 char a, b;6};7 8int test_ldrex(char *addr, long long *addr64, float *addrfloat) {9// CHECK-LABEL: @test_ldrex10// CHECK-ARM64-LABEL: @test_ldrex11 int sum = 0;12 sum += __builtin_arm_ldrex(addr);13// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i8) %addr)14// CHECK: trunc i32 [[INTRES]] to i815 16// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i8) %addr)17// CHECK-ARM64: trunc i64 [[INTRES]] to i818 19 sum += __builtin_arm_ldrex((short *)addr);20// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i16) %addr)21// CHECK: trunc i32 [[INTRES]] to i1622 23// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i16) %addr)24// CHECK-ARM64: trunc i64 [[INTRES]] to i1625 26 sum += __builtin_arm_ldrex((int *)addr);27// CHECK: call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr)28 29// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i32) %addr)30// CHECK-ARM64: trunc i64 [[INTRES]] to i3231 32 sum += __builtin_arm_ldrex((long long *)addr);33// CHECK: call { i32, i32 } @llvm.arm.ldrexd(ptr %addr)34 35// CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)36 37 sum += __builtin_arm_ldrex(addr64);38// CHECK: call { i32, i32 } @llvm.arm.ldrexd(ptr %addr64)39 40// CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr64)41 42 sum += __builtin_arm_ldrex(addrfloat);43// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addrfloat)44 45// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i32) %addrfloat)46// CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i3247// CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float48 49 sum += __builtin_arm_ldrex((double *)addr);50// CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(ptr %addr)51// CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 152// CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 053// CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i6454// CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i6455// CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 3256// CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]57 58// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)59// CHECK-ARM64: bitcast i64 [[INTRES]] to double60 61 sum += *__builtin_arm_ldrex((int **)addr);62// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr)63// CHECK: inttoptr i32 [[INTRES]] to ptr64 65// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)66// CHECK-ARM64: inttoptr i64 [[INTRES]] to ptr67 68 sum += __builtin_arm_ldrex((struct Simple **)addr)->a;69// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr)70// CHECK: inttoptr i32 [[INTRES]] to ptr71 72// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0(ptr elementtype(i64) %addr)73// CHECK-ARM64: inttoptr i64 [[INTRES]] to ptr74 return sum;75}76 77int test_ldaex(char *addr, long long *addr64, float *addrfloat) {78// CHECK-LABEL: @test_ldaex79// CHECK-ARM64-LABEL: @test_ldaex80 int sum = 0;81 sum += __builtin_arm_ldaex(addr);82// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i8) %addr)83// CHECK: trunc i32 [[INTRES]] to i884 85// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i8) %addr)86// CHECK-ARM64: trunc i64 [[INTRES]] to i887 88 sum += __builtin_arm_ldaex((short *)addr);89// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i16) %addr)90// CHECK: trunc i32 [[INTRES]] to i1691 92// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i16) %addr)93// CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i1694 95 sum += __builtin_arm_ldaex((int *)addr);96// CHECK: call i32 @llvm.arm.ldaex.p0(ptr elementtype(i32) %addr)97 98// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i32) %addr)99// CHECK-ARM64: trunc i64 [[INTRES]] to i32100 101 sum += __builtin_arm_ldaex((long long *)addr);102// CHECK: call { i32, i32 } @llvm.arm.ldaexd(ptr %addr)103 104// CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)105 106 sum += __builtin_arm_ldaex(addr64);107// CHECK: call { i32, i32 } @llvm.arm.ldaexd(ptr %addr64)108 109// CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr64)110 111 sum += __builtin_arm_ldaex(addrfloat);112// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i32) %addrfloat)113 114// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i32) %addrfloat)115// CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32116// CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float117 118 sum += __builtin_arm_ldaex((double *)addr);119// CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldaexd(ptr %addr)120// CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1121// CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0122// CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64123// CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64124// CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32125// CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]126 127// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)128// CHECK-ARM64: bitcast i64 [[INTRES]] to double129 130 sum += *__builtin_arm_ldaex((int **)addr);131// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i32) %addr)132// CHECK: inttoptr i32 [[INTRES]] to ptr133 134// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)135// CHECK-ARM64: inttoptr i64 [[INTRES]] to ptr136 137 sum += __builtin_arm_ldaex((struct Simple **)addr)->a;138// CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0(ptr elementtype(i32) %addr)139// CHECK: inttoptr i32 [[INTRES]] to ptr140 141// CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0(ptr elementtype(i64) %addr)142// CHECK-ARM64: inttoptr i64 [[INTRES]] to ptr143 return sum;144}145 146int test_strex(char *addr) {147// CHECK-LABEL: @test_strex148// CHECK-ARM64-LABEL: @test_strex149 int res = 0;150 struct Simple var = {0};151 res |= __builtin_arm_strex(4, addr);152// CHECK: call i32 @llvm.arm.strex.p0(i32 4, ptr elementtype(i8) %addr)153 154// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 4, ptr elementtype(i8) %addr)155 156 res |= __builtin_arm_strex(42, (short *)addr);157// CHECK: call i32 @llvm.arm.strex.p0(i32 42, ptr elementtype(i16) %addr)158 159// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 42, ptr elementtype(i16) %addr)160 161 res |= __builtin_arm_strex(42, (int *)addr);162// CHECK: call i32 @llvm.arm.strex.p0(i32 42, ptr elementtype(i32) %addr)163 164// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 42, ptr elementtype(i32) %addr)165 166 res |= __builtin_arm_strex(42, (long long *)addr);167// CHECK: store i64 42, ptr [[TMP:%.*]], align 8168// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]169// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0170// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1171// CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr %addr)172 173// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 42, ptr elementtype(i64) %addr)174 175 res |= __builtin_arm_strex(2.71828f, (float *)addr);176// CHECK: call i32 @llvm.arm.strex.p0(i32 1076754509, ptr elementtype(i32) %addr)177 178// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 1076754509, ptr elementtype(i32) %addr)179 180 res |= __builtin_arm_strex(3.14159, (double *)addr);181// CHECK: store double 3.141590e+00, ptr [[TMP:%.*]], align 8182// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]183// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0184// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1185// CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr %addr)186 187// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 4614256650576692846, ptr elementtype(i64) %addr)188 189 res |= __builtin_arm_strex(&var, (struct Simple **)addr);190// CHECK: [[INTVAL:%.*]] = ptrtoint ptr %var to i32191// CHECK: call i32 @llvm.arm.strex.p0(i32 [[INTVAL]], ptr elementtype(i32) %addr)192 193// CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint ptr %var to i64194// CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0(i64 [[INTVAL]], ptr elementtype(i64) %addr)195 196 return res;197}198 199int test_stlex(char *addr) {200// CHECK-LABEL: @test_stlex201// CHECK-ARM64-LABEL: @test_stlex202 int res = 0;203 struct Simple var = {0};204 res |= __builtin_arm_stlex(4, addr);205// CHECK: call i32 @llvm.arm.stlex.p0(i32 4, ptr elementtype(i8) %addr)206 207// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 4, ptr elementtype(i8) %addr)208 209 res |= __builtin_arm_stlex(42, (short *)addr);210// CHECK: call i32 @llvm.arm.stlex.p0(i32 42, ptr elementtype(i16) %addr)211 212// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 42, ptr elementtype(i16) %addr)213 214 res |= __builtin_arm_stlex(42, (int *)addr);215// CHECK: call i32 @llvm.arm.stlex.p0(i32 42, ptr elementtype(i32) %addr)216 217// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 42, ptr elementtype(i32) %addr)218 219 res |= __builtin_arm_stlex(42, (long long *)addr);220// CHECK: store i64 42, ptr [[TMP:%.*]], align 8221// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]222// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0223// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1224// CHECK: call i32 @llvm.arm.stlexd(i32 [[LO]], i32 [[HI]], ptr %addr)225 226// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 42, ptr elementtype(i64) %addr)227 228 res |= __builtin_arm_stlex(2.71828f, (float *)addr);229// CHECK: call i32 @llvm.arm.stlex.p0(i32 1076754509, ptr elementtype(i32) %addr)230 231// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 1076754509, ptr elementtype(i32) %addr)232 233 res |= __builtin_arm_stlex(3.14159, (double *)addr);234// CHECK: store double 3.141590e+00, ptr [[TMP:%.*]], align 8235// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]236// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0237// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1238// CHECK: call i32 @llvm.arm.stlexd(i32 [[LO]], i32 [[HI]], ptr %addr)239 240// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 4614256650576692846, ptr elementtype(i64) %addr)241 242 res |= __builtin_arm_stlex(&var, (struct Simple **)addr);243// CHECK: [[INTVAL:%.*]] = ptrtoint ptr %var to i32244// CHECK: call i32 @llvm.arm.stlex.p0(i32 [[INTVAL]], ptr elementtype(i32) %addr)245 246// CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint ptr %var to i64247// CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0(i64 [[INTVAL]], ptr elementtype(i64) %addr)248 249 return res;250}251 252void test_clrex(void) {253// CHECK-LABEL: @test_clrex254// CHECK-ARM64-LABEL: @test_clrex255 256 __builtin_arm_clrex();257// CHECK: call void @llvm.arm.clrex()258// CHECK-ARM64: call void @llvm.aarch64.clrex()259}260 261#ifdef __aarch64__262// 128-bit tests263 264__int128 test_ldrex_128(__int128 *addr) {265// CHECK-ARM64-LABEL: @test_ldrex_128266 267 return __builtin_arm_ldrex(addr);268// CHECK-ARM64: [[STRUCTRES:%.*]] = call { i64, i64 } @llvm.aarch64.ldxp(ptr %addr)269// CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1270// CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0271// CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128272// CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128273// CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64274// CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]275// CHECK-ARM64: ret i128 [[INTRES]]276}277 278int test_strex_128(__int128 *addr, __int128 val) {279// CHECK-ARM64-LABEL: @test_strex_128280 281 return __builtin_arm_strex(val, addr);282// CHECK-ARM64: store i128 %val, ptr [[TMP:%.*]], align 16283// CHECK-ARM64: [[LOHI:%.*]] = load { i64, i64 }, ptr [[TMP]]284// CHECK-ARM64: [[LO:%.*]] = extractvalue { i64, i64 } [[LOHI]], 0285// CHECK-ARM64: [[HI:%.*]] = extractvalue { i64, i64 } [[LOHI]], 1286// CHECK-ARM64: call i32 @llvm.aarch64.stxp(i64 [[LO]], i64 [[HI]], ptr %addr)287}288 289__int128 test_ldaex_128(__int128 *addr) {290// CHECK-ARM64-LABEL: @test_ldaex_128291 292 return __builtin_arm_ldaex(addr);293// CHECK-ARM64: [[STRUCTRES:%.*]] = call { i64, i64 } @llvm.aarch64.ldaxp(ptr %addr)294// CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1295// CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0296// CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128297// CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128298// CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64299// CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]300// CHECK-ARM64: ret i128 [[INTRES]]301}302 303int test_stlex_128(__int128 *addr, __int128 val) {304// CHECK-ARM64-LABEL: @test_stlex_128305 306 return __builtin_arm_stlex(val, addr);307// CHECK-ARM64: store i128 %val, ptr [[TMP:%.*]], align 16308// CHECK-ARM64: [[LOHI:%.*]] = load { i64, i64 }, ptr [[TMP]]309// CHECK-ARM64: [[LO:%.*]] = extractvalue { i64, i64 } [[LOHI]], 0310// CHECK-ARM64: [[HI:%.*]] = extractvalue { i64, i64 } [[LOHI]], 1311// CHECK-ARM64: [[RES:%.*]] = call i32 @llvm.aarch64.stlxp(i64 [[LO]], i64 [[HI]], ptr %addr)312}313 314#endif315 316#ifdef __arm__317// ARM exclusive atomic builtins318 319int test_ldrexd(char *addr, long long *addr64, float *addrfloat) {320// CHECK-LABEL: @test_ldrexd321 int sum = 0;322 sum += __builtin_arm_ldrexd((long long *)addr);323// CHECK: call { i32, i32 } @llvm.arm.ldrexd(ptr %addr)324 325 sum += __builtin_arm_ldrexd(addr64);326// CHECK: call { i32, i32 } @llvm.arm.ldrexd(ptr %addr64)327 328 sum += __builtin_arm_ldrexd((double *)addr);329// CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(ptr %addr)330// CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1331// CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0332// CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64333// CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64334// CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32335// CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]336 337 return sum;338}339 340int test_strexd(char *addr) {341// CHECK-LABEL: @test_strexd342 int res = 0;343 res |= __builtin_arm_strexd(42, (long long *)addr);344// CHECK: store i64 42, ptr [[TMP:%.*]], align 8345// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]346// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0347// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1348// CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr %addr)349 350 res |= __builtin_arm_strexd(3.14159, (double *)addr);351// CHECK: store double 3.141590e+00, ptr [[TMP:%.*]], align 8352// CHECK: [[LOHI:%.*]] = load { i32, i32 }, ptr [[TMP]]353// CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0354// CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1355// CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], ptr %addr)356 357 return res;358}359 360#endif361