Another missing case of CALL_INSN_FUNCTION_USAGE, where clobbered registers are also marked, this time in postreload/ reload_cse_move2add.
Fixed compiler now generates following code call sysv_abi_func movl $global, %esi movl $.LC2, %edi call sysv_abi_func movl $global, %esi movl $.LC3, %edi call sysv_abi_func which correctly reloads %esi for every sysv_abi function call. 2015-07-12 Uros Bizjak <ubiz...@gmail.com> PR rtl-optimization/66838 * postreload.c (reload_cse_move2add): Also process CALL_INSN_FUNCTION_USAGE when resetting information of call-clobbered registers. testsuite/ChangeLog: 2015-07-12 Uros Bizjak <ubiz...@gmail.com> PR rtl-optimization/66838 * gcc.target/i386/pr66838.c: New test. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. OK for mainline and gcc-5 branch? Uros.
Index: postreload.c =================================================================== --- postreload.c (revision 225722) +++ postreload.c (working copy) @@ -2127,6 +2127,8 @@ reload_cse_move2add (rtx_insn *first) unknown values. */ if (CALL_P (insn)) { + rtx link; + for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--) { if (call_used_regs[i]) @@ -2133,6 +2135,21 @@ reload_cse_move2add (rtx_insn *first) /* Reset the information about this register. */ reg_mode[i] = VOIDmode; } + + for (link = CALL_INSN_FUNCTION_USAGE (insn); link; + link = XEXP (link, 1)) + { + rtx setuse = XEXP (link, 0); + rtx usage_rtx = XEXP (setuse, 0); + if (GET_CODE (setuse) == CLOBBER + && REG_P (usage_rtx)) + { + unsigned int end_regno = END_REGNO (usage_rtx); + for (unsigned int r = REGNO (usage_rtx); r < end_regno; ++r) + /* Reset the information about this register. */ + reg_mode[r] = VOIDmode; + } + } } } return changed; Index: testsuite/gcc.target/i386/pr66838.c =================================================================== --- testsuite/gcc.target/i386/pr66838.c (revision 0) +++ testsuite/gcc.target/i386/pr66838.c (working copy) @@ -0,0 +1,36 @@ +/* { dg-do run { target lp64 } } */ +/* { dg-options "-O2" } */ + +void abort (void); + +char global; + +__attribute__((sysv_abi, noinline, noclone)) +void sysv_abi_func(char const *desc, void *local) +{ + register int esi asm ("esi"); + register int edi asm ("edi"); + + if (local != &global) + abort (); + + /* Clobber some of the extra SYSV ABI registers. */ + asm volatile ("movl\t%2, %0\n\tmovl\t%2, %1" + : "=r" (esi), "=r" (edi) + : "i" (0xdeadbeef)); +} + +__attribute__((ms_abi, noinline, noclone)) +void ms_abi_func () +{ + sysv_abi_func ("1st call", &global); + sysv_abi_func ("2nd call", &global); + sysv_abi_func ("3rd call", &global); +} + +int +main(void) +{ + ms_abi_func(); + return 0; +}