rustc_target: callconv: mips64: Return structs with single f128 in FPRs#159967
Open
Gelbpunkt wants to merge 1 commit into
Open
rustc_target: callconv: mips64: Return structs with single f128 in FPRs#159967Gelbpunkt wants to merge 1 commit into
Gelbpunkt wants to merge 1 commit into
Conversation
folkertdev
reviewed
Jul 26, 2026
folkertdev
reviewed
Jul 26, 2026
| ret.cast_to(reg); | ||
| // The inreg attribute forces LLVM to return a struct containing a f128 in | ||
| // $f0 and $f1 rather than $f0 and $f2, see: | ||
| // https://github.com/llvm/llvm-project/blob/a81db64570f94c2ca8ac0f598c0b5bba1a7ae59e/llvm/lib/Target/Mips/MipsCallingConv.td#L48-L51 |
Contributor
There was a problem hiding this comment.
// Contrary to the ABI documentation, a struct containing a long double is
// returned in $f0, and $f1 instead of the usual $f0, and $f2. This is to
// match the de facto ABI as implemented by GCC.
lol classic
Contributor
There was a problem hiding this comment.
I was thinking this could be a bit more general, so maybe mips-struct-float and testing some of the other 1 and 2 element cases too?
For more popular targets we'd find ABI issues organically, but for targets like mips it's possible something would slip through.
Contributor
Author
There was a problem hiding this comment.
Changed it so we test all the combinations of f32 / f64 / f128 that should be returned in FPRs
Gelbpunkt
force-pushed
the
mips64-struct-return-single-f128
branch
2 times, most recently
from
July 26, 2026 16:32
dccc817 to
ba8c047
Compare
The MIPS n64 ABI returns structs that meet the following requirements: - Up to 128 bits large - Only one or two fields, all of which are floating point - Offset of the first field is zero in floating point registers. This was already accounted for, but the edge case of a struct with a single f128 field was not handled correctly and would always be returned in integer registers. If we tell the backend to use a f128 register here, LLVM will return the value in two of the 64-bit FPRs, $f0 and $f2. That is equivalent to how Clang, GCC and also Rustc today would return a long double / f128. However, both Clang and GCC return a struct with a single long double field in $f0 and $f1. In order to achieve the same result in Rustc, we need to set the InReg attribute on the return value. With this, we now match Clang and GCC. Clang: https://godbolt.org/z/za8qv9P4n GCC: https://godbolt.org/z/9qcdGsce6 Rustc currently: https://godbolt.org/z/8sP5G4ash LLVM IR comparisons: https://godbolt.org/z/ojaTTY9hW
Gelbpunkt
force-pushed
the
mips64-struct-return-single-f128
branch
from
July 26, 2026 16:33
ba8c047 to
b0bc5a0
Compare
Collaborator
|
The job Click to see the possible cause of the failure (guessed by this bot) |
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The MIPS n64 ABI returns structs that meet the following requirements:
in floating point registers. This was already accounted for, but the edge case of a struct with a single
f128field was not handled correctly and would always be returned in integer registers.If we tell the backend to use a
f128register here, LLVM will return the value in two of the 64-bit FPRs,$f0and$f2. That is equivalent to how Clang, GCC and also Rustc today would return along double/f128.However, both Clang and GCC return a struct with a single long double field in
$f0and$f1. In order to achieve the same result in Rustc, we need to set theInRegattribute on the return value.With this, we now match Clang and GCC.
Clang: https://godbolt.org/z/za8qv9P4n
GCC: https://godbolt.org/z/9qcdGsce6
Rustc currently: https://godbolt.org/z/8sP5G4ash
LLVM IR comparisons: https://godbolt.org/z/ojaTTY9hW
I'm not sure if it is acceptable to use
Reg::f128since MIPS has no 128-bit floating point registers unless MSA is present. LLVM lowers it correctly to use two FPRs, not sure if this would cause issues with GCC.f16probably also needs some changes here, but I'll do that as a follow-up.r? @folkertdev
and Folkert also told me to cc @tgross35 :)