This bug was causing miscompiled code related to branch delay slots Signed-off-by: Felix Fietkau <nbd@nbd.name>
		
			
				
	
	
		
			137 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From: ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
 | 
						|
Date: Mon, 26 Feb 2018 16:29:30 +0000
 | 
						|
Subject: [PATCH] 	PR rtl-optimization/83496 	* reorg.c
 | 
						|
 (steal_delay_list_from_target): Change REDUNDANT array from 	booleans to
 | 
						|
 RTXes.  Call fix_reg_dead_note on every non-null element.
 | 
						|
 (steal_delay_list_from_fallthrough): Call fix_reg_dead_note on a
 | 
						|
 redundant insn, if any. 	(relax_delay_slots): Likewise.
 | 
						|
 (update_reg_unused_notes): Rename REDUNDANT_INSN to OTHER_INSN.
 | 
						|
 | 
						|
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257996 138bc75d-0d04-0410-961f-82ee72b054a4
 | 
						|
---
 | 
						|
 create mode 120000 gcc/testsuite/gcc.c-torture/execute/20180226-1.c
 | 
						|
 | 
						|
--- a/gcc/reorg.c
 | 
						|
+++ b/gcc/reorg.c
 | 
						|
@@ -1035,7 +1035,8 @@ check_annul_list_true_false (int annul_t
 | 
						|
 
 | 
						|
 static void
 | 
						|
 steal_delay_list_from_target (rtx_insn *insn, rtx condition, rtx_sequence *seq,
 | 
						|
-			      vec<rtx_insn *> *delay_list, resources *sets,
 | 
						|
+			      vec<rtx_insn *> *delay_list,
 | 
						|
+			      struct resources *sets,
 | 
						|
 			      struct resources *needed,
 | 
						|
 			      struct resources *other_needed,
 | 
						|
 			      int slots_to_fill, int *pslots_filled,
 | 
						|
@@ -1048,7 +1049,7 @@ steal_delay_list_from_target (rtx_insn *
 | 
						|
   int used_annul = 0;
 | 
						|
   int i;
 | 
						|
   struct resources cc_set;
 | 
						|
-  bool *redundant;
 | 
						|
+  rtx_insn **redundant;
 | 
						|
 
 | 
						|
   /* We can't do anything if there are more delay slots in SEQ than we
 | 
						|
      can handle, or if we don't know that it will be a taken branch.
 | 
						|
@@ -1087,7 +1088,7 @@ steal_delay_list_from_target (rtx_insn *
 | 
						|
   if (! targetm.can_follow_jump (insn, seq->insn (0)))
 | 
						|
     return;
 | 
						|
 
 | 
						|
-  redundant = XALLOCAVEC (bool, XVECLEN (seq, 0));
 | 
						|
+  redundant = XALLOCAVEC (rtx_insn *, XVECLEN (seq, 0));
 | 
						|
   for (i = 1; i < seq->len (); i++)
 | 
						|
     {
 | 
						|
       rtx_insn *trial = seq->insn (i);
 | 
						|
@@ -1151,7 +1152,10 @@ steal_delay_list_from_target (rtx_insn *
 | 
						|
      we therefore decided not to copy.  */
 | 
						|
   for (i = 1; i < seq->len (); i++)
 | 
						|
     if (redundant[i])
 | 
						|
-      update_block (seq->insn (i), insn);
 | 
						|
+      {
 | 
						|
+	fix_reg_dead_note (redundant[i], insn);
 | 
						|
+	update_block (seq->insn (i), insn);
 | 
						|
+      }
 | 
						|
 
 | 
						|
   /* Show the place to which we will be branching.  */
 | 
						|
   *pnew_thread = first_active_target_insn (JUMP_LABEL (seq->insn (0)));
 | 
						|
@@ -1198,6 +1202,7 @@ steal_delay_list_from_fallthrough (rtx_i
 | 
						|
   for (i = 1; i < seq->len (); i++)
 | 
						|
     {
 | 
						|
       rtx_insn *trial = seq->insn (i);
 | 
						|
+      rtx_insn *prior_insn;
 | 
						|
 
 | 
						|
       /* If TRIAL sets CC0, stealing it will move it too far from the use
 | 
						|
 	 of CC0.  */
 | 
						|
@@ -1209,8 +1214,9 @@ steal_delay_list_from_fallthrough (rtx_i
 | 
						|
 	break;
 | 
						|
 
 | 
						|
       /* If this insn was already done, we don't need it.  */
 | 
						|
-      if (redundant_insn (trial, insn, *delay_list))
 | 
						|
+      if ((prior_insn = redundant_insn (trial, insn, *delay_list)))
 | 
						|
 	{
 | 
						|
+	  fix_reg_dead_note (prior_insn, insn);
 | 
						|
 	  update_block (trial, insn);
 | 
						|
 	  delete_from_delay_slot (trial);
 | 
						|
 	  continue;
 | 
						|
@@ -1790,15 +1796,14 @@ fix_reg_dead_note (rtx_insn *start_insn,
 | 
						|
       }
 | 
						|
 }
 | 
						|
 
 | 
						|
-/* Delete any REG_UNUSED notes that exist on INSN but not on REDUNDANT_INSN.
 | 
						|
+/* Delete any REG_UNUSED notes that exist on INSN but not on OTHER_INSN.
 | 
						|
 
 | 
						|
    This handles the case of udivmodXi4 instructions which optimize their
 | 
						|
-   output depending on whether any REG_UNUSED notes are present.
 | 
						|
-   we must make sure that INSN calculates as many results as REDUNDANT_INSN
 | 
						|
-   does.  */
 | 
						|
+   output depending on whether any REG_UNUSED notes are present.  We must
 | 
						|
+   make sure that INSN calculates as many results as OTHER_INSN does.  */
 | 
						|
 
 | 
						|
 static void
 | 
						|
-update_reg_unused_notes (rtx_insn *insn, rtx redundant_insn)
 | 
						|
+update_reg_unused_notes (rtx_insn *insn, rtx other_insn)
 | 
						|
 {
 | 
						|
   rtx link, next;
 | 
						|
 
 | 
						|
@@ -1810,8 +1815,7 @@ update_reg_unused_notes (rtx_insn *insn,
 | 
						|
 	  || !REG_P (XEXP (link, 0)))
 | 
						|
 	continue;
 | 
						|
 
 | 
						|
-      if (! find_regno_note (redundant_insn, REG_UNUSED,
 | 
						|
-			     REGNO (XEXP (link, 0))))
 | 
						|
+      if (!find_regno_note (other_insn, REG_UNUSED, REGNO (XEXP (link, 0))))
 | 
						|
 	remove_note (insn, link);
 | 
						|
     }
 | 
						|
 }
 | 
						|
@@ -2324,9 +2328,8 @@ follow_jumps (rtx label, rtx_insn *jump,
 | 
						|
    taken and THREAD_IF_TRUE is set.  This is used for the branch at the
 | 
						|
    end of a loop back up to the top.
 | 
						|
 
 | 
						|
-   OWN_THREAD and OWN_OPPOSITE_THREAD are true if we are the only user of the
 | 
						|
-   thread.  I.e., it is the fallthrough code of our jump or the target of the
 | 
						|
-   jump when we are the only jump going there.
 | 
						|
+   OWN_THREAD is true if we are the only user of the thread, i.e. it is
 | 
						|
+   the target of the jump when we are the only jump going there.
 | 
						|
 
 | 
						|
    If OWN_THREAD is false, it must be the "true" thread of a jump.  In that
 | 
						|
    case, we can only take insns from the head of the thread for our delay
 | 
						|
@@ -3117,7 +3120,7 @@ relax_delay_slots (rtx_insn *first)
 | 
						|
   /* Look at every JUMP_INSN and see if we can improve it.  */
 | 
						|
   for (insn = first; insn; insn = next)
 | 
						|
     {
 | 
						|
-      rtx_insn *other;
 | 
						|
+      rtx_insn *other, *prior_insn;
 | 
						|
       bool crossing;
 | 
						|
 
 | 
						|
       next = next_active_insn (insn);
 | 
						|
@@ -3223,8 +3226,9 @@ relax_delay_slots (rtx_insn *first)
 | 
						|
       /* See if the first insn in the delay slot is redundant with some
 | 
						|
 	 previous insn.  Remove it from the delay slot if so; then set up
 | 
						|
 	 to reprocess this insn.  */
 | 
						|
-      if (redundant_insn (pat->insn (1), delay_insn, vNULL))
 | 
						|
+      if ((prior_insn = redundant_insn (pat->insn (1), delay_insn, vNULL)))
 | 
						|
 	{
 | 
						|
+	  fix_reg_dead_note (prior_insn, insn);
 | 
						|
 	  update_block (pat->insn (1), insn);
 | 
						|
 	  delete_from_delay_slot (pat->insn (1));
 | 
						|
 	  next = prev_active_insn (next);
 |