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.

Reply via email to