-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[clang] Separate Intel ADC instrinsics from ADX intrinsics #75992
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b6ea2ff
c78edb3
a435b3a
f037a86
c220fec
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
/*===---- adcintrin.h - ADC intrinsics -------------------------------------=== | ||
* | ||
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
* See https://llvm.org/LICENSE.txt for license information. | ||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
* | ||
*===-----------------------------------------------------------------------=== | ||
*/ | ||
|
||
#ifndef __ADCINTRIN_H | ||
#define __ADCINTRIN_H | ||
|
||
#if !defined(__i386__) && !defined(__x86_64__) | ||
#error "This header is only meant to be used on x86 and x64 architecture" | ||
#endif | ||
|
||
/* Define the default attributes for the functions in this file. */ | ||
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) | ||
|
||
/* Use C++ inline semantics in C++, GNU inline for C mode. */ | ||
#if defined(__cplusplus) | ||
#define __INLINE __inline | ||
#else | ||
#define __INLINE static __inline | ||
#endif | ||
|
||
#if defined(__cplusplus) | ||
extern "C" { | ||
#endif | ||
|
||
/// Adds unsigned 32-bit integers \a __x and \a __y, plus 0 or 1 as indicated | ||
/// by the carry flag \a __cf. Stores the unsigned 32-bit sum in the memory | ||
/// at \a __p, and returns the 8-bit carry-out (carry flag). | ||
/// | ||
/// \code{.operation} | ||
/// temp := (__cf == 0) ? 0 : 1 | ||
/// Store32(__p, __x + __y + temp) | ||
/// result := CF | ||
/// \endcode | ||
/// | ||
/// \headerfile <immintrin.h> | ||
/// | ||
/// This intrinsic corresponds to the \c ADC instruction. | ||
/// | ||
/// \param __cf | ||
/// The 8-bit unsigned carry flag; any non-zero value indicates carry. | ||
/// \param __x | ||
/// A 32-bit unsigned addend. | ||
/// \param __y | ||
/// A 32-bit unsigned addend. | ||
/// \param __p | ||
/// Pointer to memory for storing the sum. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarry_u32(unsigned char __cf, | ||
unsigned int __x, | ||
unsigned int __y, | ||
unsigned int *__p) { | ||
return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p); | ||
} | ||
|
||
/// Adds unsigned 32-bit integer \a __y to 0 or 1 as indicated by the carry | ||
/// flag \a __cf, and subtracts the result from unsigned 32-bit integer | ||
/// \a __x. Stores the unsigned 32-bit difference in the memory at \a __p, | ||
/// and returns the 8-bit carry-out (carry or overflow flag). | ||
/// | ||
/// \code{.operation} | ||
/// temp := (__cf == 0) ? 0 : 1 | ||
/// Store32(__p, __x - (__y + temp)) | ||
/// result := CF | ||
/// \endcode | ||
/// | ||
/// \headerfile <immintrin.h> | ||
/// | ||
/// This intrinsic corresponds to the \c SBB instruction. | ||
/// | ||
/// \param __cf | ||
/// The 8-bit unsigned carry flag; any non-zero value indicates carry. | ||
/// \param __x | ||
/// The 32-bit unsigned minuend. | ||
/// \param __y | ||
/// The 32-bit unsigned subtrahend. | ||
/// \param __p | ||
/// Pointer to memory for storing the difference. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS _subborrow_u32(unsigned char __cf, | ||
unsigned int __x, | ||
unsigned int __y, | ||
unsigned int *__p) { | ||
return __builtin_ia32_subborrow_u32(__cf, __x, __y, __p); | ||
} | ||
|
||
#ifdef __x86_64__ | ||
/// Adds unsigned 64-bit integers \a __x and \a __y, plus 0 or 1 as indicated | ||
/// by the carry flag \a __cf. Stores the unsigned 64-bit sum in the memory | ||
/// at \a __p, and returns the 8-bit carry-out (carry flag). | ||
/// | ||
/// \code{.operation} | ||
/// temp := (__cf == 0) ? 0 : 1 | ||
/// Store64(__p, __x + __y + temp) | ||
/// result := CF | ||
/// \endcode | ||
/// | ||
/// \headerfile <immintrin.h> | ||
/// | ||
/// This intrinsic corresponds to the \c ADC instruction. | ||
/// | ||
/// \param __cf | ||
/// The 8-bit unsigned carry flag; any non-zero value indicates carry. | ||
/// \param __x | ||
/// A 64-bit unsigned addend. | ||
/// \param __y | ||
/// A 64-bit unsigned addend. | ||
/// \param __p | ||
/// Pointer to memory for storing the sum. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS | ||
_addcarry_u64(unsigned char __cf, unsigned long long __x, | ||
unsigned long long __y, unsigned long long *__p) { | ||
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p); | ||
} | ||
|
||
/// Adds unsigned 64-bit integer \a __y to 0 or 1 as indicated by the carry | ||
/// flag \a __cf, and subtracts the result from unsigned 64-bit integer | ||
/// \a __x. Stores the unsigned 64-bit difference in the memory at \a __p, | ||
/// and returns the 8-bit carry-out (carry or overflow flag). | ||
/// | ||
/// \code{.operation} | ||
/// temp := (__cf == 0) ? 0 : 1 | ||
/// Store64(__p, __x - (__y + temp)) | ||
/// result := CF | ||
/// \endcode | ||
/// | ||
/// \headerfile <immintrin.h> | ||
/// | ||
/// This intrinsic corresponds to the \c ADC instruction. | ||
/// | ||
/// \param __cf | ||
/// The 8-bit unsigned carry flag; any non-zero value indicates carry. | ||
/// \param __x | ||
/// The 64-bit unsigned minuend. | ||
/// \param __y | ||
/// The 64-bit unsigned subtrahend. | ||
/// \param __p | ||
/// Pointer to memory for storing the difference. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS | ||
_subborrow_u64(unsigned char __cf, unsigned long long __x, | ||
unsigned long long __y, unsigned long long *__p) { | ||
return __builtin_ia32_subborrow_u64(__cf, __x, __y, __p); | ||
} | ||
#endif | ||
|
||
#if defined(__cplusplus) | ||
} | ||
#endif | ||
|
||
#undef __INLINE | ||
#undef __DEFAULT_FN_ATTRS | ||
|
||
#endif /* __ADCINTRIN_H */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,7 +15,8 @@ | |
#define __ADXINTRIN_H | ||
|
||
/* Define the default attributes for the functions in this file. */ | ||
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) | ||
#define __DEFAULT_FN_ATTRS \ | ||
__attribute__((__always_inline__, __nodebug__, __target__("adx"))) | ||
|
||
/* Use C++ inline semantics in C++, GNU inline for C mode. */ | ||
#if defined(__cplusplus) | ||
|
@@ -53,10 +54,10 @@ extern "C" { | |
/// \param __p | ||
/// Pointer to memory for storing the sum. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char | ||
__attribute__((__always_inline__, __nodebug__, __target__("adx"))) | ||
_addcarryx_u32(unsigned char __cf, unsigned int __x, unsigned int __y, | ||
unsigned int *__p) { | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarryx_u32(unsigned char __cf, | ||
unsigned int __x, | ||
unsigned int __y, | ||
unsigned int *__p) { | ||
return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p); | ||
} | ||
|
||
|
@@ -84,144 +85,18 @@ __INLINE unsigned char | |
/// \param __p | ||
/// Pointer to memory for storing the sum. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char | ||
__attribute__((__always_inline__, __nodebug__, __target__("adx"))) | ||
_addcarryx_u64(unsigned char __cf, unsigned long long __x, | ||
unsigned long long __y, unsigned long long *__p) { | ||
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p); | ||
} | ||
#endif | ||
|
||
/* Intrinsics that are also available if __ADX__ is undefined. */ | ||
|
||
/// Adds unsigned 32-bit integers \a __x and \a __y, plus 0 or 1 as indicated | ||
/// by the carry flag \a __cf. Stores the unsigned 32-bit sum in the memory | ||
/// at \a __p, and returns the 8-bit carry-out (carry flag). | ||
/// | ||
/// \code{.operation} | ||
/// temp := (__cf == 0) ? 0 : 1 | ||
/// Store32(__p, __x + __y + temp) | ||
/// result := CF | ||
/// \endcode | ||
/// | ||
/// \headerfile <immintrin.h> | ||
/// | ||
/// This intrinsic corresponds to the \c ADC instruction. | ||
/// | ||
/// \param __cf | ||
/// The 8-bit unsigned carry flag; any non-zero value indicates carry. | ||
/// \param __x | ||
/// A 32-bit unsigned addend. | ||
/// \param __y | ||
/// A 32-bit unsigned addend. | ||
/// \param __p | ||
/// Pointer to memory for storing the sum. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS _addcarry_u32(unsigned char __cf, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
unsigned int __x, | ||
unsigned int __y, | ||
unsigned int *__p) { | ||
return __builtin_ia32_addcarryx_u32(__cf, __x, __y, __p); | ||
} | ||
|
||
#ifdef __x86_64__ | ||
/// Adds unsigned 64-bit integers \a __x and \a __y, plus 0 or 1 as indicated | ||
/// by the carry flag \a __cf. Stores the unsigned 64-bit sum in the memory | ||
/// at \a __p, and returns the 8-bit carry-out (carry flag). | ||
/// | ||
/// \code{.operation} | ||
/// temp := (__cf == 0) ? 0 : 1 | ||
/// Store64(__p, __x + __y + temp) | ||
/// result := CF | ||
/// \endcode | ||
/// | ||
/// \headerfile <immintrin.h> | ||
/// | ||
/// This intrinsic corresponds to the \c ADC instruction. | ||
/// | ||
/// \param __cf | ||
/// The 8-bit unsigned carry flag; any non-zero value indicates carry. | ||
/// \param __x | ||
/// A 64-bit unsigned addend. | ||
/// \param __y | ||
/// A 64-bit unsigned addend. | ||
/// \param __p | ||
/// Pointer to memory for storing the sum. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS | ||
_addcarry_u64(unsigned char __cf, unsigned long long __x, | ||
unsigned long long __y, unsigned long long *__p) { | ||
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p); | ||
} | ||
#endif | ||
|
||
/// Adds unsigned 32-bit integer \a __y to 0 or 1 as indicated by the carry | ||
/// flag \a __cf, and subtracts the result from unsigned 32-bit integer | ||
/// \a __x. Stores the unsigned 32-bit difference in the memory at \a __p, | ||
/// and returns the 8-bit carry-out (carry or overflow flag). | ||
/// | ||
/// \code{.operation} | ||
/// temp := (__cf == 0) ? 0 : 1 | ||
/// Store32(__p, __x - (__y + temp)) | ||
/// result := CF | ||
/// \endcode | ||
/// | ||
/// \headerfile <immintrin.h> | ||
/// | ||
/// This intrinsic corresponds to the \c SBB instruction. | ||
/// | ||
/// \param __cf | ||
/// The 8-bit unsigned carry flag; any non-zero value indicates carry. | ||
/// \param __x | ||
/// The 32-bit unsigned minuend. | ||
/// \param __y | ||
/// The 32-bit unsigned subtrahend. | ||
/// \param __p | ||
/// Pointer to memory for storing the difference. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS _subborrow_u32(unsigned char __cf, | ||
unsigned int __x, | ||
unsigned int __y, | ||
unsigned int *__p) { | ||
return __builtin_ia32_subborrow_u32(__cf, __x, __y, __p); | ||
} | ||
|
||
#ifdef __x86_64__ | ||
/// Adds unsigned 64-bit integer \a __y to 0 or 1 as indicated by the carry | ||
/// flag \a __cf, and subtracts the result from unsigned 64-bit integer | ||
/// \a __x. Stores the unsigned 64-bit difference in the memory at \a __p, | ||
/// and returns the 8-bit carry-out (carry or overflow flag). | ||
/// | ||
/// \code{.operation} | ||
/// temp := (__cf == 0) ? 0 : 1 | ||
/// Store64(__p, __x - (__y + temp)) | ||
/// result := CF | ||
/// \endcode | ||
/// | ||
/// \headerfile <immintrin.h> | ||
/// | ||
/// This intrinsic corresponds to the \c ADC instruction. | ||
/// | ||
/// \param __cf | ||
/// The 8-bit unsigned carry flag; any non-zero value indicates carry. | ||
/// \param __x | ||
/// The 64-bit unsigned minuend. | ||
/// \param __y | ||
/// The 64-bit unsigned subtrahend. | ||
/// \param __p | ||
/// Pointer to memory for storing the difference. | ||
/// \returns The 8-bit unsigned carry-out value. | ||
__INLINE unsigned char __DEFAULT_FN_ATTRS | ||
_subborrow_u64(unsigned char __cf, unsigned long long __x, | ||
_addcarryx_u64(unsigned char __cf, unsigned long long __x, | ||
unsigned long long __y, unsigned long long *__p) { | ||
return __builtin_ia32_subborrow_u64(__cf, __x, __y, __p); | ||
return __builtin_ia32_addcarryx_u64(__cf, __x, __y, __p); | ||
} | ||
#endif | ||
|
||
#if defined(__cplusplus) | ||
} | ||
#endif | ||
|
||
#undef __INLINE | ||
#undef __DEFAULT_FN_ATTRS | ||
|
||
#endif /* __ADXINTRIN_H */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -580,9 +580,13 @@ _storebe_i64(void * __P, long long __D) { | |
#include <cetintrin.h> | ||
#endif | ||
|
||
/* Some intrinsics inside adxintrin.h are available only on processors with ADX, | ||
* whereas others are also available at all times. */ | ||
Comment on lines
-583
to
-584
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, just noticed this. Since we removed the comments, should we use the same format for
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Up to you. I felt the header names imply that Let me know and I can add a, "/* Intrinsics inside adcintrin.h are available at all times. */", comment above
I didn't protect For For I can guard this header now if desired. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think comment is good. Without it, people may wonder anything special here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Confirmed that Intel ADX is supported on Ryzen. I checked the Sony PS5 compiler on my work pc and confirmed that |
||
/* Intrinsics inside adcintrin.h are available at all times. */ | ||
#include <adcintrin.h> | ||
|
||
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ | ||
defined(__ADX__) | ||
#include <adxintrin.h> | ||
#endif | ||
|
||
#if !(defined(_MSC_VER) || defined(__SCE__)) || __has_feature(modules) || \ | ||
defined(__RDSEED__) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(minor) You could put this back with
__attribute__((__always_inline__, __nodebug__, __target__("adx")))
and now use it for the ADX intrinsics.