Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Unexpected codegen for __builtin_elementwise_bitreverse on unsigned char and short #84047

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

Closed
shafik opened this issue Mar 5, 2024 · 7 comments · Fixed by #119423
Closed

Unexpected codegen for __builtin_elementwise_bitreverse on unsigned char and short #84047

shafik opened this issue Mar 5, 2024 · 7 comments · Fixed by #119423
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema"

Comments

@shafik
Copy link
Collaborator

shafik commented Mar 5, 2024

Given the following: https://godbolt.org/z/M1hEqs9q5

unsigned char f(unsigned char a) {
  return __builtin_elementwise_bitreverse(a);
}

unsigned short f(unsigned short a) {
  return __builtin_elementwise_bitreverse(a);
}

signed char f3(signed char a) {
  return __builtin_elementwise_bitreverse(a);
}

signed short f3(signed short a) {
  return __builtin_elementwise_bitreverse(a);
}

for the unsigned char and unsigned short cases it automatically returns 0 w/ any level of optimization e.g.

define dso_local noundef zeroext i8 @f(unsigned char)(i8 noundef zeroext %a) local_unnamed_addr {
entry:
  tail call void @llvm.dbg.value(metadata i8 %a, metadata !16, metadata !DIExpression())
  ret i8 0
}

Based on the documentation: https://clang.llvm.org/docs/LanguageExtensions.html

This is not expected behavior.

@topperc
Copy link
Collaborator

topperc commented Mar 5, 2024

Seems like its zext the input and calling the i32 bitreverse.

I thought the __builtin_elementwise* were for vectors, not scalars?

@shafik
Copy link
Collaborator Author

shafik commented Mar 5, 2024

Seems like its zext the input and calling the i32 bitreverse.

I thought the __builtin_elementwise* were for vectors, not scalars?

Documentation says:

For scalar types, consider the operation applied to a vector with a single element.

@EugeneZelenko EugeneZelenko added clang:codegen IR generation bugs: mangling, exceptions, etc. and removed new issue labels Mar 5, 2024
@llvmbot
Copy link
Member

llvmbot commented Mar 5, 2024

@llvm/issue-subscribers-clang-codegen

Author: Shafik Yaghmour (shafik)

Given the following: https://godbolt.org/z/M1hEqs9q5
unsigned char f(unsigned char a) {
  return __builtin_elementwise_bitreverse(a);
}

unsigned short f(unsigned short a) {
  return __builtin_elementwise_bitreverse(a);
}

signed char f3(signed char a) {
  return __builtin_elementwise_bitreverse(a);
}

signed short f3(signed short a) {
  return __builtin_elementwise_bitreverse(a);
}

for the unsigned char and unsigned short cases it automatically returns 0 w/ any level of optimization e.g.

define dso_local noundef zeroext i8 @<!-- -->f(unsigned char)(i8 noundef zeroext %a) local_unnamed_addr {
entry:
  tail call void @<!-- -->llvm.dbg.value(metadata i8 %a, metadata !16, metadata !DIExpression())
  ret i8 0
}

Based on the documentation: https://clang.llvm.org/docs/LanguageExtensions.html

This is not expected behavior.

@shafik
Copy link
Collaborator Author

shafik commented Mar 11, 2024

If I look closer the documentation does say the implementation is incomplete but does not specify:

Note: The implementation of vector builtins is work-in-progress and incomplete.

In addition to the operators mentioned above, Clang provides a set of builtins to perform additional operations on certain scalar and vector types.

Let T be one of the following types:

an integer type (as in C23 6.2.5p22), but excluding enumerated types and bool

...
For scalar types, consider the operation applied to a vector with a single element.

but nothing indicates it should not work w/ unsigned char or unsigned short

@shafik
Copy link
Collaborator Author

shafik commented Mar 11, 2024

CC @bob80905 @arsenm

@RKSimon
Copy link
Collaborator

RKSimon commented Dec 20, 2024

CC @frasercrmck who hit this in #119423

@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed clang:codegen IR generation bugs: mangling, exceptions, etc. labels Jan 29, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 29, 2025

@llvm/issue-subscribers-clang-frontend

Author: Shafik Yaghmour (shafik)

Given the following: https://godbolt.org/z/M1hEqs9q5
unsigned char f(unsigned char a) {
  return __builtin_elementwise_bitreverse(a);
}

unsigned short f(unsigned short a) {
  return __builtin_elementwise_bitreverse(a);
}

signed char f3(signed char a) {
  return __builtin_elementwise_bitreverse(a);
}

signed short f3(signed short a) {
  return __builtin_elementwise_bitreverse(a);
}

for the unsigned char and unsigned short cases it automatically returns 0 w/ any level of optimization e.g.

define dso_local noundef zeroext i8 @<!-- -->f(unsigned char)(i8 noundef zeroext %a) local_unnamed_addr {
entry:
  tail call void @<!-- -->llvm.dbg.value(metadata i8 %a, metadata !16, metadata !DIExpression())
  ret i8 0
}

Based on the documentation: https://clang.llvm.org/docs/LanguageExtensions.html

This is not expected behavior.

fhahn pushed a commit to swiftlang/llvm-project that referenced this issue Apr 8, 2025
)

This commit restricts the use of scalar types in vector math builtins,
particularly the `__builtin_elementwise_*` builtins.

Previously, small scalar integer types would be promoted to `int`, as
per the usual conversions. This would silently do the wrong thing for
certain operations, such as `add_sat`, `popcount`, `bitreverse`, and
others. Similarly, since unsigned integer types were promoted to `int`,
something like `add_sat(unsigned char, unsigned char)` would perform a
*signed* operation.

With this patch, promotable scalar integer types are not promoted to
int, and are kept intact. If any of the types differ in the binary and
ternary builtins, an error is issued. Similarly an error is issued if
builtins are supplied integer types of different signs. Mixing enums of
different types in binary/ternary builtins now consistently raises an
error in all language modes.

This brings the behaviour surrounding scalar types more in line with
that of vector types. No change is made to vector types, which are both
not promoted and whose element types must match.

Fixes llvm#84047.

RFC:
https://discourse.llvm.org/t/rfc-change-behaviour-of-elementwise-builtins-on-scalar-integer-types/83725
fhahn pushed a commit to fhahn/llvm-project that referenced this issue May 8, 2025
)

This commit restricts the use of scalar types in vector math builtins,
particularly the `__builtin_elementwise_*` builtins.

Previously, small scalar integer types would be promoted to `int`, as
per the usual conversions. This would silently do the wrong thing for
certain operations, such as `add_sat`, `popcount`, `bitreverse`, and
others. Similarly, since unsigned integer types were promoted to `int`,
something like `add_sat(unsigned char, unsigned char)` would perform a
*signed* operation.

With this patch, promotable scalar integer types are not promoted to
int, and are kept intact. If any of the types differ in the binary and
ternary builtins, an error is issued. Similarly an error is issued if
builtins are supplied integer types of different signs. Mixing enums of
different types in binary/ternary builtins now consistently raises an
error in all language modes.

This brings the behaviour surrounding scalar types more in line with
that of vector types. No change is made to vector types, which are both
not promoted and whose element types must match.

Fixes llvm#84047.

RFC:
https://discourse.llvm.org/t/rfc-change-behaviour-of-elementwise-builtins-on-scalar-integer-types/83725
fhahn pushed a commit to fhahn/llvm-project that referenced this issue May 12, 2025
)

This commit restricts the use of scalar types in vector math builtins,
particularly the `__builtin_elementwise_*` builtins.

Previously, small scalar integer types would be promoted to `int`, as
per the usual conversions. This would silently do the wrong thing for
certain operations, such as `add_sat`, `popcount`, `bitreverse`, and
others. Similarly, since unsigned integer types were promoted to `int`,
something like `add_sat(unsigned char, unsigned char)` would perform a
*signed* operation.

With this patch, promotable scalar integer types are not promoted to
int, and are kept intact. If any of the types differ in the binary and
ternary builtins, an error is issued. Similarly an error is issued if
builtins are supplied integer types of different signs. Mixing enums of
different types in binary/ternary builtins now consistently raises an
error in all language modes.

This brings the behaviour surrounding scalar types more in line with
that of vector types. No change is made to vector types, which are both
not promoted and whose element types must match.

Fixes llvm#84047.

RFC:
https://discourse.llvm.org/t/rfc-change-behaviour-of-elementwise-builtins-on-scalar-integer-types/83725
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema"
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants