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.

Reply via email to