gcse.c (one_cprop_pass): Change function arguments to take both cprop_jumps and bypas...
authorRoger Sayle <roger@eyesopen.com>
Thu, 16 Jan 2003 01:06:33 +0000 (01:06 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Thu, 16 Jan 2003 01:06:33 +0000 (01:06 +0000)
* gcse.c (one_cprop_pass): Change function arguments to take both
cprop_jumps and bypass_jumps flags instead of just alter_jumps.
(gcse_main): Update calls to one_cprop_pass, disabling bypassing.
(bypass_jumps): New function to perform separate jump bypassing pass.
* rtl.h (bypass_jumps): Add function prototype.
* timevar.def (TV_BYPASS): New timing variable.
* toplev.c (enum dump_file_index): Add new entry DFI_bypass.
(dump_file): New entry for the bypass RTL dump file.
(rest_of_compilation): Insert new jump bypassing optimization
pass after loop.
* doc/passes.texi: Document new pass.

From-SVN: r61374

gcc/ChangeLog
gcc/doc/passes.texi
gcc/gcse.c
gcc/rtl.h
gcc/timevar.def
gcc/toplev.c

index 0d7d19c3e41f84e168600cc8f79ad57b889dd0ec..a98b2b356e865104747830d7be418d8780b83575 100644 (file)
@@ -1,3 +1,17 @@
+2003-01-15  Roger Sayle  <roger@eyesopen.com>
+
+       * gcse.c (one_cprop_pass): Change function arguments to take both
+       cprop_jumps and bypass_jumps flags instead of just alter_jumps.
+       (gcse_main): Update calls to one_cprop_pass, disabling bypassing.
+       (bypass_jumps): New function to perform separate jump bypassing pass.
+       * rtl.h (bypass_jumps): Add function prototype.
+       * timevar.def (TV_BYPASS): New timing variable.
+       * toplev.c (enum dump_file_index): Add new entry DFI_bypass.
+       (dump_file): New entry for the bypass RTL dump file.
+       (rest_of_compilation): Insert new jump bypassing optimization
+       pass after loop.
+       * doc/passes.texi: Document new pass.
+
 2003-01-15  John David Anglin  <dave@hiauly1.hia.nrc.ca>
 
        * som.h (SUPPORTS_WEAK, SUPPORTS_ONE_ONLY, MAKE_DECL_ONE_ONLY,
index 8a96a6924619534505e5b08377690062ba24f330..fe0fc2e086b3342f6e8fb28cdff2520de9d0ffee 100644 (file)
@@ -1,5 +1,5 @@
-@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002,
-@c 1999, 2000, 2001 Free Software Foundation, Inc.
+@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+@c 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 @c This is part of the GCC manual.
 @c For copying conditions, see the file gcc.texi.
 
@@ -338,6 +338,19 @@ The option @option{-dL} causes a debugging dump of the RTL code after
 this pass.  This dump file's name is made by appending @samp{.loop} to
 the input file name.
 
+@cindex jump bypassing
+@item
+Jump bypassing.  This pass is an aggressive form of GCSE that transforms
+the control flow graph of a function by propagating constants into
+conditional branch instructions.
+
+The source file for this pass is @file{gcse.c}.
+
+@opindex dG
+The option @option{-dG} causes a debugging dump of the RTL code after
+this pass.  This dump file's name is made by appending @samp{.bypass}
+to the input file name.
+
 @item
 @opindex frerun-cse-after-loop
 If @option{-frerun-cse-after-loop} was enabled, a second common
index ae0a1ba5752cccb06f857d893a9f3ac8ceff7e56..e8976cbe74d1439a9cf55261899097e74c10f3c0 100644 (file)
@@ -1,6 +1,6 @@
 /* Global common subexpression elimination/Partial redundancy elimination
    and global constant/copy propagation for GNU compiler.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -614,7 +614,7 @@ static int load_killed_in_block_p    PARAMS ((basic_block, int, rtx, int));
 static void canon_list_insert        PARAMS ((rtx, rtx, void *));
 static int cprop_insn          PARAMS ((rtx, int));
 static int cprop               PARAMS ((int));
-static int one_cprop_pass      PARAMS ((int, int));
+static int one_cprop_pass      PARAMS ((int, int, int));
 static bool constprop_register PARAMS ((rtx, rtx, rtx, int));
 static struct expr *find_bypass_set PARAMS ((int, int));
 static int bypass_block                    PARAMS ((basic_block, rtx, rtx));
@@ -819,7 +819,7 @@ gcse_main (f, file)
 
       /* Don't allow constant propagation to modify jumps
         during this pass.  */
-      changed = one_cprop_pass (pass + 1, 0);
+      changed = one_cprop_pass (pass + 1, 0, 0);
 
       if (optimize_size)
        changed |= one_classic_gcse_pass (pass + 1);
@@ -886,7 +886,7 @@ gcse_main (f, file)
   max_gcse_regno = max_reg_num ();
   alloc_gcse_mem (f);
   /* This time, go ahead and allow cprop to alter jumps.  */
-  one_cprop_pass (pass + 1, 1);
+  one_cprop_pass (pass + 1, 1, 0);
   free_gcse_mem ();
 
   if (file)
@@ -4463,20 +4463,22 @@ cprop (alter_jumps)
 }
 
 /* Perform one copy/constant propagation pass.
-   F is the first insn in the function.
-   PASS is the pass count.  */
+   PASS is the pass count.  If CPROP_JUMPS is true, perform constant
+   propagation into conditional jumps.  If BYPASS_JUMPS is true,
+   perform conditional jump bypassing optimizations.  */
 
 static int
-one_cprop_pass (pass, alter_jumps)
+one_cprop_pass (pass, cprop_jumps, bypass_jumps)
      int pass;
-     int alter_jumps;
+     int cprop_jumps;
+     int bypass_jumps;
 {
   int changed = 0;
 
   const_prop_count = 0;
   copy_prop_count = 0;
 
-  local_cprop_pass (alter_jumps);
+  local_cprop_pass (cprop_jumps);
 
   alloc_hash_table (max_cuid, &set_hash_table, 1);
   compute_hash_table (&set_hash_table);
@@ -4486,8 +4488,8 @@ one_cprop_pass (pass, alter_jumps)
     {
       alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
       compute_cprop_data ();
-      changed = cprop (alter_jumps);
-      if (alter_jumps)
+      changed = cprop (cprop_jumps);
+      if (bypass_jumps)
        changed |= bypass_conditional_jumps ();
       free_cprop_mem ();
     }
@@ -7348,4 +7350,109 @@ store_motion ()
   end_alias_analysis ();
 }
 
+\f
+/* Entry point for jump bypassing optimization pass.  */
+
+int
+bypass_jumps (file)
+     FILE *file;
+{
+  int changed;
+
+  /* We do not construct an accurate cfg in functions which call
+     setjmp, so just punt to be safe.  */
+  if (current_function_calls_setjmp)
+    return 0;
+
+  /* For calling dump_foo fns from gdb.  */
+  debug_stderr = stderr;
+  gcse_file = file;
+
+  /* Identify the basic block information for this function, including
+     successors and predecessors.  */
+  max_gcse_regno = max_reg_num ();
+
+  if (file)
+    dump_flow_info (file);
+
+  /* Return if there's nothing to do.  */
+  if (n_basic_blocks <= 1)
+    return 0;
+
+  /* Trying to perform global optimizations on flow graphs which have
+     a high connectivity will take a long time and is unlikely to be
+     particularly useful.
+
+     In normal circumstances a cfg should have about twice as many edges
+     as blocks.  But we do not want to punish small functions which have
+     a couple switch statements.  So we require a relatively large number
+     of basic blocks and the ratio of edges to blocks to be high.  */
+  if (n_basic_blocks > 1000 && n_edges / n_basic_blocks >= 20)
+    {
+      if (warn_disabled_optimization)
+        warning ("BYPASS disabled: %d > 1000 basic blocks and %d >= 20 edges/basic block",
+                 n_basic_blocks, n_edges / n_basic_blocks);
+      return 0;
+    }
+
+  /* If allocating memory for the cprop bitmap would take up too much
+     storage it's better just to disable the optimization.  */
+  if ((n_basic_blocks
+       * SBITMAP_SET_SIZE (max_gcse_regno)
+       * sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY)
+    {
+      if (warn_disabled_optimization)
+        warning ("GCSE disabled: %d basic blocks and %d registers",
+                 n_basic_blocks, max_gcse_regno);
+
+      return 0;
+    }
+
+  /* See what modes support reg/reg copy operations.  */
+  if (! can_copy_init_p)
+    {
+      compute_can_copy ();
+      can_copy_init_p = 1;
+    }
+
+  gcc_obstack_init (&gcse_obstack);
+  bytes_used = 0;
+
+  /* We need alias.  */
+  init_alias_analysis ();
+
+  /* Record where pseudo-registers are set.  This data is kept accurate
+     during each pass.  ??? We could also record hard-reg information here
+     [since it's unchanging], however it is currently done during hash table
+     computation.
+
+     It may be tempting to compute MEM set information here too, but MEM sets
+     will be subject to code motion one day and thus we need to compute
+     information about memory sets when we build the hash tables.  */
+
+  alloc_reg_set_mem (max_gcse_regno);
+  compute_sets (get_insns ());
+
+  max_gcse_regno = max_reg_num ();
+  alloc_gcse_mem (get_insns ());
+  changed = one_cprop_pass (1, 1, 1);
+  free_gcse_mem ();
+
+  if (file)
+    {
+      fprintf (file, "BYPASS of %s: %d basic blocks, ",
+              current_function_name, n_basic_blocks);
+      fprintf (file, "%d bytes\n\n", bytes_used);
+    }
+
+  obstack_free (&gcse_obstack, NULL);
+  free_reg_set_mem ();
+
+  /* We are finished with alias.  */
+  end_alias_analysis ();
+  allocate_reg_info (max_reg_num (), FALSE, FALSE);
+
+  return changed;
+}
+
 #include "gt-gcse.h"
index a2c7514a8989bf26a4031b9eb7a9853660d080f8..2066b77daa0a69a970d0124218fd6698eb9ac508 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1,6 +1,6 @@
 /* Register Transfer Language (RTL) definitions for GNU C-Compiler
    Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -2086,6 +2086,7 @@ extern rtx expand_mult_highpart           PARAMS ((enum machine_mode, rtx,
 /* In gcse.c */
 #ifdef BUFSIZ
 extern int gcse_main                   PARAMS ((rtx, FILE *));
+extern int bypass_jumps                        PARAMS ((FILE *));
 #endif
 
 /* In global.c */
index 4d1eba8465eb54e501dae72b24d69eecf5df792a..766207e78a6d18fe648c0e3cf96fc71f3532cff4 100644 (file)
@@ -1,6 +1,6 @@
 /* This file contains the definitions for timing variables used to
    measure run-time performance of the compiler.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Alex Samuel <samuel@codesourcery.com>
 
    This file is part of GCC.
@@ -59,6 +59,7 @@ DEFTIMEVAR (TV_JUMP                  , "jump")
 DEFTIMEVAR (TV_CSE                   , "CSE")
 DEFTIMEVAR (TV_GCSE                  , "global CSE")
 DEFTIMEVAR (TV_LOOP                  , "loop analysis")
+DEFTIMEVAR (TV_BYPASS                , "bypass jumps")
 DEFTIMEVAR (TV_TRACER                , "tracer")
 DEFTIMEVAR (TV_CSE2                  , "CSE 2")
 DEFTIMEVAR (TV_BRANCH_PROB           , "branch prediction")
index 554f471b3975cbeaebe542c8f3a9e01e45e99812..b860500a87182f9cef882ae1fdff7abf7805d429 100644 (file)
@@ -232,6 +232,7 @@ enum dump_file_index
   DFI_addressof,
   DFI_gcse,
   DFI_loop,
+  DFI_bypass,
   DFI_cfg,
   DFI_bp,
   DFI_ce1,
@@ -281,6 +282,7 @@ static struct dump_file_info dump_file[DFI_MAX] =
   { "addressof", 'F', 0, 0, 0 },
   { "gcse",    'G', 1, 0, 0 },
   { "loop",    'L', 1, 0, 0 },
+  { "bypass",   'G', 1, 0, 0 }, /* Yes, duplicate enable switch.  */
   { "cfg",     'f', 1, 0, 0 },
   { "bp",      'b', 1, 0, 0 },
   { "ce1",     'C', 1, 0, 0 },
@@ -2964,6 +2966,32 @@ rest_of_compilation (decl)
       ggc_collect ();
     }
 
+  /* Perform jump bypassing and control flow optimizations.  */
+  if (optimize > 0 && flag_gcse)
+    {
+      timevar_push (TV_BYPASS);
+      open_dump_file (DFI_bypass, decl);
+
+      cleanup_cfg (CLEANUP_EXPENSIVE);
+      tem = bypass_jumps (rtl_dump_file);
+
+      if (tem)
+        {
+          rebuild_jump_labels (insns);
+          cleanup_cfg (CLEANUP_EXPENSIVE);
+          delete_trivially_dead_insns (insns, max_reg_num ());
+        }
+
+      close_dump_file (DFI_bypass, print_rtl_with_bb, insns);
+      timevar_pop (TV_BYPASS);
+
+      ggc_collect ();
+
+#ifdef ENABLE_CHECKING
+      verify_flow_info ();
+#endif
+    }
+
   /* Do control and data flow analysis; wrote some of the results to
      the dump file.  */