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 5 struct Simple { 6 char a, b; 7 }; 8 9 int 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 102 int 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 195 int 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 269 int 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 343 void 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 370 int 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 398 int 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