bb-reorder.c (find_traces_1_round): Don't connect easy to copy successors with multip...
authorRichard Henderson <rth@redhat.com>
Sat, 15 Feb 2003 21:22:56 +0000 (13:22 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 15 Feb 2003 21:22:56 +0000 (13:22 -0800)
        * bb-reorder.c (find_traces_1_round): Don't connect easy to copy
        successors with multiple predecessors.
        (connect_traces): Try harder to copy traces of length 1.

        * function.h (struct function): Add computed_goto_common_label,
        computed_goto_common_reg.
        * function.c (free_after_compilation): Zap them.
        * stmt.c (expand_computed_goto): Use them to produce one
        indirect branch per function.

From-SVN: r62944

gcc/ChangeLog
gcc/bb-reorder.c
gcc/function.c
gcc/function.h
gcc/stmt.c

index adb0f78..0942b3a 100644 (file)
 
 2003-02-15  Richard Henderson  <rth@redhat.com>
 
+       * bb-reorder.c (find_traces_1_round): Don't connect easy to copy
+       successors with multiple predecessors.
+       (connect_traces): Try harder to copy traces of length 1.
+
+       * function.h (struct function): Add computed_goto_common_label,
+       computed_goto_common_reg.
+       * function.c (free_after_compilation): Zap them.
+       * stmt.c (expand_computed_goto): Use them to produce one 
+       indirect branch per function.
+
+2003-02-15  Richard Henderson  <rth@redhat.com>
+
        * cfgcleanup.c: Include params.h.
        (try_crossjump_bb): Use PARAM_MAX_CROSSJUMP_EDGES.  Fix test for
        too many outgoing edges from a block.
index 0711f18..49889ee 100644 (file)
@@ -448,6 +448,12 @@ find_traces_1_round (branch_th, exec_th, count_th, traces, n_traces, round,
                  || prob < branch_th || freq < exec_th || e->count < count_th)
                continue;
 
+             /* If the destination has multiple precessesors, and can be
+                duplicated cheaper than a jump, don't allow it to be added
+                to a trace.  We'll duplicate it when connecting traces.  */
+             if (e->dest->pred->pred_next && copy_bb_p (e->dest, 0))
+               continue;
+
              if (better_edge_p (bb, e, prob, freq, best_prob, best_freq))
                {
                  best_edge = e;
@@ -905,19 +911,27 @@ connect_traces (n_traces, traces)
              /* Try to connect the traces by duplication of 1 block.  */
              edge e2;
              basic_block next_bb = NULL;
+             bool try_copy = false;
 
              for (e = traces[t].last->succ; e; e = e->succ_next)
                if (e->dest != EXIT_BLOCK_PTR
                    && (e->flags & EDGE_CAN_FALLTHRU)
                    && !(e->flags & EDGE_COMPLEX)
-                   && (EDGE_FREQUENCY (e) >= freq_threshold)
-                   && (e->count >= count_threshold)
-                   && (!best
-                       || e->probability > best->probability))
+                   && (!best || e->probability > best->probability))
                  {
                    edge best2 = NULL;
                    int best2_len = 0;
 
+                   /* If the destination trace is only one block
+                      long, then no need to search the successor
+                      blocks of the trace.  Accept it.  */
+                  if (traces[bbd[e->dest->index].start_of_trace].length == 1)
+                    {
+                      best = e;
+                      try_copy = true;
+                      continue;
+                    }
+
                    for (e2 = e->dest->succ; e2; e2 = e2->succ_next)
                      {
                        int di = e2->dest->index;
@@ -942,10 +956,18 @@ connect_traces (n_traces, traces)
                            else
                              best2_len = INT_MAX;
                            next_bb = e2->dest;
+                           try_copy = true;
                          }
                      }
                  }
-             if (best && next_bb && copy_bb_p (best->dest, !optimize_size))
+
+             /* Copy tiny blocks always; copy larger blocks only when the
+                edge is traversed frequently enough.  */
+             if (try_copy
+                 && copy_bb_p (best->dest,
+                               !optimize_size
+                               && EDGE_FREQUENCY (best) >= freq_threshold
+                               && best->count >= count_threshold))
                {
                  basic_block new_bb;
 
@@ -953,7 +975,9 @@ connect_traces (n_traces, traces)
                    {
                      fprintf (rtl_dump_file, "Connection: %d %d ",
                               traces[t].last->index, best->dest->index);
-                     if (next_bb == EXIT_BLOCK_PTR)
+                     if (!next_bb)
+                       fputc ('\n', rtl_dump_file);
+                     else if (next_bb == EXIT_BLOCK_PTR)
                        fprintf (rtl_dump_file, "exit\n");
                      else
                        fprintf (rtl_dump_file, "%d\n", next_bb->index);
@@ -961,7 +985,7 @@ connect_traces (n_traces, traces)
 
                  new_bb = copy_bb (best->dest, best, traces[t].last, t);
                  traces[t].last = new_bb;
-                 if (next_bb != EXIT_BLOCK_PTR)
+                 if (next_bb && next_bb != EXIT_BLOCK_PTR)
                    {
                      t = bbd[next_bb->index].start_of_trace;
                      RBI (traces[last_trace].last)->next = traces[t].first;
index cb5cf64..b20d41f 100644 (file)
@@ -452,6 +452,8 @@ free_after_compilation (f)
   f->x_nonlocal_goto_stack_level = NULL;
   f->x_cleanup_label = NULL;
   f->x_return_label = NULL;
+  f->computed_goto_common_label = NULL;
+  f->computed_goto_common_reg = NULL;
   f->x_save_expr_regs = NULL;
   f->x_stack_slot_list = NULL;
   f->x_rtl_expr_chain = NULL;
index d92b815..5d4258f 100644 (file)
@@ -268,6 +268,10 @@ struct function GTY(())
      on machines which require execution of the epilogue on all returns.  */
   rtx x_return_label;
 
+  /* Label and register for unswitching computed gotos.  */
+  rtx computed_goto_common_label;
+  rtx computed_goto_common_reg;
+
   /* List (chain of EXPR_LISTs) of pseudo-regs of SAVE_EXPRs.
      So we can mark them all live at the end of the function, if nonopt.  */
   rtx x_save_expr_regs;
index f968012..bc7cc28 100644 (file)
@@ -539,10 +539,23 @@ expand_computed_goto (exp)
 #endif
 
   emit_queue ();
-  do_pending_stack_adjust ();
-  emit_indirect_jump (x);
 
-  current_function_has_computed_jump = 1;
+  if (! cfun->computed_goto_common_label)
+    {
+      cfun->computed_goto_common_reg = copy_to_mode_reg (Pmode, x);
+      cfun->computed_goto_common_label = gen_label_rtx ();
+      emit_label (cfun->computed_goto_common_label);
+  
+      do_pending_stack_adjust ();
+      emit_indirect_jump (cfun->computed_goto_common_reg);
+
+      current_function_has_computed_jump = 1;
+    }
+  else
+    {
+      emit_move_insn (cfun->computed_goto_common_reg, x);
+      emit_jump (cfun->computed_goto_common_label);
+    }
 }
 \f
 /* Handle goto statements and the labels that they can go to.  */