Thu Aug 16 17:39:45 CEST 2001 Jan Hubicka <jh@suse.cz>
authorJan Hubicka <jh@suse.cz>
Thu, 16 Aug 2001 15:41:05 +0000 (17:41 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 16 Aug 2001 15:41:05 +0000 (15:41 +0000)
* function.c (put_var_into_stack): Temporarily clear DECL_RTL.
(assign_params): Avoid setting DECL_RTL to unfinished RTX.
(expand_function_start): Likewise.
* stmt.c (expand_decl): Likewise.
* varasm.c (make_decl_rtx): Likewise.

From-SVN: r44940

gcc/ChangeLog
gcc/doc/tm.texi
gcc/final.c
gcc/output.h

index 80ff580b7ec7ddf8c6bc73403532fdb0c0f75f85..6800290ebfec2341d81367e77006a17d34a01ea3 100644 (file)
@@ -1,3 +1,11 @@
+Thu Aug 16 17:39:45 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * function.c (put_var_into_stack): Temporarily clear DECL_RTL.
+       (assign_params): Avoid setting DECL_RTL to unfinished RTX.
+       (expand_function_start): Likewise.
+       * stmt.c (expand_decl): Likewise.
+       * varasm.c (make_decl_rtx): Likewise.
+
 2001-08-16  Jason Merrill  <jason_merrill@redhat.com>
 
        * stor-layout.c (layout_decl): Don't set DECL_USER_ALIGN.
index 538888b16d496927d882913661be7b0ef6aecdaa..d3e581975a9e8cd0a6b089476d4e0aabb7d0920a 100644 (file)
@@ -7137,10 +7137,10 @@ the target supports DWARF 2 frame unwind information.
 This describes commands for alignment.
 
 @table @code
-@findex LABEL_ALIGN_AFTER_BARRIER
-@item LABEL_ALIGN_AFTER_BARRIER (@var{label})
-The alignment (log base 2) to put in front of @var{label}, which follows
-a @code{BARRIER}.
+@findex JUMP_ALIGN_AFTER_BARRIER
+@item JUMP_ALIGN (@var{label})
+The alignment (log base 2) to put in front of @var{label}, which is
+a common destination of jumps and has no fallthru incomming edge.
 
 This macro need not be defined if you don't want any special alignment
 to be done at such a time.  Most machine descriptions do not currently
@@ -7149,8 +7149,17 @@ define the macro.
 Unless it's necessary to inspect the @var{label} parameter, it is better
 to set the variable @var{align_jumps} in the target's
 @code{OVERRIDE_OPTIONS}.  Otherwise, you should try to honour the user's
-selection in @var{align_jumps} in a @code{LABEL_ALIGN_AFTER_BARRIER}
-implementation.
+selection in @var{align_jumps} in a @code{JUMP_ALIGN} implementation.
+
+@table @code
+@findex LABEL_ALIGN_AFTER_BARRIER
+@item LABEL_ALIGN_AFTER_BARRIER (@var{label})
+The alignment (log base 2) to put in front of @var{label}, which follows
+a @code{BARRIER}.
+
+This macro need not be defined if you don't want any special alignment
+to be done at such a time.  Most machine descriptions do not currently
+define the macro.
 
 @findex LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
 @item LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
index d32248196a0066c1045a5b4e90766203d6c2e670..ad922915c85efd0a3a7d32a663b8ca9580b9274b 100644 (file)
@@ -632,11 +632,6 @@ static struct label_alignment *label_align;
 void
 init_insn_lengths ()
 {
-  if (label_align)
-    {
-      free (label_align);
-      label_align = 0;
-    }
   if (uid_shuid)
     {
       free (uid_shuid);
@@ -780,11 +775,19 @@ get_attr_length (insn)
 #endif
 
 #ifndef LABEL_ALIGN_AFTER_BARRIER
-#define LABEL_ALIGN_AFTER_BARRIER(LABEL) align_jumps_log
+#define LABEL_ALIGN_AFTER_BARRIER(LABEL) 1
 #endif
 
 #ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
-#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP (align_jumps-1)
+#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0
+#endif
+
+#ifndef JUMP_ALIGN
+#define JUMP_ALIGN(LABEL) align_jumps_log
+#endif
+
+#ifndef JUMP_ALIGN_MAX_SKIP
+#define JUMP_ALIGN_MAX_SKIP (align_jumps-1)
 #endif
 
 #ifndef ADDR_VEC_ALIGN
@@ -935,6 +938,85 @@ insn_current_reference_address (branch)
 }
 #endif /* HAVE_ATTR_length */
 \f
+void
+compute_alignments ()
+{
+  int i;
+  int log, max_skip, max_log;
+
+  if (label_align)
+    {
+      free (label_align);
+      label_align = 0;
+    }
+
+  max_labelno = max_label_num ();
+  min_labelno = get_first_label_num ();
+  label_align = (struct label_alignment *) xcalloc ((max_labelno - min_labelno + 1),
+            sizeof (struct label_alignment));
+
+  /* If not optimizing or optimizing for size, don't assign any alignments.  */
+  for (i = 0; i < n_basic_blocks; i++)
+    {
+      basic_block bb = BASIC_BLOCK (i);
+      rtx label = bb->head;
+      int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
+      edge e;
+
+      if (GET_CODE (label) != CODE_LABEL)
+       continue;
+      max_log = LABEL_ALIGN (label);
+      max_skip = LABEL_ALIGN_MAX_SKIP;
+
+      for (e = bb->pred; e; e = e->pred_next)
+       {
+         if (e->flags & EDGE_FALLTHRU)
+           has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e);
+         else
+           branch_frequency += EDGE_FREQUENCY (e);
+       }
+
+      /* There are two purposes to align block with no fallthru incomming edge:
+        1) to avoid fetch stalls when branch destination is near cache boundary
+        2) to improve cache effciency in case the previous block is not executed
+           (so it does not need to be in the cache).
+
+        We to catch first case, we align frequently executed blocks.
+        To catch the second, we align blocks that are executed more frequently
+        than the predecesor and the predecesor is likely to not be executed
+        when function is called.  */
+
+      if (!has_fallthru
+         && (branch_frequency > BB_FREQ_MAX / 10
+             || (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10
+                 && (BASIC_BLOCK (i - 1)->frequency
+                     <= ENTRY_BLOCK_PTR->frequency / 2))))
+       {
+         log = JUMP_ALIGN (label);
+         if (max_log < log)
+           {
+             max_log = log;
+             max_skip = JUMP_ALIGN_MAX_SKIP;
+           }
+       }
+      /* In case block is frequent and reached mostly by non-fallthru edge,
+        align it.  It is most likely an first block of loop.  */
+      if (has_fallthru
+         && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10
+         && branch_frequency > fallthru_frequency * 5)
+       {
+         log = LOOP_ALIGN (label);
+         if (max_log < log)
+           {
+             max_log = log;
+             max_skip = LOOP_ALIGN_MAX_SKIP;
+           }
+       }
+      LABEL_TO_ALIGNMENT (label) = max_log;
+      LABEL_TO_MAX_SKIP (label) = max_skip;
+    }
+}
+\f
 /* Make a pass over all insns and compute their actual lengths by shortening
    any branches of variable length if possible.  */
 
@@ -972,21 +1054,22 @@ shorten_branches (first)
 
 #endif
 
-  /* We must do some computations even when not actually shortening, in
-     order to get the alignment information for the labels.  */
-
-  init_insn_lengths ();
-
   /* Compute maximum UID and allocate label_align / uid_shuid.  */
   max_uid = get_max_uid ();
 
-  max_labelno = max_label_num ();
-  min_labelno = get_first_label_num ();
-  label_align = (struct label_alignment *)
-    xcalloc ((max_labelno - min_labelno + 1), sizeof (struct label_alignment));
-
   uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
 
+  if (max_labelno != max_label_num ())
+    {
+      int old = max_labelno;
+      max_labelno = max_label_num ();
+      label_align = (struct label_alignment *) xrealloc
+       (label_align,
+        (max_labelno - min_labelno + 1) * sizeof (struct label_alignment));
+      memset (label_align + old + 1 - min_labelno, 0,
+             sizeof (struct label_alignment) * (max_labelno - old));
+    }
+
   /* Initialize label_align and set up uid_shuid to be strictly
      monotonically rising with insn order.  */
   /* We use max_log here to keep track of the maximum alignment we want to
@@ -1012,6 +1095,14 @@ shorten_branches (first)
       else if (GET_CODE (insn) == CODE_LABEL)
        {
          rtx next;
+         
+         /* Merge in alignments computed by compute_alignments.  */
+         log = LABEL_TO_ALIGNMENT (insn);
+         if (max_log < log)
+           {
+             max_log = log;
+             max_skip = LABEL_TO_MAX_SKIP (insn);
+           }
 
          log = LABEL_ALIGN (insn);
          if (max_log < log)
@@ -1063,41 +1154,6 @@ shorten_branches (first)
                break;
              }
        }
-      /* Again, we allow NOTE_INSN_LOOP_BEG - INSN - CODE_LABEL
-        sequences in order to handle reorg output efficiently.  */
-      else if (GET_CODE (insn) == NOTE
-              && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
-       {
-         rtx label;
-         int nest = 0;
-
-         /* Search for the label that starts the loop.
-            Don't skip past the end of the loop, since that could
-            lead to putting an alignment where it does not belong.
-            However, a label after a nested (non-)loop would be OK.  */
-         for (label = insn; label; label = NEXT_INSN (label))
-           {
-             if (GET_CODE (label) == NOTE
-                 && NOTE_LINE_NUMBER (label) == NOTE_INSN_LOOP_BEG)
-               nest++;
-             else if (GET_CODE (label) == NOTE
-                      && NOTE_LINE_NUMBER (label) == NOTE_INSN_LOOP_END
-                      && --nest == 0)
-               break;
-             else if (GET_CODE (label) == CODE_LABEL)
-               {
-                 log = LOOP_ALIGN (label);
-                 if (max_log < log)
-                   {
-                     max_log = log;
-                     max_skip = LOOP_ALIGN_MAX_SKIP;
-                   }
-                 break;
-               }
-           }
-       }
-      else
-       continue;
     }
 #ifdef HAVE_ATTR_length
 
index a72f80dbf31c6956d2372686957679626af75238..c2cf497485d5dff80d076822815df1b418da349f 100644 (file)
@@ -20,6 +20,9 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
+/* Compute branch alignments based on frequency information in the CFG.  */
+extern void compute_alignments  PARAMS ((void));
+
 /* Initialize data in final at the beginning of a compilation.  */
 extern void init_final         PARAMS ((const char *));