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