1 // RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
2 // RUN: -triple x86_64--windows -Oz -emit-llvm -target-feature +cx16 %s -o - \
3 // RUN: | FileCheck %s --check-prefixes=CHECK
5 // RUN: %clang_cc1 -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
6 // RUN: -triple aarch64--windows -Oz -emit-llvm %s -o - \
7 // RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-AARCH64
9 // Ensure that we emit _Interlocked atomic operations specifying natural
10 // alignment, even when clang's usual alignment derivation would result in a
11 // lower alignment value.
13 // intrin.h needs size_t, but -ffreestanding prevents us from getting it from
14 // stddef.h. Work around it with this typedef.
15 typedef __SIZE_TYPE__
size_t;
28 _Static_assert(sizeof(X
) == 23, "");
29 _Static_assert(__alignof__(X
) == 1, "");
31 // CHECK-LABEL: @test_InterlockedExchangePointer(
32 // CHECK: atomicrmw {{.*}} align 8
33 void *test_InterlockedExchangePointer(X
*x
) {
34 return _InterlockedExchangePointer(&x
->p
, 0);
37 // CHECK-LABEL: @test_InterlockedExchange8(
38 // CHECK: atomicrmw {{.*}} align 1
39 char test_InterlockedExchange8(X
*x
) {
40 return _InterlockedExchange8(&x
->a
, 0);
43 // CHECK-LABEL: @test_InterlockedExchange16(
44 // CHECK: atomicrmw {{.*}} align 2
45 short test_InterlockedExchange16(X
*x
) {
46 return _InterlockedExchange16(&x
->b
, 0);
49 // CHECK-LABEL: @test_InterlockedExchange(
50 // CHECK: atomicrmw {{.*}} align 4
51 long test_InterlockedExchange(X
*x
) {
52 return _InterlockedExchange(&x
->c
, 0);
55 // CHECK-LABEL: @test_InterlockedExchange64(
56 // CHECK: atomicrmw {{.*}} align 8
57 long long test_InterlockedExchange64(X
*x
) {
58 return _InterlockedExchange64(&x
->d
, 0);
61 // CHECK-LABEL: @test_InterlockedIncrement(
62 // CHECK: atomicrmw {{.*}} align 4
63 long test_InterlockedIncrement(X
*x
) {
64 return _InterlockedIncrement(&x
->c
);
67 // CHECK-LABEL: @test_InterlockedDecrement16(
68 // CHECK: atomicrmw {{.*}} align 2
69 short test_InterlockedDecrement16(X
*x
) {
70 return _InterlockedDecrement16(&x
->b
);
74 // CHECK-LABEL: @test_InterlockedCompareExchangePointer(
75 // CHECK: cmpxchg {{.*}} align 8
76 void *test_InterlockedCompareExchangePointer(X
*x
) {
77 return _InterlockedCompareExchangePointer(&x
->p
, 0, 0);
80 // CHECK-LABEL: @test_InterlockedCompareExchange8(
81 // CHECK: cmpxchg {{.*}} align 1
82 char test_InterlockedCompareExchange8(X
*x
) {
83 return _InterlockedCompareExchange8(&x
->a
, 0, 0);
86 // CHECK-LABEL: @test_InterlockedCompareExchange16(
87 // CHECK: cmpxchg {{.*}} align 2
88 short test_InterlockedCompareExchange16(X
*x
) {
89 return _InterlockedCompareExchange16(&x
->b
, 0, 0);
92 // CHECK-LABEL: @test_InterlockedCompareExchange(
93 // CHECK: cmpxchg {{.*}} align 4
94 long test_InterlockedCompareExchange(X
*x
) {
95 return _InterlockedCompareExchange(&x
->c
, 0, 0);
98 // CHECK-LABEL: @test_InterlockedCompareExchange64(
99 // CHECK: cmpxchg {{.*}} align 8
100 long long test_InterlockedCompareExchange64(X
*x
) {
101 return _InterlockedCompareExchange64(&x
->d
, 0, 0);
105 // CHECK-AARCH64-LABEL: @test_InterlockedAdd(
106 // CHECK-AARCH64: atomicrmw {{.*}} align 4
107 long test_InterlockedAdd(X
*x
) {
108 return _InterlockedAdd(&x
->c
, 4);