diff mbox

PR 48826: NOTE_INSN_CALL_ARG_LOCATION vs. define_split

Message ID 87tycm4ewx.fsf@firetop.home
State New
Headers show

Commit Message

Richard Sandiford May 22, 2011, 9:13 p.m. UTC
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.

Comments

Eric Botcazou May 23, 2011, 7:13 a.m. UTC | #1
> 	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.

OK if you move up the comment and merge it in the comment of the block.  And it 
would be nice to add the missing blurb about the SIBLING_CALL_P flag.  TIA.
diff mbox

Patch

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);
+		  }
+	      }
 	  }
     }