Skip to content

Commit 0ea8756

Browse files
authored
[clang] Separate Intel ADC instrinsics from ADX intrinsics (#75992)
See #75711 for discussion. As a summary from the PR above, `<adxintrin.h>` includes adc intrinsics and adx intrinsics. To support MSVC STL we need to expose the adc intrinsics inside the currently proposed `<intrin0.h>` header. Move the processor agnostic adc intrinsics into a separate file that can be included from `<immintrin.h>` and the currently proposed `<intrin0.h>`.
1 parent ad4cead commit 0ea8756

File tree

4 files changed

+176
-136
lines changed

4 files changed

+176
-136
lines changed

clang/lib/Headers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ set(webassembly_files
139139

140140
set(x86_files
141141
# Intrinsics
142+
adcintrin.h
142143
adxintrin.h
143144
ammintrin.h
144145
amxcomplexintrin.h

clang/lib/Headers/adcintrin.h

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*===---- adcintrin.h - ADC intrinsics -------------------------------------===
2+
*
3+
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
* See https://llvm.org/LICENSE.txt for license information.
5+
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
*
7+
*===-----------------------------------------------------------------------===
8+
*/
9+
10+
#ifndef __ADCINTRIN_H
11+
#define __ADCINTRIN_H
12+
13+
#if !defined(__i386__) && !defined(__x86_64__)
14+
#error "This header is only meant to be used on x86 and x64 architecture"
15+
#endif
16+
17+
/* Define the default attributes for the functions in this file. */
18+
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
19+
20+
/* Use C++ inline semantics in C++, GNU inline for C mode. */
21+
#if defined(__cplusplus)
22+
#define __INLINE __inline
23+
#else
24+
#define __INLINE static __inline
25+
#endif
26+
27+
#if defined(__cplusplus)
28+
extern "C" {
29+
#endif
30+
31+
/// Adds unsigned 32-bit integers \a __x and \a __y, plus 0 or 1 as indicated
32+
/// by the carry flag \a __cf. Stores the unsigned 32-bit sum in the memory
33+
/// at \a __p, and returns the 8-bit carry-out (carry flag).
34+
///
35+
/// \code{.operation}
36+
/// temp := (__cf == 0) ? 0 : 1
37+
/// Store32(__p, __x + __y + temp)
38+
/// result := CF
39+
/// \endcode
40+
///
41+
/// \headerfile <immintrin.h>
42+
///
43+
/// This intrinsic corresponds to the \c ADC instruction.
44+
///
45+
/// \param __cf
46+
/// The 8-bit unsigned carry flag; any non-zero value indicates carry.
47+
/// \param __x
48+
/// A 32-bit unsigned addend.
49+
/// \param __y
50+
/// A 32-bit unsigned addend.
51+
/// \param __p
52+
/// Pointer to memory for storing the sum.
53+
/// \returns The 8-bit unsigned carry-out value.
54+
__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarry_u32(unsigned char __cf,
55+
unsigned int __x,
56+
unsigned int __y,
57+
unsigned int *__p) {
58+
return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p);
59+
}
60+
61+
/// Adds unsigned 32-bit integer \a __y to 0 or 1 as indicated by the carry
62+
/// flag \a __cf, and subtracts the result from unsigned 32-bit integer
63+
/// \a __x. Stores the unsigned 32-bit difference in the memory at \a __p,
64+
/// and returns the 8-bit carry-out (carry or overflow flag).
65+
///
66+
/// \code{.operation}
67+
/// temp := (__cf == 0) ? 0 : 1
68+
/// Store32(__p, __x - (__y + temp))
69+
/// result := CF
70+
/// \endcode
71+
///
72+
/// \headerfile <immintrin.h>
73+
///
74+
/// This intrinsic corresponds to the \c SBB instruction.
75+
///
76+
/// \param __cf
77+
/// The 8-bit unsigned carry flag; any non-zero value indicates carry.
78+
/// \param __x
79+
/// The 32-bit unsigned minuend.
80+
/// \param __y
81+
/// The 32-bit unsigned subtrahend.
82+
/// \param __p
83+
/// Pointer to memory for storing the difference.
84+
/// \returns The 8-bit unsigned carry-out value.
85+
__INLINE unsigned char __DEFAULT_FN_ATTRS _subborrow_u32(unsigned char __cf,
86+
unsigned int __x,
87+
unsigned int __y,
88+
unsigned int *__p) {
89+
return __builtin_ia32_subborrow_u32(__cf, __x, __y, __p);
90+
}
91+
92+
#ifdef __x86_64__
93+
/// Adds unsigned 64-bit integers \a __x and \a __y, plus 0 or 1 as indicated
94+
/// by the carry flag \a __cf. Stores the unsigned 64-bit sum in the memory
95+
/// at \a __p, and returns the 8-bit carry-out (carry flag).
96+
///
97+
/// \code{.operation}
98+
/// temp := (__cf == 0) ? 0 : 1
99+
/// Store64(__p, __x + __y + temp)
100+
/// result := CF
101+
/// \endcode
102+
///
103+
/// \headerfile <immintrin.h>
104+
///
105+
/// This intrinsic corresponds to the \c ADC instruction.
106+
///
107+
/// \param __cf
108+
/// The 8-bit unsigned carry flag; any non-zero value indicates carry.
109+
/// \param __x
110+
/// A 64-bit unsigned addend.
111+
/// \param __y
112+
/// A 64-bit unsigned addend.
113+
/// \param __p
114+
/// Pointer to memory for storing the sum.
115+
/// \returns The 8-bit unsigned carry-out value.
116+
__INLINE unsigned char __DEFAULT_FN_ATTRS
117+
_addcarry_u64(unsigned char __cf, unsigned long long __x,
118+
unsigned long long __y, unsigned long long *__p) {
119+
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p);
120+
}
121+
122+
/// Adds unsigned 64-bit integer \a __y to 0 or 1 as indicated by the carry
123+
/// flag \a __cf, and subtracts the result from unsigned 64-bit integer
124+
/// \a __x. Stores the unsigned 64-bit difference in the memory at \a __p,
125+
/// and returns the 8-bit carry-out (carry or overflow flag).
126+
///
127+
/// \code{.operation}
128+
/// temp := (__cf == 0) ? 0 : 1
129+
/// Store64(__p, __x - (__y + temp))
130+
/// result := CF
131+
/// \endcode
132+
///
133+
/// \headerfile <immintrin.h>
134+
///
135+
/// This intrinsic corresponds to the \c ADC instruction.
136+
///
137+
/// \param __cf
138+
/// The 8-bit unsigned carry flag; any non-zero value indicates carry.
139+
/// \param __x
140+
/// The 64-bit unsigned minuend.
141+
/// \param __y
142+
/// The 64-bit unsigned subtrahend.
143+
/// \param __p
144+
/// Pointer to memory for storing the difference.
145+
/// \returns The 8-bit unsigned carry-out value.
146+
__INLINE unsigned char __DEFAULT_FN_ATTRS
147+
_subborrow_u64(unsigned char __cf, unsigned long long __x,
148+
unsigned long long __y, unsigned long long *__p) {
149+
return __builtin_ia32_subborrow_u64(__cf, __x, __y, __p);
150+
}
151+
#endif
152+
153+
#if defined(__cplusplus)
154+
}
155+
#endif
156+
157+
#undef __INLINE
158+
#undef __DEFAULT_FN_ATTRS
159+
160+
#endif /* __ADCINTRIN_H */

clang/lib/Headers/adxintrin.h

Lines changed: 9 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
#define __ADXINTRIN_H
1616

1717
/* Define the default attributes for the functions in this file. */
18-
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
18+
#define __DEFAULT_FN_ATTRS \
19+
__attribute__((__always_inline__, __nodebug__, __target__("adx")))
1920

2021
/* Use C++ inline semantics in C++, GNU inline for C mode. */
2122
#if defined(__cplusplus)
@@ -53,10 +54,10 @@ extern "C" {
5354
/// \param __p
5455
/// Pointer to memory for storing the sum.
5556
/// \returns The 8-bit unsigned carry-out value.
56-
__INLINE unsigned char
57-
__attribute__((__always_inline__, __nodebug__, __target__("adx")))
58-
_addcarryx_u32(unsigned char __cf, unsigned int __x, unsigned int __y,
59-
unsigned int *__p) {
57+
__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarryx_u32(unsigned char __cf,
58+
unsigned int __x,
59+
unsigned int __y,
60+
unsigned int *__p) {
6061
return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p);
6162
}
6263

@@ -84,144 +85,18 @@ __INLINE unsigned char
8485
/// \param __p
8586
/// Pointer to memory for storing the sum.
8687
/// \returns The 8-bit unsigned carry-out value.
87-
__INLINE unsigned char
88-
__attribute__((__always_inline__, __nodebug__, __target__("adx")))
89-
_addcarryx_u64(unsigned char __cf, unsigned long long __x,
90-
unsigned long long __y, unsigned long long *__p) {
91-
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p);
92-
}
93-
#endif
94-
95-
/* Intrinsics that are also available if __ADX__ is undefined. */
96-
97-
/// Adds unsigned 32-bit integers \a __x and \a __y, plus 0 or 1 as indicated
98-
/// by the carry flag \a __cf. Stores the unsigned 32-bit sum in the memory
99-
/// at \a __p, and returns the 8-bit carry-out (carry flag).
100-
///
101-
/// \code{.operation}
102-
/// temp := (__cf == 0) ? 0 : 1
103-
/// Store32(__p, __x + __y + temp)
104-
/// result := CF
105-
/// \endcode
106-
///
107-
/// \headerfile <immintrin.h>
108-
///
109-
/// This intrinsic corresponds to the \c ADC instruction.
110-
///
111-
/// \param __cf
112-
/// The 8-bit unsigned carry flag; any non-zero value indicates carry.
113-
/// \param __x
114-
/// A 32-bit unsigned addend.
115-
/// \param __y
116-
/// A 32-bit unsigned addend.
117-
/// \param __p
118-
/// Pointer to memory for storing the sum.
119-
/// \returns The 8-bit unsigned carry-out value.
120-
__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarry_u32(unsigned char __cf,
121-
unsigned int __x,
122-
unsigned int __y,
123-
unsigned int *__p) {
124-
return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p);
125-
}
126-
127-
#ifdef __x86_64__
128-
/// Adds unsigned 64-bit integers \a __x and \a __y, plus 0 or 1 as indicated
129-
/// by the carry flag \a __cf. Stores the unsigned 64-bit sum in the memory
130-
/// at \a __p, and returns the 8-bit carry-out (carry flag).
131-
///
132-
/// \code{.operation}
133-
/// temp := (__cf == 0) ? 0 : 1
134-
/// Store64(__p, __x + __y + temp)
135-
/// result := CF
136-
/// \endcode
137-
///
138-
/// \headerfile <immintrin.h>
139-
///
140-
/// This intrinsic corresponds to the \c ADC instruction.
141-
///
142-
/// \param __cf
143-
/// The 8-bit unsigned carry flag; any non-zero value indicates carry.
144-
/// \param __x
145-
/// A 64-bit unsigned addend.
146-
/// \param __y
147-
/// A 64-bit unsigned addend.
148-
/// \param __p
149-
/// Pointer to memory for storing the sum.
150-
/// \returns The 8-bit unsigned carry-out value.
15188
__INLINE unsigned char __DEFAULT_FN_ATTRS
152-
_addcarry_u64(unsigned char __cf, unsigned long long __x,
153-
unsigned long long __y, unsigned long long *__p) {
154-
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p);
155-
}
156-
#endif
157-
158-
/// Adds unsigned 32-bit integer \a __y to 0 or 1 as indicated by the carry
159-
/// flag \a __cf, and subtracts the result from unsigned 32-bit integer
160-
/// \a __x. Stores the unsigned 32-bit difference in the memory at \a __p,
161-
/// and returns the 8-bit carry-out (carry or overflow flag).
162-
///
163-
/// \code{.operation}
164-
/// temp := (__cf == 0) ? 0 : 1
165-
/// Store32(__p, __x - (__y + temp))
166-
/// result := CF
167-
/// \endcode
168-
///
169-
/// \headerfile <immintrin.h>
170-
///
171-
/// This intrinsic corresponds to the \c SBB instruction.
172-
///
173-
/// \param __cf
174-
/// The 8-bit unsigned carry flag; any non-zero value indicates carry.
175-
/// \param __x
176-
/// The 32-bit unsigned minuend.
177-
/// \param __y
178-
/// The 32-bit unsigned subtrahend.
179-
/// \param __p
180-
/// Pointer to memory for storing the difference.
181-
/// \returns The 8-bit unsigned carry-out value.
182-
__INLINE unsigned char __DEFAULT_FN_ATTRS _subborrow_u32(unsigned char __cf,
183-
unsigned int __x,
184-
unsigned int __y,
185-
unsigned int *__p) {
186-
return __builtin_ia32_subborrow_u32(__cf, __x, __y, __p);
187-
}
188-
189-
#ifdef __x86_64__
190-
/// Adds unsigned 64-bit integer \a __y to 0 or 1 as indicated by the carry
191-
/// flag \a __cf, and subtracts the result from unsigned 64-bit integer
192-
/// \a __x. Stores the unsigned 64-bit difference in the memory at \a __p,
193-
/// and returns the 8-bit carry-out (carry or overflow flag).
194-
///
195-
/// \code{.operation}
196-
/// temp := (__cf == 0) ? 0 : 1
197-
/// Store64(__p, __x - (__y + temp))
198-
/// result := CF
199-
/// \endcode
200-
///
201-
/// \headerfile <immintrin.h>
202-
///
203-
/// This intrinsic corresponds to the \c ADC instruction.
204-
///
205-
/// \param __cf
206-
/// The 8-bit unsigned carry flag; any non-zero value indicates carry.
207-
/// \param __x
208-
/// The 64-bit unsigned minuend.
209-
/// \param __y
210-
/// The 64-bit unsigned subtrahend.
211-
/// \param __p
212-
/// Pointer to memory for storing the difference.
213-
/// \returns The 8-bit unsigned carry-out value.
214-
__INLINE unsigned char __DEFAULT_FN_ATTRS
215-
_subborrow_u64(unsigned char __cf, unsigned long long __x,
89+
_addcarryx_u64(unsigned char __cf, unsigned long long __x,
21690
unsigned long long __y, unsigned long long *__p) {
217-
return __builtin_ia32_subborrow_u64(__cf, __x, __y, __p);
91+
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p);
21892
}
21993
#endif
22094

22195
#if defined(__cplusplus)
22296
}
22397
#endif
22498

99+
#undef __INLINE
225100
#undef __DEFAULT_FN_ATTRS
226101

227102
#endif /* __ADXINTRIN_H */

clang/lib/Headers/immintrin.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,9 +580,13 @@ _storebe_i64(void * __P, long long __D) {
580580
#include <cetintrin.h>
581581
#endif
582582

583-
/* Some intrinsics inside adxintrin.h are available only on processors with ADX,
584-
* whereas others are also available at all times. */
583+
/* Intrinsics inside adcintrin.h are available at all times. */
584+
#include <adcintrin.h>
585+
586+
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
587+
defined(__ADX__)
585588
#include <adxintrin.h>
589+
#endif
586590

587591
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \
588592
defined(__RDSEED__)

0 commit comments

Comments
 (0)