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 <[email protected]>
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 <[email protected]>
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;
+}