https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109989

Pash Osh <orehovpasha at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |orehovpasha at gmail dot com

--- Comment #5 from Pash Osh <orehovpasha at gmail dot com> ---
As my investigations shows, it is based on passing wasted a0 to
__floatsisf(SItype).
Gcc13 (AKA after given patch) do not cleanup a0.hi via sext.w to honor generic
calling convention. While libgcc's compiler do not honor SImode in arg of
__floatsisf(SItype) so it uses wasted a0.hi. Someplaces.

FYI see a diff of call (-fdump-rtl-combine):
     insn_cost 4 for    21: r81:DI=sign_extend(r88:SI)
    -insn_cost 4 for    22: a0:DI=r81:DI //gcc12 (AKA before patch), gcc14,
non-buildin func(SItype)
    +insn_cost 4 for    22: a0:SI=r81:DI#0 // gcc13 (AKA after patch)
     insn_cost 36 for    23: a0:SF=call [`__floatsisf'] argc:0


But gcc12 (AKA before given patch), gcc14(with -fdisable-tree-dom2 to mitigate
const propagation), or manual func(SItype) call like

    SFtype fsi (SItype  i);
    ...
    for (i=0;i<1;++i){
        //f[i]=x[i];
        f[i] = fsi(x[i]);
    }

always issues insn a0:DI=r81:DI and generates correct sext.w


So it is like call(expand) of buildin __floatsisf is broken in gcc13 till head!

## __floatsisf(SItype) analysis

Short: it ignores sometimes SItype attr and use bit63, which on
gcc13-buildin-call is wasted
    #define _FP_FROM_INT(fs, wc, X, rr, rsize, rtype){                  \
          if (r){                                                              
\
          rtype _FP_FROM_INT_ur = (r);                                  \
          if ((X##_s = ((r) < 0)))                                      \
            _FP_FROM_INT_ur = -_FP_FROM_INT_ur;                         \

      -fdump-rtl-combine:
    insn_cost 4 for   256: r226:DI=a0:DI //a0 contains SItype
    insn_cost 4 for     2: r169:DI=r226:DI
    insn_cost 4 for    23: pc={(r169:DI==0)?L238:pc}

    insn_cost 0 for   240: debug D#1 => sign_extend(r169:DI#0) 
    insn_cost 4 for    26: r154:DI=sign_extend(r169:DI#0)
    insn_cost 0 for    27: debug _FP_FROM_INT_ur => D#1#0

    insn_cost 4 for    31: r171:SI=r169:DI#0 0>>0x1f
    insn_cost 4 for    32: r134:DI=zero_extend(r171:SI#0)
    insn_cost 0 for    33: debug A_s => zero_extend(r134:DI#0)

    insn_cost 4 for    37: pc={(r169:DI>=0)?L43:pc}


      riscv64-rise.13.1$ ...objdump -S  ...libgcc_s.so.1
    000000000000fa34 <__floatsisf>:
    fa38: c53d      beqz    a0,faa6 //if(r), do not honor SI mode, and use bit
63
    fa52: 01f5549b  srliw   s1,a0,0x1f //X##_s=((r)<0)); Sign=bit31; Honors SI
mode
    fa56: 04054b63  bltz    a0,faac //if(r<0), do not honor SI mode, X##_s, use
bit 63


## Question: that does `SItype` for func arg means exactly? Does it means a0.hi
is undefined and do not use it in caller and into callee?

One more argument: SI_BITS==32 ! (#define SI_BITS (__CHAR_BIT__ * (int)
sizeof(SItype)))

## Question: Is it ok, codegen differs for buildin and for explicit func with
same signature?

## What is best way to fix:?
0. What is your word about  "SI mode VS calling convention (a0.sign_extend)"?

1. call buildin `__floatsisf((long long) x)` to drop shrink  `a0:SI=r143:DI#0`
near ./gcc/optabs.cc: expand_float (rtx, rtx ...) ?

2. fix softfloat `__floatsisf`(SI i){if(i){if(i<0)…) to override calling
convention and honor SI, do not use bit63 ?

3. backport from gcc14?

Reply via email to