xref: /llvm-project/clang/test/CodeGen/ms-intrinsics-underaligned.c (revision 0ea64ad88abcbb939547a92000d98efb2b00d95f)
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