-
Notifications
You must be signed in to change notification settings - Fork 14.6k
[clang] improve consistency with GCC vector comparison #148954
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
base: main
Are you sure you want to change the base?
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang Author: Imple Lee (ImpleLee) Changesfixes issue #132604 GCC's order of types of vector comparison should be Full diff: https://github.com/llvm/llvm-project/pull/148954.diff 3 Files Affected:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a3f534ee6712e..8a81cda9912f7 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -12901,24 +12901,24 @@ QualType Sema::GetSignedVectorType(QualType V) {
return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements());
}
- if (TypeSize == Context.getTypeSize(Context.Int128Ty))
- return Context.getVectorType(Context.Int128Ty, VTy->getNumElements(),
- VectorKind::Generic);
- if (TypeSize == Context.getTypeSize(Context.LongLongTy))
- return Context.getVectorType(Context.LongLongTy, VTy->getNumElements(),
- VectorKind::Generic);
- if (TypeSize == Context.getTypeSize(Context.LongTy))
- return Context.getVectorType(Context.LongTy, VTy->getNumElements(),
- VectorKind::Generic);
if (TypeSize == Context.getTypeSize(Context.IntTy))
return Context.getVectorType(Context.IntTy, VTy->getNumElements(),
VectorKind::Generic);
+ if (TypeSize == Context.getTypeSize(Context.SignedCharTy))
+ return Context.getVectorType(Context.SignedCharTy, VTy->getNumElements(),
+ VectorKind::Generic);
if (TypeSize == Context.getTypeSize(Context.ShortTy))
return Context.getVectorType(Context.ShortTy, VTy->getNumElements(),
VectorKind::Generic);
- assert(TypeSize == Context.getTypeSize(Context.CharTy) &&
+ if (TypeSize == Context.getTypeSize(Context.LongTy))
+ return Context.getVectorType(Context.LongTy, VTy->getNumElements(),
+ VectorKind::Generic);
+ if (TypeSize == Context.getTypeSize(Context.LongLongTy))
+ return Context.getVectorType(Context.LongLongTy, VTy->getNumElements(),
+ VectorKind::Generic);
+ assert(TypeSize == Context.getTypeSize(Context.Int128Ty) &&
"Unhandled vector element size in vector compare");
- return Context.getVectorType(Context.CharTy, VTy->getNumElements(),
+ return Context.getVectorType(Context.Int128Ty, VTy->getNumElements(),
VectorKind::Generic);
}
diff --git a/clang/test/Sema/vector-gcc-compat.c b/clang/test/Sema/vector-gcc-compat.c
index 7764b3bf686ad..7d9d25019666c 100644
--- a/clang/test/Sema/vector-gcc-compat.c
+++ b/clang/test/Sema/vector-gcc-compat.c
@@ -3,6 +3,8 @@
// Test the compatibility of clang's vector extensions with gcc's vector
// extensions for C. Notably &&, ||, ?: and ! are not available.
typedef long long v2i64 __attribute__((vector_size(16)));
+// this type is specifically used as the result type of comparison of v2i64
+typedef long v2i_long __attribute__((vector_size(16)));
typedef int v2i32 __attribute__((vector_size(8)));
typedef short v2i16 __attribute__((vector_size(4)));
typedef char v2i8 __attribute__((vector_size(2)));
@@ -81,7 +83,7 @@ void arithmeticTest(void) {
void comparisonTest(void) {
v2i64 v2i64_a = (v2i64){0, 1};
- v2i64 v2i64_r;
+ v2i_long v2i64_r;
v2i64_r = v2i64_a == 1;
v2i64_r = v2i64_a != 1;
@@ -166,7 +168,7 @@ void floatTestConstantComparison(void) {
void doubleTestConstantComparison(void) {
v2f64 v2f64_a = {0.4, 0.4};
- v2i64 v2i64_r;
+ v2i_long v2i64_r;
v2i64_r = v2f64_a > 0.4;
v2i64_r = v2f64_a >= 0.4;
v2i64_r = v2f64_a < 0.4;
diff --git a/clang/test/Sema/vector-gcc-compat.cpp b/clang/test/Sema/vector-gcc-compat.cpp
index 42c24d91ea8f3..e66cee128cd90 100644
--- a/clang/test/Sema/vector-gcc-compat.cpp
+++ b/clang/test/Sema/vector-gcc-compat.cpp
@@ -5,6 +5,8 @@
// || operators work on vector types.
typedef long long v2i64 __attribute__((vector_size(16))); // expected-warning {{'long long' is incompatible with C++98}}
+// this type is specifically used as the result type of comparison of v2i64
+typedef long v2i_long __attribute__((vector_size(16)));
typedef int v2i32 __attribute__((vector_size(8)));
typedef short v2i16 __attribute__((vector_size(4)));
typedef char v2i8 __attribute__((vector_size(2)));
@@ -60,7 +62,7 @@ void arithmeticTest(void) {
void comparisonTest(void) {
v2i64 v2i64_a = (v2i64){0, 1}; // expected-warning {{compound literals are a C99-specific feature}}
- v2i64 v2i64_r;
+ v2i_long v2i64_r;
v2i64_r = v2i64_a == 1;
v2i64_r = v2i64_a != 1;
@@ -141,7 +143,7 @@ void floatTestConstantComparison(void) {
void doubleTestConstantComparison(void) {
v2f64 v2f64_a = {0.4, 0.4};
- v2i64 v2i64_r;
+ v2i_long v2i64_r;
v2i64_r = v2f64_a > 0.4;
v2i64_r = v2f64_a >= 0.4;
v2i64_r = v2f64_a < 0.4;
|
Originally posted by @zygoloid in #132604 I now prefer this proposal over the current PR. I will convert this PR into a draft PR when implementing it, and ask for review again after that. |
They seem to be the same in GCC
Now I make a utility function There is currently no test about this, but I don't know how to or even whether should I write relevant tests. There are many other places in clang that uses |
/// int > signed char > short > long > long long > int128_t | ||
/// Returns empty type if there is no appropriate target types. | ||
QualType getGCCCompatibleIntTypeForBitwidth(unsigned DestWidth, | ||
unsigned Signed) const; |
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.
unsigned Signed) const; | |
bool Signed) const; |
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.
The parameters are intentionally the same as the parameters of getIntTypeForBitwidth
.
llvm-project/clang/include/clang/AST/ASTContext.h
Lines 877 to 882 in abce4e9
/// getIntTypeForBitwidth - | |
/// sets integer QualTy according to specified details: | |
/// bitwidth, signed/unsigned. | |
/// Returns empty type if there is no appropriate target types. | |
QualType getIntTypeForBitwidth(unsigned DestWidth, | |
unsigned Signed) const; |
Is this a tradition in LLVM? Or I should just use bool
here?
/// int > signed char > short > long > long long > int128_t | ||
/// Returns empty type if there is no appropriate target types. | ||
QualType ASTContext::getGCCCompatibleIntTypeForBitwidth(unsigned DestWidth, | ||
unsigned Signed) const { |
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.
unsigned Signed) const { | |
bool Signed) const { |
return Signed ? LongLongTy : UnsignedLongLongTy; | ||
if (DestWidth == 128) | ||
return Signed ? Int128Ty : UnsignedInt128Ty; | ||
return {}; |
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.
We should probably assert if we don't find one.
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.
The behavior of returning an empty
or null
type is also intentionally kept the same as getIntTypeForBitwidth
. Maybe keeping this behavior can make this function a better in-place replacement of getIntTypeForBitwidth
?
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.
LGTM sans the nits already pointed out. Thanks!
/// bitwidth, signed/unsigned. | ||
/// this function is compatible with GCC's preference: | ||
/// int > signed char > short > long > long long > int128_t | ||
/// Returns empty type if there is no appropriate target types. |
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.
/// Returns empty type if there is no appropriate target types. | |
/// Returns null type if there is no appropriate target types. |
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.
The term empty type
is also used in documentation of getIntTypeForBitwidth
and getRealTypeForBitwidth
series. I guess keeping them unified is probably better?
llvm-project/clang/include/clang/AST/ASTContext.h
Lines 877 to 888 in abce4e9
/// getIntTypeForBitwidth - | |
/// sets integer QualTy according to specified details: | |
/// bitwidth, signed/unsigned. | |
/// Returns empty type if there is no appropriate target types. | |
QualType getIntTypeForBitwidth(unsigned DestWidth, | |
unsigned Signed) const; | |
/// getRealTypeForBitwidth - | |
/// sets floating point QualTy according to specified bitwidth. | |
/// Returns empty type if there is no appropriate target types. | |
QualType getRealTypeForBitwidth(unsigned DestWidth, | |
FloatModeKind ExplicitType) const; |
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.
Yeah okay, that's pre-existing inconsistency (because in QualType itself we call this state 'Null'), so leaving it as 'empty' here is fine.
fixes issue #132604
GCC's preference of vector comparison types should be
int > signed char > short > long > long long
, so I just duplicate that.reference: gcc-help mailing list: https://gcc.gnu.org/pipermail/gcc-help/2025-July/144357.html