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>
* 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.
2004-06-20 Richard Henderson <rth@redhat.com>
......
......@@ -897,7 +897,7 @@ OBJS-common = \
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 \
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 \
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 \
......@@ -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)
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)
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) \
$(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) \
......
......@@ -411,6 +411,11 @@ simple_loop_desc (struct loop *loop)
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. */
extern struct loops *loop_optimizer_init (FILE *);
extern void loop_optimizer_finalize (struct loops *, FILE *);
......@@ -427,5 +432,6 @@ enum
extern void unroll_and_peel_loops (struct loops *, int);
extern void doloop_optimize_loops (struct loops *);
extern void move_loop_invariants (struct loops *);
#endif /* GCC_CFGLOOP_H */
......@@ -474,3 +474,92 @@ get_loop_level (const struct loop *loop)
}
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
Common Report Var(flag_loop_optimize)
Perform loop optimizations
floop-optimize2
Common Report Var(flag_loop_optimize2)
Perform loop optimizations using the new loop optimizer
fmath-errno
Common Report Var(flag_errno_math) Init(1)
Set errno after built-in math functions
......@@ -475,6 +479,10 @@ fmove-all-movables
Common Report Var(flag_move_all_movables)
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
Common RejectNegative Report Var(flag_mudflap)
Add mudflap bounds-checking instrumentation for single-threaded program.
......
......@@ -290,7 +290,7 @@ in the following sections.
-finline-functions -finline-limit=@var{n} -fkeep-inline-functions @gol
-fkeep-static-consts -fmerge-constants -fmerge-all-constants @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-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
-funsafe-math-optimizations -ffinite-math-only @gol
......@@ -4191,6 +4191,12 @@ well.
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
@opindex crossjumping
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
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
@opindex funswitch-loops
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
@file{loop.h} used for communication between them. Loop unrolling uses
some functions in @file{integrate.c} and the header @file{integrate.h}.
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
optimizations---unrolling, peeling and unswitching loops. The source
......@@ -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
initialization and finalization code, @file{loop-unswitch.c} for loop
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
......
......@@ -35,6 +35,13 @@ loop_optimizer_init (FILE *dumpfile)
{
struct loops *loops = xcalloc (1, sizeof (struct loops));
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
block. */
......
......@@ -1290,7 +1290,8 @@ rest_of_handle_loop2 (void)
struct loops *loops;
basic_block bb;
if (!flag_unswitch_loops
if (!flag_move_loop_invariants
&& !flag_unswitch_loops
&& !flag_peel_loops
&& !flag_unroll_loops
&& !flag_branch_on_count_reg)
......@@ -1309,6 +1310,9 @@ rest_of_handle_loop2 (void)
if (loops)
{
/* The optimizations: */
if (flag_move_loop_invariants)
move_loop_invariants (loops);
if (flag_unswitch_loops)
unswitch_loops (loops);
......@@ -1598,7 +1602,8 @@ rest_of_compilation (void)
if (flag_tracer)
rest_of_handle_tracer ();
if (optimize > 0)
if (optimize > 0
&& flag_loop_optimize2)
rest_of_handle_loop2 ();
if (flag_web)
......
......@@ -1673,6 +1673,19 @@ process_options (void)
if (flag_unroll_loops || flag_peel_loops)
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)
flag_asynchronous_unwind_tables = 1;
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