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]

Re: [PATCH] Fix ICE in distribute_notes (PR bootstrap/51796)


> I'd find that very fragile.  E.g. distribute_notes itself reverses the
> order of all notes, and for no REG_NOTES I think we rely on any ordering.

AFAIK distribute_notes is the only routine that redistributes the RTL notes for 
a fixed insn, so I'm a little skeptical about the purported fragility here.
My point is that the complexity should be in fixup_args_size_notes instead of 
distribute_notes.  Tentative patch attached.


	PR bootstrap/51796
	* calls.c (emit_call_1): Make sure REG_NORETURN note comes first.
	* combine.c (distribute_notes): If i3 is a noreturn call, allow
	old_size to be equal to args_size if !ACCUMULATE_OUTGOING_ARGS.
	* expr.c (fixup_args_size_notes): Put REG_ARGS_SIZE notes on
	noreturn calls even when the delta is 0.
	* rtlanal.c (find_and_remove_reg_note): New function.
	* rtl.h (find_and_remove_reg_note): Declare it.


-- 
Eric Botcazou
Index: calls.c
===================================================================
--- calls.c	(revision 183092)
+++ calls.c	(working copy)
@@ -413,15 +413,6 @@ emit_call_1 (rtx funexp, tree fntree ATT
   /* Create a nothrow REG_EH_REGION note, if needed.  */
   make_reg_eh_region_note (call_insn, ecf_flags, 0);
 
-  if (ecf_flags & ECF_NORETURN)
-    add_reg_note (call_insn, REG_NORETURN, const0_rtx);
-
-  if (ecf_flags & ECF_RETURNS_TWICE)
-    {
-      add_reg_note (call_insn, REG_SETJMP, const0_rtx);
-      cfun->calls_setjmp = 1;
-    }
-
   SIBLING_CALL_P (call_insn) = ((ecf_flags & ECF_SIBCALL) != 0);
 
   /* Restore this now, so that we do defer pops for this call's args
@@ -451,6 +442,17 @@ emit_call_1 (rtx funexp, tree fntree ATT
   else if (!ACCUMULATE_OUTGOING_ARGS && (ecf_flags & ECF_NORETURN) != 0)
     add_reg_note (call_insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
 
+  if (ecf_flags & ECF_RETURNS_TWICE)
+    {
+      add_reg_note (call_insn, REG_SETJMP, const0_rtx);
+      cfun->calls_setjmp = 1;
+    }
+
+  /* The REG_NORETURN note must come before the REG_ARGS_SIZE note for the
+     fixup_args_size_notes machinery to work correctly.  */
+  if (ecf_flags & ECF_NORETURN)
+    add_reg_note (call_insn, REG_NORETURN, const0_rtx);
+
   if (!ACCUMULATE_OUTGOING_ARGS)
     {
       /* If returning from the subroutine does not automatically pop the args,
Index: combine.c
===================================================================
--- combine.c	(revision 182780)
+++ combine.c	(working copy)
@@ -13282,7 +13282,13 @@ distribute_notes (rtx notes, rtx from_in
 	    {
 	      int old_size, args_size = INTVAL (XEXP (note, 0));
 	      old_size = fixup_args_size_notes (PREV_INSN (i3), i3, args_size);
-	      gcc_assert (old_size != args_size);
+	      /* emit_call_1 adds for !ACCUMULATE_OUTGOING_ARGS REG_ARGS_SIZE
+		 note to all noreturn calls, but fixup_args_size_notes cannot
+		 recompute the amount on its own, so the size is unchanged.  */
+	      gcc_assert (old_size != args_size
+			  || (CALL_P (i3)
+			      && !ACCUMULATE_OUTGOING_ARGS
+			      && find_reg_note (i3, REG_NORETURN, NULL_RTX)));
 	    }
 	  break;
 
Index: expr.c
===================================================================
--- expr.c	(revision 182780)
+++ expr.c	(working copy)
@@ -3645,9 +3645,11 @@ mem_autoinc_base (rtx mem)
      (1) One or more auto-inc style memory references (aka pushes),
      (2) One or more addition/subtraction with the SP as destination,
      (3) A single move insn with the SP as destination,
-     (4) A call_pop insn.
+     (4) A call_pop insn,
+     (5) Noreturn call insns if !ACCUMULATE_OUTGOING_ARGS.
 
-   Insns in the sequence that do not modify the SP are ignored.
+   Insns in the sequence that do not modify the SP are ignored,
+   except for noreturn calls.
 
    The return value is the amount of adjustment that can be trivially
    verified, via immediate operand or auto-inc.  If the adjustment
@@ -3786,23 +3788,42 @@ fixup_args_size_notes (rtx prev, rtx las
   for (insn = last; insn != prev; insn = PREV_INSN (insn))
     {
       HOST_WIDE_INT this_delta;
+      rtx note = NULL_RTX;
 
       if (!NONDEBUG_INSN_P (insn))
 	continue;
 
       this_delta = find_args_size_adjust (insn);
       if (this_delta == 0)
-	continue;
+	{
+	  /* In the noreturn call case, we need to maintain the invariant
+	     that the REG_NORETURN comes first.  So remove it here...  */
+	  if (!CALL_P (insn)
+	      || ACCUMULATE_OUTGOING_ARGS
+	      || (note = find_and_remove_reg_note
+			(insn, REG_NORETURN, NULL_RTX)) == NULL_RTX)
+	    continue;
+	}
 
       gcc_assert (!saw_unknown);
       if (this_delta == HOST_WIDE_INT_MIN)
 	saw_unknown = true;
 
       add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (args_size));
+
+      if (this_delta == 0)
+	{
+	  /* ...and add it back here.  */
+	  XEXP (note, 1) = REG_NOTES (insn);
+	  REG_NOTES (insn) = note;
+	}
+      else
+	{
 #ifdef STACK_GROWS_DOWNWARD
-      this_delta = -this_delta;
+	  this_delta = -this_delta;
 #endif
-      args_size -= this_delta;
+	  args_size -= this_delta;
+	}
     }
 
   return saw_unknown ? INT_MIN : args_size;
Index: rtlanal.c
===================================================================
--- rtlanal.c	(revision 182780)
+++ rtlanal.c	(working copy)
@@ -1752,6 +1752,17 @@ find_reg_note (const_rtx insn, enum reg_
   return 0;
 }
 
+/* Likewise, but additionally remove the note.  */
+
+rtx
+find_and_remove_reg_note (rtx insn, enum reg_note kind, const_rtx datum)
+{
+  rtx note = find_reg_note (insn, kind, datum);
+  if (note)
+    remove_note (insn, note);
+  return note;
+}
+
 /* Return the reg-note of kind KIND in insn INSN which applies to register
    number REGNO, if any.  Return 0 if there is no such reg-note.  Note that
    the REGNO of this NOTE need not be REGNO if REGNO is a hard register;
Index: rtl.h
===================================================================
--- rtl.h	(revision 182780)
+++ rtl.h	(working copy)
@@ -1951,6 +1951,7 @@ extern void note_uses (rtx *, void (*) (
 extern int dead_or_set_p (const_rtx, const_rtx);
 extern int dead_or_set_regno_p (const_rtx, unsigned int);
 extern rtx find_reg_note (const_rtx, enum reg_note, const_rtx);
+extern rtx find_and_remove_reg_note (rtx, enum reg_note, const_rtx);
 extern rtx find_regno_note (const_rtx, enum reg_note, unsigned int);
 extern rtx find_reg_equal_equiv_note (const_rtx);
 extern rtx find_constant_src (const_rtx);

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