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?