diff mbox

Postreload DF fix (PR middle-end/78540)

Message ID 20161128193542.GZ3541@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Nov. 28, 2016, 7:35 p.m. UTC
Hi!

On the following case we ICE in DF checking, because
reload_combine_recognize_pattern starts with apply_change_group
that in the end on success calls df_insn_rescan, but if it is successful,
we then remove_reg_equal_equiv_notes and nothing rescans the notes.

Fixed by rescanning just the notes if anything changed.
remove_reg_equal_equiv_notes is right now only used in postreload
(this spot) and in the combiner (where we df_insn_rescan shortly afterwards,
thus we are fine with remove_reg_equal_equiv_notes itself not rescanning
anything).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-11-28  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/78540
	* rtl.h (remove_reg_equal_equiv_notes): Return bool instead of void.
	* rtlanal.c (remove_reg_equal_equiv_notes): Return true if any
	note has been removed.
	* postreload.c (reload_combine_recognize_pattern): If
	remove_reg_equal_equiv_notes returns true, call df_notes_rescan.

	* gcc.dg/pr78540.c: New test.


	Jakub

Comments

Jeff Law Nov. 28, 2016, 10:47 p.m. UTC | #1
On 11/28/2016 12:35 PM, Jakub Jelinek wrote:
> Hi!
>
> On the following case we ICE in DF checking, because
> reload_combine_recognize_pattern starts with apply_change_group
> that in the end on success calls df_insn_rescan, but if it is successful,
> we then remove_reg_equal_equiv_notes and nothing rescans the notes.
>
> Fixed by rescanning just the notes if anything changed.
> remove_reg_equal_equiv_notes is right now only used in postreload
> (this spot) and in the combiner (where we df_insn_rescan shortly afterwards,
> thus we are fine with remove_reg_equal_equiv_notes itself not rescanning
> anything).
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2016-11-28  Jakub Jelinek  <jakub@redhat.com>
>
> 	PR middle-end/78540
> 	* rtl.h (remove_reg_equal_equiv_notes): Return bool instead of void.
> 	* rtlanal.c (remove_reg_equal_equiv_notes): Return true if any
> 	note has been removed.
> 	* postreload.c (reload_combine_recognize_pattern): If
> 	remove_reg_equal_equiv_notes returns true, call df_notes_rescan.
>
> 	* gcc.dg/pr78540.c: New test.
OK.
jeff
diff mbox

Patch

--- gcc/rtl.h.jj	2016-11-23 16:47:36.000000000 +0100
+++ gcc/rtl.h	2016-11-28 17:44:44.647327866 +0100
@@ -3057,7 +3057,7 @@  extern void add_int_reg_note (rtx_insn *
 extern void add_shallow_copy_of_reg_note (rtx_insn *, rtx);
 extern rtx duplicate_reg_note (rtx);
 extern void remove_note (rtx_insn *, const_rtx);
-extern void remove_reg_equal_equiv_notes (rtx_insn *);
+extern bool remove_reg_equal_equiv_notes (rtx_insn *);
 extern void remove_reg_equal_equiv_notes_for_regno (unsigned int);
 extern int side_effects_p (const_rtx);
 extern int volatile_refs_p (const_rtx);
--- gcc/rtlanal.c.jj	2016-11-28 10:59:06.000000000 +0100
+++ gcc/rtlanal.c	2016-11-28 17:45:37.592716718 +0100
@@ -2351,22 +2351,28 @@  remove_note (rtx_insn *insn, const_rtx n
     }
 }
 
-/* Remove REG_EQUAL and/or REG_EQUIV notes if INSN has such notes.  */
+/* Remove REG_EQUAL and/or REG_EQUIV notes if INSN has such notes.
+   Return true if any note has been removed.  */
 
-void
+bool
 remove_reg_equal_equiv_notes (rtx_insn *insn)
 {
   rtx *loc;
+  bool ret = false;
 
   loc = &REG_NOTES (insn);
   while (*loc)
     {
       enum reg_note kind = REG_NOTE_KIND (*loc);
       if (kind == REG_EQUAL || kind == REG_EQUIV)
-	*loc = XEXP (*loc, 1);
+	{
+	  *loc = XEXP (*loc, 1);
+	  ret = true;
+	}
       else
 	loc = &XEXP (*loc, 1);
     }
+  return ret;
 }
 
 /* Remove all REG_EQUAL and REG_EQUIV notes referring to REGNO.  */
--- gcc/postreload.c.jj	2016-11-18 20:04:26.000000000 +0100
+++ gcc/postreload.c	2016-11-28 17:47:19.081409275 +0100
@@ -1192,10 +1192,11 @@  reload_combine_recognize_pattern (rtx_in
 	      /* Delete the reg-reg addition.  */
 	      delete_insn (insn);
 
-	      if (reg_state[regno].offset != const0_rtx)
-		/* Previous REG_EQUIV / REG_EQUAL notes for PREV
-		   are now invalid.  */
-		remove_reg_equal_equiv_notes (prev);
+	      if (reg_state[regno].offset != const0_rtx
+		  /* Previous REG_EQUIV / REG_EQUAL notes for PREV
+		     are now invalid.  */
+		  && remove_reg_equal_equiv_notes (prev))
+		df_notes_rescan (prev);
 
 	      reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
 	      return true;
--- gcc/testsuite/gcc.dg/pr78540.c.jj	2016-11-28 17:53:32.769595232 +0100
+++ gcc/testsuite/gcc.dg/pr78540.c	2016-11-28 17:53:16.000000000 +0100
@@ -0,0 +1,27 @@ 
+/* PR middle-end/78540 */
+/* { dg-do compile { target int128 } } */
+/* { dg-options "-O2 -Wno-psabi" } */
+/* { dg-additional-options "-march=core2" { target i?86-*-* x86_64-*-* } } */
+
+typedef unsigned __int128 V __attribute__ ((vector_size (64)));
+V g;
+
+static inline V
+foo (V a)
+{
+  V b, c;
+  c[0] = 0;
+  a += 2281559097;
+  c ^= 0;
+  b[0] = 0;
+  return 1 + c + b + a;
+}
+
+V
+bar ()
+{
+  V a = g, b = g;
+  a[1] ^= 1;
+  b[foo (a)[0] & 3] |= 1;
+  return b;
+}