From patchwork Thu Aug 19 09:33:32 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: prevent extraneous nop past sibling call on sparc Date: Wed, 18 Aug 2010 23:33:32 -0000 From: Olivier Hainque X-Patchwork-Id: 62125 Message-Id: <20100819093332.GA9139@cardhu.act-europe.fr> To: gcc-patches@gcc.gnu.org Cc: hainque@adacore.com Hello, The sparc back-end emits an extra nop past calls at the very end of a function, to prevent the return address from falling within a different function, which causes trouble to some backtrace computation engines. Such a nop is pointless for a sibling call since the return address is setup explicitly, and this patch is a suggestion to remove it for this particular case. We found this useful in the course of the development of a machine code coverage analyzer. OK ? Thanks in advance, Olivier 2010-08-19 Olivier Hainque * config/sparc/sparc.c (sparc_asm_function_epilogue): Don't output an extra nop past a sibling call at the very end. testsuite/ * gcc.target/sparc/sibcall-dslot.c: New testcase. Index: config/sparc/sparc.c =================================================================== --- config/sparc/sparc.c (revision 163326) +++ config/sparc/sparc.c (working copy) @@ -4527,11 +4527,11 @@ static void sparc_asm_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) { - /* If code does not drop into the epilogue, we have to still output - a dummy nop for the sake of sane backtraces. Otherwise, if the - last two instructions of a function were "call foo; dslot;" this - can make the return PC of foo (i.e. address of call instruction - plus 8) point to the first instruction in the next function. */ + /* If the last two instructions of a function are "call foo; dslot;" + the return address might point to the first instruction in the next + function and we have to output a dummy nop for the sake of sane + backtraces in such cases. This is pointless for sibling calls since + the return address is explicitly adjusted. */ rtx insn, last_real_insn; @@ -4543,7 +4543,8 @@ && GET_CODE (PATTERN (last_real_insn)) == SEQUENCE) last_real_insn = XVECEXP (PATTERN (last_real_insn), 0, 0); - if (last_real_insn && GET_CODE (last_real_insn) == CALL_INSN) + if (last_real_insn && GET_CODE (last_real_insn) == CALL_INSN + && !SIBLING_CALL_P (last_real_insn)) fputs("\tnop\n", file); sparc_output_deferred_case_vectors (); Index: testsuite/gcc.target/sparc/sibcall-dslot.c =================================================================== --- testsuite/gcc.target/sparc/sibcall-dslot.c (revision 0) +++ testsuite/gcc.target/sparc/sibcall-dslot.c (revision 0) @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern int one (); + +int some_n () +{ + return one (); +} + +/* { dg-final { scan-assembler-not "nop" } } */