Commit 5e962776 by Zdenek Dvorak Committed by Zdenek Dvorak

loop-invariant.c: New file.

	* loop-invariant.c: New file.
	* Makefile.in (loop-invariant.o): New.
	* cfgloop.h (global_cost_for_size, init_set_costs,
	move_loop_invariants): Declare.
	* cfgloopanal.c (seq_cost, init_set_costs, global_cost_for_size): New
	functions.
	(avail_regs, res_regs, small_cost, pres_cost, spill_cost): New
	variables.
	* common.opt (floop-optimize2, fmove-loop-invariants): New options.
	* loop-init.c (loop_optimizer_init): Call init_set_costs.
	* passes.c (rest_of_handle_loop2): Call move_loop_invariants.
	(rest_of_compilation): Check flag_loop_optimize2.
	* toplev.c (process_options): Handle flag_loop_optimize2.
	* doc/invoke.texi (-floop-optimize2, -fmove-loop-invariants): Document.
	* doc/passes.texi (loop-invariant.c): Document.

From-SVN: r83419
parent 2e24fa83
2004-06-20 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> 2004-06-20 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* loop-invariant.c: New file.
* Makefile.in (loop-invariant.o): New.
* cfgloop.h (global_cost_for_size, init_set_costs,
move_loop_invariants): Declare.
* cfgloopanal.c (seq_cost, init_set_costs, global_cost_for_size): New
functions.
(avail_regs, res_regs, small_cost, pres_cost, spill_cost): New
variables.
* common.opt (floop-optimize2, fmove-loop-invariants): New options.
* loop-init.c (loop_optimizer_init): Call init_set_costs.
* passes.c (rest_of_handle_loop2): Call move_loop_invariants.
(rest_of_compilation): Check flag_loop_optimize2.
* toplev.c (process_options): Handle flag_loop_optimize2.
* doc/invoke.texi (-floop-optimize2, -fmove-loop-invariants): Document.
* doc/passes.texi (loop-invariant.c): Document.
2004-06-20 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* tree-ssa-pre.c (compute_antic): Keep BB_VISITED flag zeroed. * tree-ssa-pre.c (compute_antic): Keep BB_VISITED flag zeroed.
2004-06-20 Richard Henderson <rth@redhat.com> 2004-06-20 Richard Henderson <rth@redhat.com>
......
...@@ -897,7 +897,7 @@ OBJS-common = \ ...@@ -897,7 +897,7 @@ OBJS-common = \
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \ cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \ cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \
cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \ cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \
dbxout.o ddg.o \ dbxout.o ddg.o loop-invariant.o \
debug.o df.o diagnostic.o dojump.o dominance.o loop-doloop.o \ debug.o df.o diagnostic.o dojump.o dominance.o loop-doloop.o \
dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o \ dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o \
expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \ expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \
...@@ -1952,6 +1952,9 @@ cfgloopanal.o : cfgloopanal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ ...@@ -1952,6 +1952,9 @@ cfgloopanal.o : cfgloopanal.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H)
loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(GGC_H) \ loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(GGC_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H)
loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(GGC_H) \
$(BASIC_BLOCK_H) hard-reg-set.h cfgloop.h $(EXPR_H) coretypes.h $(TM_H) \
function.h flags.h df.h
cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) output.h coretypes.h $(TM_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) output.h coretypes.h $(TM_H)
loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \ loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
......
...@@ -411,6 +411,11 @@ simple_loop_desc (struct loop *loop) ...@@ -411,6 +411,11 @@ simple_loop_desc (struct loop *loop)
return loop->aux; return loop->aux;
} }
/* Register pressure estimation for induction variable optimizations & loop
invariant motion. */
extern unsigned global_cost_for_size (unsigned, unsigned, unsigned);
extern void init_set_costs (void);
/* Loop optimizer initialization. */ /* Loop optimizer initialization. */
extern struct loops *loop_optimizer_init (FILE *); extern struct loops *loop_optimizer_init (FILE *);
extern void loop_optimizer_finalize (struct loops *, FILE *); extern void loop_optimizer_finalize (struct loops *, FILE *);
...@@ -427,5 +432,6 @@ enum ...@@ -427,5 +432,6 @@ enum
extern void unroll_and_peel_loops (struct loops *, int); extern void unroll_and_peel_loops (struct loops *, int);
extern void doloop_optimize_loops (struct loops *); extern void doloop_optimize_loops (struct loops *);
extern void move_loop_invariants (struct loops *);
#endif /* GCC_CFGLOOP_H */ #endif /* GCC_CFGLOOP_H */
...@@ -474,3 +474,92 @@ get_loop_level (const struct loop *loop) ...@@ -474,3 +474,92 @@ get_loop_level (const struct loop *loop)
} }
return mx; return mx;
} }
/* Returns estimate on cost of computing SEQ. */
static unsigned
seq_cost (rtx seq)
{
unsigned cost = 0;
rtx set;
for (; seq; seq = NEXT_INSN (seq))
{
set = single_set (seq);
if (set)
cost += rtx_cost (set, SET);
else
cost++;
}
return cost;
}
/* The properties of the target. */
static unsigned avail_regs; /* Number of available registers. */
static unsigned res_regs; /* Number of reserved registers. */
static unsigned small_cost; /* The cost for register when there is a free one. */
static unsigned pres_cost; /* The cost for register when there are not too many
free ones. */
static unsigned spill_cost; /* The cost for register when we need to spill. */
/* Initialize the constants for computing set costs. */
void
init_set_costs (void)
{
rtx seq;
rtx reg1 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER);
rtx reg2 = gen_raw_REG (SImode, FIRST_PSEUDO_REGISTER + 1);
rtx addr = gen_raw_REG (Pmode, FIRST_PSEUDO_REGISTER + 2);
rtx mem = validize_mem (gen_rtx_MEM (SImode, addr));
unsigned i;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)
&& !fixed_regs[i])
avail_regs++;
res_regs = 3;
/* These are really just heuristic values. */
start_sequence ();
emit_move_insn (reg1, reg2);
seq = get_insns ();
end_sequence ();
small_cost = seq_cost (seq);
pres_cost = 2 * small_cost;
start_sequence ();
emit_move_insn (mem, reg1);
emit_move_insn (reg2, mem);
seq = get_insns ();
end_sequence ();
spill_cost = seq_cost (seq);
}
/* Calculates cost for having SIZE new loop global variables. REGS_USED is the
number of global registers used in loop. N_USES is the number of relevant
variable uses. */
unsigned
global_cost_for_size (unsigned size, unsigned regs_used, unsigned n_uses)
{
unsigned regs_needed = regs_used + size;
unsigned cost = 0;
if (regs_needed + res_regs <= avail_regs)
cost += small_cost * size;
else if (regs_needed <= avail_regs)
cost += pres_cost * size;
else
{
cost += pres_cost * size;
cost += spill_cost * n_uses * (regs_needed - avail_regs) / regs_needed;
}
return cost;
}
...@@ -447,6 +447,10 @@ floop-optimize ...@@ -447,6 +447,10 @@ floop-optimize
Common Report Var(flag_loop_optimize) Common Report Var(flag_loop_optimize)
Perform loop optimizations Perform loop optimizations
floop-optimize2
Common Report Var(flag_loop_optimize2)
Perform loop optimizations using the new loop optimizer
fmath-errno fmath-errno
Common Report Var(flag_errno_math) Init(1) Common Report Var(flag_errno_math) Init(1)
Set errno after built-in math functions Set errno after built-in math functions
...@@ -475,6 +479,10 @@ fmove-all-movables ...@@ -475,6 +479,10 @@ fmove-all-movables
Common Report Var(flag_move_all_movables) Common Report Var(flag_move_all_movables)
Force all loop invariant computations out of loops Force all loop invariant computations out of loops
fmove-loop-invariants
Common Report Var(flag_move_loop_invariants)
Move loop invariant computations out of loops
fmudflap fmudflap
Common RejectNegative Report Var(flag_mudflap) Common RejectNegative Report Var(flag_mudflap)
Add mudflap bounds-checking instrumentation for single-threaded program. Add mudflap bounds-checking instrumentation for single-threaded program.
......
...@@ -290,7 +290,7 @@ in the following sections. ...@@ -290,7 +290,7 @@ in the following sections.
-finline-functions -finline-limit=@var{n} -fkeep-inline-functions @gol -finline-functions -finline-limit=@var{n} -fkeep-inline-functions @gol
-fkeep-static-consts -fmerge-constants -fmerge-all-constants @gol -fkeep-static-consts -fmerge-constants -fmerge-all-constants @gol
-fmodulo-sched -fmove-all-movables -fnew-ra -fno-branch-count-reg @gol -fmodulo-sched -fmove-all-movables -fnew-ra -fno-branch-count-reg @gol
-fno-default-inline -fno-defer-pop @gol -fno-default-inline -fno-defer-pop -floop-optimize2 -fmove-loop-invariants @gol
-fno-function-cse -fno-guess-branch-probability @gol -fno-function-cse -fno-guess-branch-probability @gol
-fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol -fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
-funsafe-math-optimizations -ffinite-math-only @gol -funsafe-math-optimizations -ffinite-math-only @gol
...@@ -4191,6 +4191,12 @@ well. ...@@ -4191,6 +4191,12 @@ well.
Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}. Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}.
@item -floop-optimize2
@opindex floop-optimize2
Perform loop optimizations using the new loop optimizer. The optimizations
(loop unrolling, peeling and unswitching, loop invariant motion) are enabled
by separate flags.
@item -fcrossjumping @item -fcrossjumping
@opindex crossjumping @opindex crossjumping
Perform cross-jumping transformation. This transformation unifies equivalent code and save code size. The Perform cross-jumping transformation. This transformation unifies equivalent code and save code size. The
...@@ -4922,6 +4928,11 @@ roll much (from profile feedback). It also turns on complete loop peeling ...@@ -4922,6 +4928,11 @@ roll much (from profile feedback). It also turns on complete loop peeling
Enabled with @option{-fprofile-use}. Enabled with @option{-fprofile-use}.
@item -fmove-loop-invariants
@opindex fmove-loop-invariants
Enables the loop invariant motion pass in the new loop optimizer. Enabled
at level @option{-O1}
@item -funswitch-loops @item -funswitch-loops
@opindex funswitch-loops @opindex funswitch-loops
Move branches with loop invariant conditions out of the loop, with duplicates Move branches with loop invariant conditions out of the loop, with duplicates
......
...@@ -520,6 +520,8 @@ Its source files are @file{loop.c} and @file{unroll.c}, plus the header ...@@ -520,6 +520,8 @@ Its source files are @file{loop.c} and @file{unroll.c}, plus the header
@file{loop.h} used for communication between them. Loop unrolling uses @file{loop.h} used for communication between them. Loop unrolling uses
some functions in @file{integrate.c} and the header @file{integrate.h}. some functions in @file{integrate.c} and the header @file{integrate.h}.
Loop dependency analysis routines are contained in @file{dependence.c}. Loop dependency analysis routines are contained in @file{dependence.c}.
This pass is seriously out-of-date and is supposed to be replaced by
a new one described below in near future.
A second loop optimization pass takes care of basic block level A second loop optimization pass takes care of basic block level
optimizations---unrolling, peeling and unswitching loops. The source optimizations---unrolling, peeling and unswitching loops. The source
...@@ -527,6 +529,8 @@ files are @file{cfgloopanal.c} and @file{cfgloopmanip.c} containing ...@@ -527,6 +529,8 @@ files are @file{cfgloopanal.c} and @file{cfgloopmanip.c} containing
generic loop analysis and manipulation code, @file{loop-init.c} with generic loop analysis and manipulation code, @file{loop-init.c} with
initialization and finalization code, @file{loop-unswitch.c} for loop initialization and finalization code, @file{loop-unswitch.c} for loop
unswitching and @file{loop-unroll.c} for loop unrolling and peeling. unswitching and @file{loop-unroll.c} for loop unrolling and peeling.
It also contains a separate loop invariant motion pass implemented in
@file{loop-invariant.c}.
@item Jump bypassing @item Jump bypassing
......
...@@ -35,6 +35,13 @@ loop_optimizer_init (FILE *dumpfile) ...@@ -35,6 +35,13 @@ loop_optimizer_init (FILE *dumpfile)
{ {
struct loops *loops = xcalloc (1, sizeof (struct loops)); struct loops *loops = xcalloc (1, sizeof (struct loops));
edge e; edge e;
static bool first_time = true;
if (first_time)
{
first_time = false;
init_set_costs ();
}
/* Avoid annoying special cases of edges going to exit /* Avoid annoying special cases of edges going to exit
block. */ block. */
......
...@@ -1290,7 +1290,8 @@ rest_of_handle_loop2 (void) ...@@ -1290,7 +1290,8 @@ rest_of_handle_loop2 (void)
struct loops *loops; struct loops *loops;
basic_block bb; basic_block bb;
if (!flag_unswitch_loops if (!flag_move_loop_invariants
&& !flag_unswitch_loops
&& !flag_peel_loops && !flag_peel_loops
&& !flag_unroll_loops && !flag_unroll_loops
&& !flag_branch_on_count_reg) && !flag_branch_on_count_reg)
...@@ -1309,6 +1310,9 @@ rest_of_handle_loop2 (void) ...@@ -1309,6 +1310,9 @@ rest_of_handle_loop2 (void)
if (loops) if (loops)
{ {
/* The optimizations: */ /* The optimizations: */
if (flag_move_loop_invariants)
move_loop_invariants (loops);
if (flag_unswitch_loops) if (flag_unswitch_loops)
unswitch_loops (loops); unswitch_loops (loops);
...@@ -1598,7 +1602,8 @@ rest_of_compilation (void) ...@@ -1598,7 +1602,8 @@ rest_of_compilation (void)
if (flag_tracer) if (flag_tracer)
rest_of_handle_tracer (); rest_of_handle_tracer ();
if (optimize > 0) if (optimize > 0
&& flag_loop_optimize2)
rest_of_handle_loop2 (); rest_of_handle_loop2 ();
if (flag_web) if (flag_web)
......
...@@ -1673,6 +1673,19 @@ process_options (void) ...@@ -1673,6 +1673,19 @@ process_options (void)
if (flag_unroll_loops || flag_peel_loops) if (flag_unroll_loops || flag_peel_loops)
flag_rerun_cse_after_loop = 1; flag_rerun_cse_after_loop = 1;
/* If explicitly asked to run new loop optimizer, switch off the old
one. */
if (flag_loop_optimize2)
flag_loop_optimize = 0;
/* Enable new loop optimizer pass if any of its optimizations is called. */
if (flag_move_loop_invariants
|| flag_unswitch_loops
|| flag_peel_loops
|| flag_unroll_loops
|| flag_branch_on_count_reg)
flag_loop_optimize2 = 1;
if (flag_non_call_exceptions) if (flag_non_call_exceptions)
flag_asynchronous_unwind_tables = 1; flag_asynchronous_unwind_tables = 1;
if (flag_asynchronous_unwind_tables) if (flag_asynchronous_unwind_tables)
......
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