Skip to content
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

more complete sparc64 ABI fix for aggregates with floating point members #94216

Merged
merged 3 commits into from
Feb 28, 2022

Conversation

psumbera
Copy link
Contributor

Previous fix didn't handle nested structures at all.

Previous fix didn't handle nested structures at all.
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Feb 21, 2022
@rust-highfive
Copy link
Collaborator

r? @matthewjasper

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 21, 2022
@rust-log-analyzer

This comment has been minimized.

@nagisa
Copy link
Member

nagisa commented Feb 21, 2022

This definitely would benefit from some additional test coverage.

@psumbera
Copy link
Contributor Author

This definitely would benefit from some additional test coverage.

Yes. My main test was to build Firefox. With my previous fix there was some improvement. But later I have found that there was also regression and part of what started to work was rather coincidence. This time newly Firefox Webrender started work and all previous known issues remain resolved.

The issue with tests is that they won't cover everything.

I have used following tests here:
https://github.com/psumbera/rust-sparc64-abi-tests

Note that these tests are not platform specific. I mean there could be teoretically also other platforms which could benefit from them.

So I'm not entirely sure how to proceed here. What do you exactly suggest?

@nagisa
Copy link
Member

nagisa commented Feb 21, 2022

I would like to see codegen tests at least for the cases that involve the problematic nested structures in question. Either LLVM or assembly works (much like what was added in #91003) It is OK if they aren't 100% exhaustive, as the primary purpose is for them to act as a regression test.

A run-pass test based on your test code is also a welcome addition. Especially if running the entire rustc test suite on sparc passed without any failures before this fix.

@psumbera
Copy link
Contributor Author

@nagisa is it ok now with one test case added?

@nagisa
Copy link
Member

nagisa commented Feb 27, 2022

r? @nagisa

@bors r+

NB: I didn't dig into the changes very deeply. I don't have a SPARC ABI document on hand and most of the stuff I saw, while complicated, seemed reasonable in isolation. Since this is a T2/3 target and @psumbera has been one of the very few parties interested in maintaining the target, I'm inclined to trust them implicitly that this is an improvement over the status quo.

@bors
Copy link
Contributor

bors commented Feb 27, 2022

📌 Commit 992c27c has been approved by nagisa

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 27, 2022
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Feb 28, 2022
more complete sparc64 ABI fix for aggregates with floating point members

Previous fix didn't handle nested structures at all.
@bors
Copy link
Contributor

bors commented Feb 28, 2022

⌛ Testing commit 992c27c with merge edda7e9...

@bors
Copy link
Contributor

bors commented Feb 28, 2022

☀️ Test successful - checks-actions
Approved by: nagisa
Pushing edda7e9 to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Feb 28, 2022
@bors bors merged commit edda7e9 into rust-lang:master Feb 28, 2022
@rustbot rustbot added this to the 1.61.0 milestone Feb 28, 2022
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (edda7e9): comparison url.

Summary: This benchmark run did not return any relevant results. 2 results were found to be statistically significant but too small to be relevant.

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

@rustbot label: -perf-regression

Comment on lines +82 to +94
if scalar1.value == abi::F32 {
offset += Reg::f32().size;
} else if scalar2.value == abi::F64 {
offset += Reg::f64().size;
} else if let abi::Int(i, _signed) = scalar1.value {
offset += i.size();
} else if scalar1.value == abi::Pointer {
offset = offset + Reg::i64().size;
}

// This doesn't intentionally handle structures with floats which needs
// special care below.
if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
arg.cast_to(uniform);
return;
if (offset.raw % 4) != 0 && (scalar2.value == abi::F32 || scalar2.value == abi::F64) {
offset.raw += 4 - (offset.raw % 4);
}
Copy link
Member

Choose a reason for hiding this comment

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

There's three issues here:

  • Abi::ScalarPair should not be special-cased in call ABIs - it's just Abi::Aggregate with extra Rust-only optimizations tacked on (none of the other issues matter if the parse_structure codepath is taken)
  • this is not how one computes the offset of the second scalar for an Abi::ScalarPair (scalar1.size(cx).align_to(scalar2.align(cx).abi) is more or less the typical formula, anything else risks being wrong for certain scalars)
  • else if scalar2.value == abi::F64 is probably a typo? certainly seems like the intention is to get the size of scalar1 (which is just scalar1.size(cx))

As it stands, I believe this code passes (u128, f64) incorrectly (thanks to alignment, I can't think of anything else that would be mismatched), so it was probably unobserved for that reason.

Comment on lines +118 to 121
for i in 0..layout.fields.count().clone() {
if offset < layout.fields.offset(i) {
offset = layout.fields.offset(i);
}
Copy link
Member

Choose a reason for hiding this comment

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

This is a silent failure (it will cause data corruption AFAICT). If the fields aren't in ascending order, this is a non-C-friendly type and you have to either ICE (which is arguably unfriendly), or better just fall back to "this cannot be passed in any optimized way".

Sadly SPARC64 seems to be one of the architectures unfortunate enough to use "turn struct into as many immediate arguments as needed", instead of byval, for on-stack passing.

But still, you could use something similar to the Union case handled a bit above.

Actually, wait, this is wronger than I thought, it doesn't add field offsets to the enclosing struct's offset, just replaces it altogether.

There's no way the testcases added in this PR could work, I think it's just hitting all the silent failure modes around here and last_offset and accidentally causing the right output...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for looking at it! I'm sure there are problems with my fix.
I was testing it with: https://github.com/psumbera/rust-sparc64-abi-tests
So maybe you can come with sample code which will not work.
Or If you are willing to help with your expertise it I'm ready to provide SPARC testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants