https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126115
Bug ID: 126115
Summary: [SH] Won't load complex-float constant directly into
return regs
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: olegendo at gcc dot gnu.org
Target Milestone: ---
This is a carry over observation from PR 116709.
The following test
_Complex float bleh_c0 (void)
{
return __builtin_complex (12.3f, 15.4f);
}
Compiled with -m4-single -ml -O2:
_bleh_c0:
mova .L6,r0 ! 26 [c=9 l=2] mova
fmov.s @r0+,fr2 ! 6 [c=5 l=2] movsf_ie/5
fmov.s @r0+,fr3 ! 5 [c=5 l=2] movsf_ie/5
fmov fr2,fr1 ! 12 [c=4 l=2] movsf_ie_ra/0
rts ! 23 [c=0 l=2] *return_i
fmov fr3,fr0 ! 11 [c=4 l=2] movsf_ie_ra/0
.L7:
.align 2
.L6:
.long 1098278502
.long 1095027917
It's first loading the complex constant into {fr3,fr2} and then does {fr3,fr2}
-> {fr1,fr0} for the return value. It could load the constant directly into
{fr1,fr0}.
SH doesn't define dedicated complex move insns, emit_move_complex_parts splits
it into single-fp moves. After the asmcons pass the RTL looks like this:
(insn 5 2 6 2 (parallel [
(set (reg:SF 162 [ <retval> ])
(const_double:SF 1.230000019073486328125e+1 [0x0.c4cccdp+4]))
(use (reg:SI 154 fpscr0))
(clobber (reg:SI 0 r0))
]) "sh_tmp.cpp":11:16 discrim 1 222 {movsf_ie}
(expr_list:REG_UNUSED (reg:SI 0 r0)
(nil)))
(insn 6 5 10 2 (parallel [
(set (reg:SF 163 [ <retval>+4 ])
(const_double:SF 1.53999996185302734375e+1 [0x0.f66666p+4]))
(use (reg:SI 154 fpscr0))
(clobber (reg:SI 0 r0))
]) "sh_tmp.cpp":11:16 discrim 1 222 {movsf_ie}
(expr_list:REG_UNUSED (reg:SI 0 r0)
(nil)))
(insn 10 6 11 2 (clobber (reg/i:SC 64 fr0)) "sh_tmp.cpp":12:7 -1
(expr_list:REG_UNUSED (reg/i:SC 64 fr0)
(nil)))
(insn 11 10 12 2 (parallel [
(set (reg:SF 64 fr0)
(reg:SF 162 [ <retval> ]))
(use (reg:SI 154 fpscr0))
]) "sh_tmp.cpp":12:7 223 {movsf_ie_ra}
(expr_list:REG_DEAD (reg:SF 162 [ <retval> ])
(expr_list:REG_EQUAL (const_double:SF 1.230000019073486328125e+1
[0x0.c4cccdp+4])
(nil))))
(insn 12 11 13 2 (parallel [
(set (reg:SF 65 fr1 [+4 ])
(reg:SF 163 [ <retval>+4 ]))
(use (reg:SI 154 fpscr0))
]) "sh_tmp.cpp":12:7 223 {movsf_ie_ra}
(expr_list:REG_DEAD (reg:SF 163 [ <retval>+4 ])
(expr_list:REG_DEAD (reg:SI 154 fpscr0)
(expr_list:REG_EQUAL (const_double:SF 1.53999996185302734375e+1
[0x0.f66666p+4])
(nil)))))
(insn 13 12 0 2 (use (reg/i:SC 64 fr0)) "sh_tmp.cpp":12:7 -1
(nil))
It seems that clobber on fr0 in insn 10 prevents further reg-reg move
optimizations from eliminating the extra regs.