In PR 44826, we split a pre-reload call into another call followed
by a load of GP.  The problem is that we're running the split pass after
var-tracking, and the original call had a NOTE_INSN_CALL_ARG_LOCATION
attached to it.  We need to move the note to the new call, just like we
already move other properties of the call.

This shows up on 32-bit MIPS GNU/Linux at -O -g, because the first
post-epilogue scheduling pass is after var tracking.  It doesn't
show up on -O2 and above because an earlier pass does the split.

I think the bug could in principle trigger on other targets with
call-clobbered GPs (e.g. some variants of Alpha, ia64 and PA).
However, most other ports split on reload_completed, whereas MIPS
does it on epilogue_completed, so perhaps it really is only MIPS.

Tested on mips-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard


gcc/
        PR rtl-optimization/48826
        * emit-rtl.c (try_split): When splitting a call that is followed
        by a NOTE_INSN_CALL_ARG_LOCATION, move the note after the new call.

Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c      2011-05-22 17:13:06.000000000 +0100
+++ gcc/emit-rtl.c      2011-05-22 20:37:09.000000000 +0100
@@ -3476,11 +3476,27 @@ try_split (rtx pat, rtx trial, int last)
       for (insn = insn_last; insn ; insn = PREV_INSN (insn))
        if (CALL_P (insn))
          {
+           rtx next;
            rtx *p = &CALL_INSN_FUNCTION_USAGE (insn);
            while (*p)
              p = &XEXP (*p, 1);
            *p = CALL_INSN_FUNCTION_USAGE (trial);
            SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial);
+           /* If the new call is the last instruction in the sequence,
+              it will effectively replace the old call in-situ.  Otherwise
+              we must move any following NOTE_INSN_CALL_ARG_LOCATION note
+              so that it comes immediately after the new call.  */
+           if (NEXT_INSN (insn))
+             {
+               next = NEXT_INSN (trial);
+               if (next
+                   && NOTE_P (next)
+                   && NOTE_KIND (next) == NOTE_INSN_CALL_ARG_LOCATION)
+                 {
+                   remove_insn (next);
+                   add_insn_after (next, insn, NULL);
+                 }
+             }
          }
     }
 

Reply via email to