https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87690
--- Comment #5 from Andrew Waterman <andrew at sifive dot com> --- FWIW, I agree with your last paragraph On Wed, Oct 24, 2018 at 7:54 AM wilson at gcc dot gnu.org < gcc-bugzi...@gcc.gnu.org> wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87690 > > Jim Wilson <wilson at gcc dot gnu.org> changed: > > What |Removed |Added > > ---------------------------------------------------------------------------- > Status|UNCONFIRMED |NEW > Last reconfirmed| |2018-10-23 > Assignee|unassigned at gcc dot gnu.org |wilson at gcc dot > gnu.org > Ever confirmed|0 |1 > > --- Comment #4 from Jim Wilson <wilson at gcc dot gnu.org> --- > I think the intent of the second rule is that float values are passed in > the > same regs as an integer value, and that it wasn't the intent that the > promotion > rule also applied to float values. > > The GCC RISC-V port is passing 32-bit floats as SFmode, which means only > the > low 32-bits of the value are valid. A struct with a single float field > also > gets treated as SFmode, so that we can directly access the float member. > riscv_function_arg isn't checking the argument type, it is only checking > the > argument mode. Hence, a float and a struct with a single float member get > handled exactly the same. Since they are passed the same, there is no > conversion code to go from one to the other. > > We would have the exact same problem with a struct with a single int field, > except that PROMOTE_MODE forces SImode to be handled as DImode, and the > promote_mode function does check types, and only applies PROMOTE_MODE to > integer types. Hence, a struct with single int field is SImode and an int > is > DImode, and we require conversion code which does the sign extension > called for > by the ABI. But PROMOTE_MODE is only sensible for integral types, so this > can't solve the float problem. > > I don't see any point to trying to sign extend a 32-bit float in a 64-bit > integer register. There are only a few useful things one can do to a > float in > an integer register, such as absolute value and signbit, and having the > value > be sign extended doesn't help there. For instance given > #include <math.h> > > float sub (float a) > { > return fabs (a); > } > and compiling with riscv64-unknown-elf-gcc -O2 -S -mabi=lp64 -march=rv64i > I get > sub: > slli a0,a0,33 > srli a0,a0,33 > ret > The upper 32-bits of a0 are being treated as don't care bits for both the > argument and the return value. They are ignored for the input value, and > set > to 0 for the return value. Having the value sign-extended doesn't make > this > code any simpler. I see that we aren't actually optimizing signbit as we > should be, but again having it sign-extended doesn't give shorter code. > > Requiring that float values be sign extended in a 64-bit reg might require > emitting extra instructions in some cases, which could reduce > performance. So > it also seems unwise from that point of view. Consider this testcase for > instance > struct float_struct { float v; float w;}; > > struct float_struct callee(float, float); > > struct float_struct caller(struct float_struct fs) { > return callee(fs.v, fs.w); > } > Compiled with riscv64-unknown-elf-gcc -O2 -S -mabi=lp64 I get > caller: > addi sp,sp,-32 > sd a0,8(sp) > srli a1,a0,32 > addi sp,sp,32 > tail callee > The 2-float struct is passed entirely in a0. Since the upper 32-bits of a > float arg are don't care bits, we can pass a0 directly to callee > unchanged. > The second arg for callee is extracted from the upper bits of a0 with a > logical > shift that zero extends it. We could change the logical shift to an > arithmetic > shift at no cost. But sign-extending the float a0 would require adding two > shift instructions. > > I am also concerned that there might be implementation problems trying to > convince gcc to sign-extend floating point values in integer registers, as > that > isn't a natural thing to do. > > I think the simplest solution here is to update the psABI to indicate that > float values in integer registers are not sign extended. Or alternatively > that > the sign extension rule only applies to integer types.