Commit a0134312 by Roger Sayle Committed by Roger Sayle

gcse.c (one_cprop_pass): Change function arguments to take both cprop_jumps and…

gcse.c (one_cprop_pass): Change function arguments to take both cprop_jumps and bypass_jumps flags...


	* 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
parent 6b543e86
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> 2003-01-15 John David Anglin <dave@hiauly1.hia.nrc.ca>
* som.h (SUPPORTS_WEAK, SUPPORTS_ONE_ONLY, MAKE_DECL_ONE_ONLY, * som.h (SUPPORTS_WEAK, SUPPORTS_ONE_ONLY, MAKE_DECL_ONE_ONLY,
......
@c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002, @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
@c 1999, 2000, 2001 Free Software Foundation, Inc. @c 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
@c This is part of the GCC manual. @c This is part of the GCC manual.
@c For copying conditions, see the file gcc.texi. @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 ...@@ -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 this pass. This dump file's name is made by appending @samp{.loop} to
the input file name. 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 @item
@opindex frerun-cse-after-loop @opindex frerun-cse-after-loop
If @option{-frerun-cse-after-loop} was enabled, a second common If @option{-frerun-cse-after-loop} was enabled, a second common
......
/* Global common subexpression elimination/Partial redundancy elimination /* Global common subexpression elimination/Partial redundancy elimination
and global constant/copy propagation for GNU compiler. 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. Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
...@@ -614,7 +614,7 @@ static int load_killed_in_block_p PARAMS ((basic_block, int, rtx, int)); ...@@ -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 void canon_list_insert PARAMS ((rtx, rtx, void *));
static int cprop_insn PARAMS ((rtx, int)); static int cprop_insn PARAMS ((rtx, int));
static int cprop PARAMS ((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 bool constprop_register PARAMS ((rtx, rtx, rtx, int));
static struct expr *find_bypass_set PARAMS ((int, int)); static struct expr *find_bypass_set PARAMS ((int, int));
static int bypass_block PARAMS ((basic_block, rtx, rtx)); static int bypass_block PARAMS ((basic_block, rtx, rtx));
...@@ -819,7 +819,7 @@ gcse_main (f, file) ...@@ -819,7 +819,7 @@ gcse_main (f, file)
/* Don't allow constant propagation to modify jumps /* Don't allow constant propagation to modify jumps
during this pass. */ during this pass. */
changed = one_cprop_pass (pass + 1, 0); changed = one_cprop_pass (pass + 1, 0, 0);
if (optimize_size) if (optimize_size)
changed |= one_classic_gcse_pass (pass + 1); changed |= one_classic_gcse_pass (pass + 1);
...@@ -886,7 +886,7 @@ gcse_main (f, file) ...@@ -886,7 +886,7 @@ gcse_main (f, file)
max_gcse_regno = max_reg_num (); max_gcse_regno = max_reg_num ();
alloc_gcse_mem (f); alloc_gcse_mem (f);
/* This time, go ahead and allow cprop to alter jumps. */ /* 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 (); free_gcse_mem ();
if (file) if (file)
...@@ -4463,20 +4463,22 @@ cprop (alter_jumps) ...@@ -4463,20 +4463,22 @@ cprop (alter_jumps)
} }
/* Perform one copy/constant propagation pass. /* Perform one copy/constant propagation pass.
F is the first insn in the function. PASS is the pass count. If CPROP_JUMPS is true, perform constant
PASS is the pass count. */ propagation into conditional jumps. If BYPASS_JUMPS is true,
perform conditional jump bypassing optimizations. */
static int static int
one_cprop_pass (pass, alter_jumps) one_cprop_pass (pass, cprop_jumps, bypass_jumps)
int pass; int pass;
int alter_jumps; int cprop_jumps;
int bypass_jumps;
{ {
int changed = 0; int changed = 0;
const_prop_count = 0; const_prop_count = 0;
copy_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); alloc_hash_table (max_cuid, &set_hash_table, 1);
compute_hash_table (&set_hash_table); compute_hash_table (&set_hash_table);
...@@ -4486,8 +4488,8 @@ one_cprop_pass (pass, alter_jumps) ...@@ -4486,8 +4488,8 @@ one_cprop_pass (pass, alter_jumps)
{ {
alloc_cprop_mem (last_basic_block, set_hash_table.n_elems); alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
compute_cprop_data (); compute_cprop_data ();
changed = cprop (alter_jumps); changed = cprop (cprop_jumps);
if (alter_jumps) if (bypass_jumps)
changed |= bypass_conditional_jumps (); changed |= bypass_conditional_jumps ();
free_cprop_mem (); free_cprop_mem ();
} }
...@@ -7348,4 +7350,109 @@ store_motion () ...@@ -7348,4 +7350,109 @@ store_motion ()
end_alias_analysis (); 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" #include "gt-gcse.h"
/* Register Transfer Language (RTL) definitions for GNU C-Compiler /* Register Transfer Language (RTL) definitions for GNU C-Compiler
Copyright (C) 1987, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 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. This file is part of GCC.
...@@ -2086,6 +2086,7 @@ extern rtx expand_mult_highpart PARAMS ((enum machine_mode, rtx, ...@@ -2086,6 +2086,7 @@ extern rtx expand_mult_highpart PARAMS ((enum machine_mode, rtx,
/* In gcse.c */ /* In gcse.c */
#ifdef BUFSIZ #ifdef BUFSIZ
extern int gcse_main PARAMS ((rtx, FILE *)); extern int gcse_main PARAMS ((rtx, FILE *));
extern int bypass_jumps PARAMS ((FILE *));
#endif #endif
/* In global.c */ /* In global.c */
......
/* This file contains the definitions for timing variables used to /* This file contains the definitions for timing variables used to
measure run-time performance of the compiler. 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> Contributed by Alex Samuel <samuel@codesourcery.com>
This file is part of GCC. This file is part of GCC.
...@@ -59,6 +59,7 @@ DEFTIMEVAR (TV_JUMP , "jump") ...@@ -59,6 +59,7 @@ DEFTIMEVAR (TV_JUMP , "jump")
DEFTIMEVAR (TV_CSE , "CSE") DEFTIMEVAR (TV_CSE , "CSE")
DEFTIMEVAR (TV_GCSE , "global CSE") DEFTIMEVAR (TV_GCSE , "global CSE")
DEFTIMEVAR (TV_LOOP , "loop analysis") DEFTIMEVAR (TV_LOOP , "loop analysis")
DEFTIMEVAR (TV_BYPASS , "bypass jumps")
DEFTIMEVAR (TV_TRACER , "tracer") DEFTIMEVAR (TV_TRACER , "tracer")
DEFTIMEVAR (TV_CSE2 , "CSE 2") DEFTIMEVAR (TV_CSE2 , "CSE 2")
DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction") DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction")
......
...@@ -232,6 +232,7 @@ enum dump_file_index ...@@ -232,6 +232,7 @@ enum dump_file_index
DFI_addressof, DFI_addressof,
DFI_gcse, DFI_gcse,
DFI_loop, DFI_loop,
DFI_bypass,
DFI_cfg, DFI_cfg,
DFI_bp, DFI_bp,
DFI_ce1, DFI_ce1,
...@@ -281,6 +282,7 @@ static struct dump_file_info dump_file[DFI_MAX] = ...@@ -281,6 +282,7 @@ static struct dump_file_info dump_file[DFI_MAX] =
{ "addressof", 'F', 0, 0, 0 }, { "addressof", 'F', 0, 0, 0 },
{ "gcse", 'G', 1, 0, 0 }, { "gcse", 'G', 1, 0, 0 },
{ "loop", 'L', 1, 0, 0 }, { "loop", 'L', 1, 0, 0 },
{ "bypass", 'G', 1, 0, 0 }, /* Yes, duplicate enable switch. */
{ "cfg", 'f', 1, 0, 0 }, { "cfg", 'f', 1, 0, 0 },
{ "bp", 'b', 1, 0, 0 }, { "bp", 'b', 1, 0, 0 },
{ "ce1", 'C', 1, 0, 0 }, { "ce1", 'C', 1, 0, 0 },
...@@ -2964,6 +2966,32 @@ rest_of_compilation (decl) ...@@ -2964,6 +2966,32 @@ rest_of_compilation (decl)
ggc_collect (); 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 /* Do control and data flow analysis; wrote some of the results to
the dump file. */ the dump file. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment