Patchwork Preserve label alignment info through dbr

login
register
mail settings
Submitter Eric Botcazou
Date July 10, 2013, 9:37 a.m.
Message ID <1821473.SyjjZnTRdx@polaris>
Download mbox | patch
Permalink /patch/257994/
State New
Headers show

Comments

Eric Botcazou - July 10, 2013, 9:37 a.m.
Hi,

I was a little surprised to find out that dbr can silently drop the alignment 
information for labels computed when the CFG is valid (in compute_alignments). 
The pessimization can be significant for loops when the top label needs to be 
overaligned, as seen on a private port.  Hence the attached patch.

Tested on SPARC/Solaris and SPARC64/Solaris, any objections?


2013-07-10  Eric Botcazou  <ebotcazou@adacore.com>

	* rtl.h (update_alignments): Declare.
	* final.c (grow_label_align): New function extracted from...
	(shorten_branches): ...here.  Call it.
	(update_alignments): New function.
	* reorg.c (sibling_labels): New variable.
	(get_label_before): Add SIBLING parameter.  If it is non-zero, push
	the new label along with it onto the sibling_labels vector.
	(fill_simple_delay_slots): Adjust call to get_label_before.
	(fill_slots_from_thread): Likewise.
	(relax_delay_slots): Likewise.
	(make_return_insns): Likewise.
	(dbr_schedule): Invoke update_alignment on the sibling_labels vector.
Jeff Law - July 17, 2013, 9:03 p.m.
On 07/10/2013 03:37 AM, Eric Botcazou wrote:
> Hi,
>
> I was a little surprised to find out that dbr can silently drop the alignment
> information for labels computed when the CFG is valid (in compute_alignments).
> The pessimization can be significant for loops when the top label needs to be
> overaligned, as seen on a private port.  Hence the attached patch.
>
> Tested on SPARC/Solaris and SPARC64/Solaris, any objections?
>
>
> 2013-07-10  Eric Botcazou  <ebotcazou@adacore.com>
>
> 	* rtl.h (update_alignments): Declare.
> 	* final.c (grow_label_align): New function extracted from...
> 	(shorten_branches): ...here.  Call it.
> 	(update_alignments): New function.
> 	* reorg.c (sibling_labels): New variable.
> 	(get_label_before): Add SIBLING parameter.  If it is non-zero, push
> 	the new label along with it onto the sibling_labels vector.
> 	(fill_simple_delay_slots): Adjust call to get_label_before.
> 	(fill_slots_from_thread): Likewise.
> 	(relax_delay_slots): Likewise.
> 	(make_return_insns): Likewise.
> 	(dbr_schedule): Invoke update_alignment on the sibling_labels vector.
>
>
Looks good to me.

jeff

Patch

Index: rtl.h
===================================================================
--- rtl.h	(revision 200780)
+++ rtl.h	(working copy)
@@ -2749,6 +2749,7 @@  extern void simplify_using_condition (rt
 
 /* In final.c  */
 extern unsigned int compute_alignments (void);
+extern void update_alignments (vec<rtx> &);
 extern int asm_str_count (const char *templ);
 
 struct rtl_hooks
Index: final.c
===================================================================
--- final.c	(revision 200780)
+++ final.c	(working copy)
@@ -814,7 +814,53 @@  struct rtl_opt_pass pass_compute_alignme
   TODO_verify_rtl_sharing               /* todo_flags_finish */
  }
 };
+
+/* Grow the LABEL_ALIGN array after new labels are created.  */
+
+static void 
+grow_label_align (void)
+{
+  int old = max_labelno;
+  int n_labels;
+  int n_old_labels;
+
+  max_labelno = max_label_num ();
+
+  n_labels = max_labelno - min_labelno + 1;
+  n_old_labels = old - min_labelno + 1;
 
+  label_align = XRESIZEVEC (struct label_alignment, label_align, n_labels);
+
+  /* Range of labels grows monotonically in the function.  Failing here
+     means that the initialization of array got lost.  */
+  gcc_assert (n_old_labels <= n_labels);
+
+  memset (label_align + n_old_labels, 0,
+          (n_labels - n_old_labels) * sizeof (struct label_alignment));
+}
+
+/* Update the already computed alignment information.  LABEL_PAIRS is a vector
+   made up of pairs of labels for which the alignment information of the first
+   element will be copied from that of the second element.  */
+
+void
+update_alignments (vec<rtx> &label_pairs)
+{
+  unsigned int i = 0;
+  rtx iter, label;
+
+  if (max_labelno != max_label_num ())
+    grow_label_align ();
+
+  FOR_EACH_VEC_ELT (label_pairs, i, iter)
+    if (i & 1)
+      {
+	LABEL_TO_ALIGNMENT (label) = LABEL_TO_ALIGNMENT (iter);
+	LABEL_TO_MAX_SKIP (label) = LABEL_TO_MAX_SKIP (iter);
+      }
+    else
+      label = iter;
+}
 
 /* Make a pass over all insns and compute their actual lengths by shortening
    any branches of variable length if possible.  */
@@ -852,25 +898,7 @@  shorten_branches (rtx first)
   uid_shuid = XNEWVEC (int, max_uid);
 
   if (max_labelno != max_label_num ())
-    {
-      int old = max_labelno;
-      int n_labels;
-      int n_old_labels;
-
-      max_labelno = max_label_num ();
-
-      n_labels = max_labelno - min_labelno + 1;
-      n_old_labels = old - min_labelno + 1;
-
-      label_align = XRESIZEVEC (struct label_alignment, label_align, n_labels);
-
-      /* Range of labels grows monotonically in the function.  Failing here
-         means that the initialization of array got lost.  */
-      gcc_assert (n_old_labels <= n_labels);
-
-      memset (label_align + n_old_labels, 0,
-	      (n_labels - n_old_labels) * sizeof (struct label_alignment));
-    }
+    grow_label_align ();
 
   /* Initialize label_align and set up uid_shuid to be strictly
      monotonically rising with insn order.  */
Index: reorg.c
===================================================================
--- reorg.c	(revision 200780)
+++ reorg.c	(working copy)
@@ -1856,10 +1856,15 @@  update_reg_unused_notes (rtx insn, rtx r
     }
 }
 
-/* Return the label before INSN, or put a new label there.  */
+static vec <rtx> sibling_labels;
+
+/* Return the label before INSN, or put a new label there.  If SIBLING is
+   non-zero, it is another label associated with the new label (if any),
+   typically the former target of the jump that will be redirected to
+   the new label.  */
 
 static rtx
-get_label_before (rtx insn)
+get_label_before (rtx insn, rtx sibling)
 {
   rtx label;
 
@@ -1874,6 +1879,11 @@  get_label_before (rtx insn)
       label = gen_label_rtx ();
       emit_label_after (label, prev);
       LABEL_NUSES (label) = 0;
+      if (sibling)
+	{
+	  sibling_labels.safe_push (label);
+	  sibling_labels.safe_push (sibling);
+	}
     }
   return label;
 }
@@ -2219,7 +2229,7 @@  fill_simple_delay_slots (int non_jumps_p
 	      rtx new_label = next_real_insn (next_trial);
 
 	      if (new_label != 0)
-		new_label = get_label_before (new_label);
+		new_label = get_label_before (new_label, JUMP_LABEL (trial));
 	      else
 		new_label = find_end_label (simple_return_rtx);
 
@@ -2770,7 +2780,7 @@  fill_slots_from_thread (rtx insn, rtx co
       else if (LABEL_P (new_thread))
 	label = new_thread;
       else
-	label = get_label_before (new_thread);
+	label = get_label_before (new_thread, JUMP_LABEL (insn));
 
       if (label)
 	{
@@ -3321,7 +3331,7 @@  relax_delay_slots (rtx first)
 	      
 	      /* Now emit a label before the special USE insn, and
 		 redirect our jump to the new label.  */
-	      target_label = get_label_before (PREV_INSN (tmp));
+	      target_label = get_label_before (PREV_INSN (tmp), target_label);
 	      reorg_redirect_jump (delay_insn, target_label);
 	      next = insn;
 	      continue;
@@ -3495,7 +3505,7 @@  make_return_insns (rtx first)
   for (insn = first; insn; insn = NEXT_INSN (insn))
     if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
       {
-	rtx t = get_label_before (insn);
+	rtx t = get_label_before (insn, NULL_RTX);
 	if (PATTERN (insn) == ret_rtx)
 	  real_return_label = t;
 	else
@@ -3825,6 +3835,12 @@  dbr_schedule (rtx first)
       fprintf (dump_file, "\n");
     }
 
+  if (!sibling_labels.is_empty ())
+    {
+      update_alignments (sibling_labels);
+      sibling_labels.release ();
+    }
+
   free_resource_info ();
   free (uid_to_ruid);
   crtl->dbr_scheduled_p = true;