Skip to content

[clang] Implement constexpr bit_cast for vectors #66894

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

Merged
merged 2 commits into from
Oct 30, 2023

Conversation

DaMatrix
Copy link
Contributor

This makes __builtin_bit_cast support converting to and from vector types in a constexpr context.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 20, 2023
Copy link
Collaborator

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally this looks good to me, but doesn't seem to properly handle __attribute__((ext_vector_type(N))) bool.

@DaMatrix DaMatrix force-pushed the constexpr-vector-bit-cast branch 2 times, most recently from 99d894e to cb7e616 Compare September 21, 2023 20:16
@DaMatrix DaMatrix force-pushed the constexpr-vector-bit-cast branch from cb7e616 to 61f1f5f Compare September 21, 2023 20:33
@DaMatrix DaMatrix force-pushed the constexpr-vector-bit-cast branch from 61f1f5f to 8768741 Compare September 24, 2023 11:53
@DaMatrix
Copy link
Contributor Author

While attempting to make the result properly endianness-dependent, I noticed that VectorExprEvaluator::VisitCastExpr with CK_BitCast already had code for this which takes the byte ordering into account (although it also didn't handle bool vectors correctly either). I've now moved the existing Vector<->APInt bit casting code into a pair of separate methods, and made both CK_BitCast and the new bit casting code use those.

Copy link
Collaborator

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I like the code reuse! There are some minor optimization and simplification opportunities in the code you're reusing that might be worth addressing now.

I'm worried that vectors with padding (which I think is only vectors of x86 long double) might not be being treated properly by bit_cast here. It's probably a bit awkward to fix, given the new approach, but maybe we can handle the padding separately from the conversion of the vector to/from APInt.

@DaMatrix DaMatrix force-pushed the constexpr-vector-bit-cast branch 2 times, most recently from c05ee51 to f24c57f Compare October 3, 2023 14:06
zygoloid
zygoloid previously approved these changes Oct 4, 2023
Copy link
Collaborator

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, looks good. Just a couple of minor suggestions.

@DaMatrix DaMatrix force-pushed the constexpr-vector-bit-cast branch from f24c57f to f05f52e Compare October 9, 2023 08:07
@DaMatrix DaMatrix force-pushed the constexpr-vector-bit-cast branch from f05f52e to 95c018c Compare October 10, 2023 08:18
@llvmbot llvmbot added the clang:codegen IR generation bugs: mangling, exceptions, etc. label Oct 10, 2023
Copy link
Collaborator

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, other than the handling of x86_fp80, which doesn't seem to match Clang's current runtime behavior.

@zygoloid zygoloid dismissed their stale review October 11, 2023 06:57

Review of older changes

@DaMatrix DaMatrix force-pushed the constexpr-vector-bit-cast branch from 95c018c to 72f63b6 Compare October 19, 2023 08:10
Copy link
Collaborator

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this looks good to me other than a small test coverage (see comment) / diagnostic wording issue.

(For future reference, please don't force-push to PR branches; that makes it much harder for your reviewer to see what's changed since their last review and can cause github to lose track of comments. See https://llvm.org/docs/GitHub.html#updating-pull-requests)

Comment on lines +147 to +148
//static v12i16 b = (v12i16)(v2f80){1,2};
//static v2f80 c = (v2f80)(v12i16){0,0,0,-32768,16383,0,0,0,0,-32768,16384,0};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add some test coverage that we properly diagnose this situation.

I think we'll produce a diagnostic mentioning bit_cast, which is probably not what we want here. Maybe the simplest thing to do to fix that would be to replace bit_cast with bit cast in all the diagnostics. That seems at least as good for the std::bit_cast / __builtin_bit_cast case, and better for the vector cast case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, uncommenting these lines doesn't cause any diagnostic messages to be generated, only an error stating error: initializer element is not a compile-time constant. I'll see if I can get the diagnostic to be output and change the messages as suggested.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, on further investigation, it looks like the diagnostic isn't being emitted at all because the constant evaluation code is called with an EvalInfo which has diagnostics disabled, and is never called again.

https://github.com/llvm/llvm-project/blob/72f63b695c9ebd9c7032c4b754ff7965c28fad5c/clang/lib/AST/Expr.cpp#L3486
https://github.com/llvm/llvm-project/blob/72f63b695c9ebd9c7032c4b754ff7965c28fad5c/clang/lib/AST/ExprConstant.cpp#L15483-L15485

And once it's been evaluted with no diagnostic, an diag::err_init_element_not_constant is emitted which triggers an error and so it never gets evaluated again with diagnostics enabled.

https://github.com/llvm/llvm-project/blob/72f63b695c9ebd9c7032c4b754ff7965c28fad5c/clang/lib/Sema/SemaDecl.cpp#L12510-L12514

What should I do here? This feels like a weakness of the code in Sema; any changes I make here are going to break a bunch of tests which expect no diagnostics to be output in these cases.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps you could add a C++ testcass with the variable declared constexpr.

@DaMatrix DaMatrix force-pushed the constexpr-vector-bit-cast branch from 32cbfd1 to e23b362 Compare October 24, 2023 08:59
Copy link
Collaborator

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, LGTM

@DaMatrix
Copy link
Contributor Author

DaMatrix commented Oct 30, 2023

@zygoloid since no one else has added any comments, can you commit this? I don't have write access to the repository.

@zygoloid zygoloid merged commit b45236f into llvm:main Oct 30, 2023
@DaMatrix DaMatrix deleted the constexpr-vector-bit-cast branch October 31, 2023 06:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants