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