This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR 48826: NOTE_INSN_CALL_ARG_LOCATION vs. define_split


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]