with
https://godbolt.org/z/EYxKxTs4f
// --target=powerpc64-unknown-linux-gnu -Copt-level=3
#[repr(C)] pub union TwoFloats { a: f32, b: f32 }
#[unsafe(no_mangle)]
extern "C" fn foo(x: TwoFloats) -> f32 {
unsafe { x.a }
}
rustc emits
foo:
.quad .Lfunc_begin0
.quad .TOC.@tocbase
.quad 0
.Lfunc_begin0:
blr
I.e. the argument is already in a float register, and it stays there for the return. But with GCC and Clang the equivalent
https://godbolt.org/z/Mx8GEzdvn
typedef union { float a; float b; } TwoFloats;
float foo(TwoFloats x) {
return x.a;
}
Has an explicit move from GPR to memory to FPR
foo:
.quad .Lfunc_begin0
.quad .TOC.@tocbase
.quad 0
.Lfunc_begin0:
stw 3, -4(1)
lfs 1, -4(1)
blr
You can see this difference in the LLVM IR emitted by rustc and clang too:
; rust
define noundef float @foo(float returned %0) unnamed_addr {
start:
ret float %0
}
; clang
define dso_local float @foo(i32 %x.coerce) local_unnamed_addr {
entry:
%0 = bitcast i32 %x.coerce to float
ret float %0
}
This came up in relation to #161987.
with
https://godbolt.org/z/EYxKxTs4f
rustc emits
I.e. the argument is already in a float register, and it stays there for the return. But with GCC and Clang the equivalent
https://godbolt.org/z/Mx8GEzdvn
Has an explicit move from GPR to memory to FPR
You can see this difference in the LLVM IR emitted by rustc and clang too:
This came up in relation to #161987.