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
4
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
8
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.
12
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;
16
17 #include <intrin.h>
18
19 #pragma pack(1)
20 typedef struct {
21 char a;
22 short b;
23 long c;
24 long long d;
25 void *p;
26 } X;
27
28 _Static_assert(sizeof(X) == 23, "");
29 _Static_assert(__alignof__(X) == 1, "");
30
31 // CHECK-LABEL: @test_InterlockedExchangePointer(
32 // CHECK: atomicrmw {{.*}} align 8
test_InterlockedExchangePointer(X * x)33 void *test_InterlockedExchangePointer(X *x) {
34 return _InterlockedExchangePointer(&x->p, 0);
35 }
36
37 // CHECK-LABEL: @test_InterlockedExchange8(
38 // CHECK: atomicrmw {{.*}} align 1
test_InterlockedExchange8(X * x)39 char test_InterlockedExchange8(X *x) {
40 return _InterlockedExchange8(&x->a, 0);
41 }
42
43 // CHECK-LABEL: @test_InterlockedExchange16(
44 // CHECK: atomicrmw {{.*}} align 2
test_InterlockedExchange16(X * x)45 short test_InterlockedExchange16(X *x) {
46 return _InterlockedExchange16(&x->b, 0);
47 }
48
49 // CHECK-LABEL: @test_InterlockedExchange(
50 // CHECK: atomicrmw {{.*}} align 4
test_InterlockedExchange(X * x)51 long test_InterlockedExchange(X *x) {
52 return _InterlockedExchange(&x->c, 0);
53 }
54
55 // CHECK-LABEL: @test_InterlockedExchange64(
56 // CHECK: atomicrmw {{.*}} align 8
test_InterlockedExchange64(X * x)57 long long test_InterlockedExchange64(X *x) {
58 return _InterlockedExchange64(&x->d, 0);
59 }
60
61 // CHECK-LABEL: @test_InterlockedIncrement(
62 // CHECK: atomicrmw {{.*}} align 4
test_InterlockedIncrement(X * x)63 long test_InterlockedIncrement(X *x) {
64 return _InterlockedIncrement(&x->c);
65 }
66
67 // CHECK-LABEL: @test_InterlockedDecrement16(
68 // CHECK: atomicrmw {{.*}} align 2
test_InterlockedDecrement16(X * x)69 short test_InterlockedDecrement16(X *x) {
70 return _InterlockedDecrement16(&x->b);
71 }
72
73
74 // CHECK-LABEL: @test_InterlockedCompareExchangePointer(
75 // CHECK: cmpxchg {{.*}} align 8
test_InterlockedCompareExchangePointer(X * x)76 void *test_InterlockedCompareExchangePointer(X *x) {
77 return _InterlockedCompareExchangePointer(&x->p, 0, 0);
78 }
79
80 // CHECK-LABEL: @test_InterlockedCompareExchange8(
81 // CHECK: cmpxchg {{.*}} align 1
test_InterlockedCompareExchange8(X * x)82 char test_InterlockedCompareExchange8(X *x) {
83 return _InterlockedCompareExchange8(&x->a, 0, 0);
84 }
85
86 // CHECK-LABEL: @test_InterlockedCompareExchange16(
87 // CHECK: cmpxchg {{.*}} align 2
test_InterlockedCompareExchange16(X * x)88 short test_InterlockedCompareExchange16(X *x) {
89 return _InterlockedCompareExchange16(&x->b, 0, 0);
90 }
91
92 // CHECK-LABEL: @test_InterlockedCompareExchange(
93 // CHECK: cmpxchg {{.*}} align 4
test_InterlockedCompareExchange(X * x)94 long test_InterlockedCompareExchange(X *x) {
95 return _InterlockedCompareExchange(&x->c, 0, 0);
96 }
97
98 // CHECK-LABEL: @test_InterlockedCompareExchange64(
99 // CHECK: cmpxchg {{.*}} align 8
test_InterlockedCompareExchange64(X * x)100 long long test_InterlockedCompareExchange64(X *x) {
101 return _InterlockedCompareExchange64(&x->d, 0, 0);
102 }
103
104 #ifdef __aarch64__
105 // CHECK-AARCH64-LABEL: @test_InterlockedAdd(
106 // CHECK-AARCH64: atomicrmw {{.*}} align 4
test_InterlockedAdd(X * x)107 long test_InterlockedAdd(X *x) {
108 return _InterlockedAdd(&x->c, 4);
109 }
110
111 // CHECK-AARCH64-LABEL: @test_InterlockedAdd64(
112 // CHECK-AARCH64: atomicrmw {{.*}} align 8
test_InterlockedAdd64(X * x)113 long test_InterlockedAdd64(X *x) {
114 return _InterlockedAdd64(&x->c, 4);
115 }
116 #endif
117