http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60028

            Bug ID: 60028
           Summary: TIC6X: B3 register (return address) is saved on stack
                    when real call is replaced with sibling call in a leaf
                    function
           Product: gcc
           Version: 4.8.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: target
          Assignee: unassigned at gcc dot gnu.org
          Reporter: wojtek.golf at interia dot pl

GCC 4.8.2, target tic6x
Input source:

int e_fun(int arg);
extern int e_int;

void g_fun(void)
{
    e_fun(e_int);
}

compiled with a command: -fleading-underscore -march=c674x -O2 -g0 -S main.c

gives the following assembler code:
_g_fun:
        sub .d2 B15, 8, B15
        stw .d2t2   B3, *+B15(8)
        b   .s1 (_e_fun)
    ||  ldw .d2t1   *+B14(_e_int), A4
        ldw .d2t2   *+B15(8), B3
    ||  add .s2 8, B15, B15
    ;; sibcall to (_e_fun) occurs
        nop 4

where B3 is saved on the stack even though a branch is taken to _e_fun. Texas
Instruments CGTools compiler v7.3.2 (cl6x --gcc -mv6740 --symdebug:none -k -n
main.c) gives the following assembler code (CALLRET is an alias to B):

_g_fun:
           CALLRET .S1     _e_fun            ; |6|
           LDW     .D2T1   *+DP(_e_int),A4   ; |6|
           NOP             4
$C$RL0:    ; CALL-RETURN OCCURS {_e_fun} 0   ; |6|

where B3 is not saved.

Some investigation on my part leads to the function c6x_expand_call in the file
gcc/gcc/config/c6x/c6x.c, where we see what may cause B3 being marked as used
and hence saved on the stack prior to the branch:

  if (sibcall)
    {
      call_insn = emit_call_insn (call_insn);
      use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
         gen_rtx_REG (Pmode, REG_B3));
    }

commenting out use_reg invocation makes gcc to generate the expected listing:

_g_fun:
        b   .s1 (_e_fun)
    ||  ldw .d2t1   *+B14(_e_int), A4
    ;; sibcall to (_e_fun) occurs
        nop 5

I haven't tested yet whether removal of use_reg invocation causes any
regression, but I'd like it to be investigated whether it should be removed
altogether or protected with some extra execution condition.

With best,

Wojciech

Reply via email to