c-variadic: use emit_ptr_va_arg for mips#152576
c-variadic: use emit_ptr_va_arg for mips#152576rust-bors[bot] merged 2 commits intorust-lang:mainfrom
emit_ptr_va_arg for mips#152576Conversation
|
|
| bx, | ||
| addr, | ||
| target_ty, | ||
| PassMode::Direct, |
There was a problem hiding this comment.
Nothing in the LLVM implementation suggests a double load. byval is not handled.
There was a problem hiding this comment.
and there is no conditional logic based on the size either
| match bx.tcx().sess.target.pointer_width { | ||
| 32 => SlotSize::Bytes4, | ||
| 64 => SlotSize::Bytes8, | ||
| _ => unreachable!(), | ||
| }, |
There was a problem hiding this comment.
based on
unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4;There was a problem hiding this comment.
...Hm, but
(ABI.IsN32() || ABI.IsN64()) ? 8 : 4;evaluates to 8 if N32 or N64 is true, no? And N32 is an ILP32 ABI despite having 64-bit registers available, if I understand correctly.
There was a problem hiding this comment.
Is this correct anyways for the targets we actually support? A comment might be desired about the frumious "N32" ABI, if so.
There was a problem hiding this comment.
It is correct for our current targets, but we can match the LLVM logic more based on
I've implemented that now.
| 64 => SlotSize::Bytes8, | ||
| _ => unreachable!(), | ||
| }, | ||
| AllowHigherAlign::Yes, |
There was a problem hiding this comment.
Because the code allows, and corrects for, a higher alignment
if (Align > getMinStackArgumentAlignment()) {| match bx.tcx().sess.target.endian { | ||
| Endian::Big => ForceRightAdjust::Yes, | ||
| Endian::Little => ForceRightAdjust::No, | ||
| }, |
There was a problem hiding this comment.
there is a whole comment about this
// In big-endian mode we must adjust the pointer when the load size is smaller
// than the argument slot size. We must also reduce the known alignment to
// match. For example in the N64 ABI, we must add 4 bytes to the offset to get
// the correct half of the slot, and reduce the alignment from 8 (slot
// alignment) down to 4 (type alignment).
There was a problem hiding this comment.
Something to this effect seems rather helpful to have in a code comment rather than a review comment? Ditto for align comment, I don't think that's all going to be obvious when somebody reads this code.
ForceRightAdjust could also use some documentation, I needed to dig a bit to figure out its intended purpose. (same for AllowHigherAlign though that one is more obvious)
|
Pinging some target maintainers: @Gelbpunkt @wzssyqa @chenx97 @709924470 @Cyanoxygen @Fearyncess Mostly this is just a heads-up. You could try to run (with your target) this test to be sure that it all works: this likely needs some sort of config in [target.mips64-unknown-linux-gnuabi64]
runner = "qemu-mips64 -L /usr/mips64-linux-gnuabi64"
[target.mipsel-unknown-linux-gnu]
runner = "qemu-mipsel -cpu 24Kf -L /usr/mipsel-linux-gnu"
[target.mips-unknown-linux-gnu]
runner = "qemu-mips -L /usr/mips-linux-gnu" |
This comment has been minimized.
This comment has been minimized.
|
r? tgross35 |
|
|
|
Do we have any asm tests for varargs that could be extended to this target? Unfortunately I don't know much about this area of code and I'm not positive what effects I should actually be looking for. |
|
We don't, but I could add some. Really I think what we're looking for is whether the mips implementation subtly deviates from what I'll also just extract the non-mips changes, they were combined for convenience but not it probably makes more sense to split them up. |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
this will need a rebase after the currently in flight PR merges, so it's not quite ready yet, but I added an extra commit that captures what assembly LLVM generates, and then an updated version with the rustc implementation.
on 32-bit mips that leads to a slightly nasty diff no matter what I do, but I believe it is in fact equivalent.
| // mips64el-NEXT: lw $1, 0($1) | ||
| // mips64el-NEXT: lw $2, 0($1) | ||
| // mips64el-NEXT: jr $ra | ||
| // mips64el-NEXT: sll $2, $1, 0 | ||
| // mips64el-NEXT: nop |
There was a problem hiding this comment.
the rust versions stores the value into $2 directly, clang emits this weird "shift by zero" instruction, essentially a move, that has the same effect.
| // mips: lw $1, 0($4) | ||
| // mips-NEXT: addiu $2, $zero, 4 | ||
| // mips-NEXT: addiu $1, $1, 7 | ||
| // mips-NEXT: move $3, $1 | ||
| // mips-NEXT: ins $3, $2, 0, 3 | ||
| // mips-NEXT: addiu $2, $zero, -8 | ||
| // mips-NEXT: addiu $1, $1, 7 | ||
| // mips-NEXT: and $2, $1, $2 | ||
| // mips-NEXT: addiu $3, $2, 8 | ||
| // mips-NEXT: sw $3, 0($4) | ||
| // mips-NEXT: and $1, $1, $2 | ||
| // mips-NEXT: lw $2, 0($1) | ||
| // mips-NEXT: addiu $1, $3, 4 | ||
| // mips-NEXT: sw $1, 0($4) | ||
| // mips-NEXT: lw $3, 0($3) | ||
| // mips-NEXT: addiu $3, $zero, 4 | ||
| // mips-NEXT: lw $2, 0($2) | ||
| // mips-NEXT: ins $1, $3, 0, 3 | ||
| // mips-NEXT: lw $3, 0($1) | ||
| // mips-NEXT: jr $ra | ||
| // mips-NEXT: nop |
There was a problem hiding this comment.
I stared at this for a long time, and am fairly confident these are equivalent. The equivalence is easier to see on godbolt which compiles this slightly differently (I don't know why, but both should be valid compilations for the target)
https://godbolt.org/z/h7WxPE58n
The original version calculates a pointer to the second word, and writes that back into ap, but the value is never used and ap is later overwritten.
ori $2, $1, 4 # $2 = aligned + 4
addiu $3, $1, 8 # $3 = aligned + 8
sw $2, 0($4) # *ap = aligned + 4
lw $2, 0($1) # $2 = *$1
sw $3, 0($4) # *ap = aligned + 8
lw $3, 4($1) # $3 = *($1 + 4)
versus
addiu $2, $1, 8 # $2 = aligned + 8
sw $2, 0($4) # *ap = aligned + 8
lw $2, 0($1) # $2 = *$1
lw $3, 4($1) # $3 = *($1 + 4)
This comment has been minimized.
This comment has been minimized.
…ross35 c-variadic: `va_arg` fixes tracking issue: rust-lang#44930 extracts some generic LLVM `va_arg` fixes from rust-lang#152576 and rust-lang#155429. r? tgross35
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
I can barely read the mips assembly but think it serves the purpose of making sure we don't accidentally change implementations. One request here with the naming, and the request above to turn the review notes into comments, then r=me.
(Thanks for separating test addition from doing the update, made it easy to see what changed)
There was a problem hiding this comment.
Any thought on making this c-variadic.rs and then eventually merging in the ARM version and others? Since many arches need the same test cases I'm not sure it's worth duplicating the setup.
There was a problem hiding this comment.
I'd rather keep them separate per-arch, working with these files is already not that fun when they do need updating. We could put them in their own directory
There was a problem hiding this comment.
Reasonable enough, +1 to a variadic directory.
How did you update these by the way? As far as I know we don't have anything like LLVM's python script.
There was a problem hiding this comment.
Right, so conveniently we do write the whole generated asm file to disk (for each revision), and then it's some vim stuff (retab to get rid of tabs, multiple cursors for adding the NEXT lines). But, pretty tedious still.
Especially because it took a couple of tries to land on the right thing to even test. For any real program, our version gets optimized differently because we provide LLVM with the separate loads early, while LLVM itself only expands va_arg quite late.
There was a problem hiding this comment.
Reasonable enough, +1 to a variadic directory.
I'll look at that in the sparc PR
There was a problem hiding this comment.
Oof, that's pretty brutal. It would be nice if we could have --bless work something like the LLVM script tbh, but that sounds like a bit of a pain to build.
| //@ revisions: mips mips64 mips64el | ||
| //@ [mips] compile-flags: -Copt-level=3 --target mips-unknown-linux-gnu | ||
| //@ [mips] needs-llvm-components: mips | ||
| //@ [mips64] compile-flags: -Copt-level=3 --target mipsisa64r6-unknown-linux-gnuabi64 | ||
| //@ [mips64] needs-llvm-components: mips | ||
| //@ [mips64el] compile-flags: -Copt-level=3 --target mips64el-unknown-linux-gnuabi64 | ||
| //@ [mips64el] needs-llvm-components: mips |
There was a problem hiding this comment.
Nit, I think we've been using more uppercase revisions for the codegen tests to match CHECK and the NEXT suffixes
There was a problem hiding this comment.
really? I though it was because there is some lowercase revision name that doesn't work (windows maybe? some common name like that). But I'm happy to change them
There was a problem hiding this comment.
It's just for consistency with filecheck AFAIK, we've talked about auto-uppercasing vs. just using uppercase names before to make things match. But everything is totally inconsistent so also a complete 🤷♂️ if you don't feel like changing it
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
c-variadic: use `emit_ptr_va_arg` for mips tracking issue: rust-lang#44930 After reading the implementation carefully, I believe it really is just `emit_ptr_va_arg`. The LLVM implementation can be found here: https://github.com/llvm/llvm-project/blob/289a3292be0c6a3df86bcdf5be7dd05b79a5570c/llvm/lib/Target/Mips/MipsISelLowering.cpp#L2338. r? workingjubilee
…uwer Rollup of 10 pull requests Successful merges: - #146544 (mir-opt: Remove the workaround in UnreachableEnumBranching) - #154819 (Fix ICE for inherent associated type mismatches) - #155265 (Improved assumptions relating to isqrt) - #152576 (c-variadic: use `emit_ptr_va_arg` for mips) - #154481 (Mark a function only used in nightly as nightly only) - #155614 (c-variadic: rename `VaList::arg` to `VaList::next_arg`) - #155630 (Make `//@ skip-filecheck` a normal compiletest directive) - #155641 (Remove non-working code for "running" mir-opt tests) - #155652 (Expand `Path::is_empty` docs) - #155656 (rustc_llvm: update opt-level handling for LLVM 23)
Rollup merge of #152576 - folkertdev:mips-va-arg, r=tgross35 c-variadic: use `emit_ptr_va_arg` for mips tracking issue: #44930 After reading the implementation carefully, I believe it really is just `emit_ptr_va_arg`. The LLVM implementation can be found here: https://github.com/llvm/llvm-project/blob/289a3292be0c6a3df86bcdf5be7dd05b79a5570c/llvm/lib/Target/Mips/MipsISelLowering.cpp#L2338. r? workingjubilee
…uwer Rollup of 10 pull requests Successful merges: - rust-lang/rust#146544 (mir-opt: Remove the workaround in UnreachableEnumBranching) - rust-lang/rust#154819 (Fix ICE for inherent associated type mismatches) - rust-lang/rust#155265 (Improved assumptions relating to isqrt) - rust-lang/rust#152576 (c-variadic: use `emit_ptr_va_arg` for mips) - rust-lang/rust#154481 (Mark a function only used in nightly as nightly only) - rust-lang/rust#155614 (c-variadic: rename `VaList::arg` to `VaList::next_arg`) - rust-lang/rust#155630 (Make `//@ skip-filecheck` a normal compiletest directive) - rust-lang/rust#155641 (Remove non-working code for "running" mir-opt tests) - rust-lang/rust#155652 (Expand `Path::is_empty` docs) - rust-lang/rust#155656 (rustc_llvm: update opt-level handling for LLVM 23)
c-variadic: `va_arg` fixes tracking issue: rust-lang/rust#44930 extracts some generic LLVM `va_arg` fixes from rust-lang/rust#152576 and rust-lang/rust#155429. r? tgross35
…uwer Rollup of 10 pull requests Successful merges: - rust-lang/rust#146544 (mir-opt: Remove the workaround in UnreachableEnumBranching) - rust-lang/rust#154819 (Fix ICE for inherent associated type mismatches) - rust-lang/rust#155265 (Improved assumptions relating to isqrt) - rust-lang/rust#152576 (c-variadic: use `emit_ptr_va_arg` for mips) - rust-lang/rust#154481 (Mark a function only used in nightly as nightly only) - rust-lang/rust#155614 (c-variadic: rename `VaList::arg` to `VaList::next_arg`) - rust-lang/rust#155630 (Make `//@ skip-filecheck` a normal compiletest directive) - rust-lang/rust#155641 (Remove non-working code for "running" mir-opt tests) - rust-lang/rust#155652 (Expand `Path::is_empty` docs) - rust-lang/rust#155656 (rustc_llvm: update opt-level handling for LLVM 23)
View all comments
tracking issue: #44930
After reading the implementation carefully, I believe it really is just
emit_ptr_va_arg.The LLVM implementation can be found here: https://github.com/llvm/llvm-project/blob/289a3292be0c6a3df86bcdf5be7dd05b79a5570c/llvm/lib/Target/Mips/MipsISelLowering.cpp#L2338.
r? workingjubilee