aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/doc/passes.texi17
-rw-r--r--gcc/gcse.c129
-rw-r--r--gcc/rtl.h3
-rw-r--r--gcc/timevar.def3
-rw-r--r--gcc/toplev.c28
6 files changed, 179 insertions, 15 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0d7d19c..a98b2b3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi
index 8a96a69..fe0fc2e 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -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
diff --git a/gcc/gcse.c b/gcc/gcse.c
index ae0a1ba..e8976cb 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -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 ();
}
+
+/* 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"
diff --git a/gcc/rtl.h b/gcc/rtl.h
index a2c7514..2066b77 100644
--- 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 */
diff --git a/gcc/timevar.def b/gcc/timevar.def
index 4d1eba8..766207e 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -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")
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 554f471..b860500 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -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. */