This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lno] Use new iv analysis in unroller
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 30 Jan 2004 09:31:31 +0100
- Subject: [lno] Use new iv analysis in unroller
Hello,
this patch makes use of the new iv analysis code in unroller and branch
prediction. I have verified that the code is strictly better (i.e.
detects superset of loops as simple) during the c bootstrap on i686.
I leave the old code still in place, since similar verification needs
to be done on other platforms once handling of subregs is added.
Bootstrapped & regtested on i686 with -funroll-loops -floop-optimize2.
Zdenek
Index: ChangeLog.lno
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/ChangeLog.lno,v
retrieving revision 1.1.2.42
diff -c -3 -p -r1.1.2.42 ChangeLog.lno
*** ChangeLog.lno 29 Jan 2004 21:56:48 -0000 1.1.2.42
--- ChangeLog.lno 30 Jan 2004 01:31:20 -0000
***************
*** 1,5 ****
--- 1,44 ----
2004-01-29 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+ * basic-block.h (FOR_BB_INSNS, FOR_BB_INSNS_REVERSE): New macros.
+ * cfgloop.c (num_loop_branches): New function.
+ * cfgloop.h (struct loop_desc): Add field strange.
+ (struct loop): Remove fields simple, desc, has_desc.
+ (num_loop_branches, get_simple_loop_desc, free_simple_loop_desc):
+ Declare.
+ (simple_loop_desc): New inline function.
+ * cfgloopanal.c (count_loop_iterations): Set field strange.
+ (simple_loop_exit_p): Initialize postincr properly.
+ * loop-iv.c (assign_luids, mark_sets, simplify_using_initial_values):
+ Use FOR_BB_INSNS/FOR_BB_INSNS_REVERSE.
+ (iv_number_of_iterations): Restrict the number of iterations to the
+ actual mode.
+ (find_simple_exit): Check results with the old simple loop analyser.
+ (get_simple_loop_desc, free_simple_loop_desc): New functions.
+ * loop-unroll.c (loop_exit_at_end_p): New function.
+ (unroll_and_peel_loops, peel_loops_completely,
+ decide_unrolling_and_peeling, decide_peel_once_rolling,
+ decide_peel_completely, peel_loop_completely,
+ decide_unroll_constant_iterations, unroll_loop_constant_iterations,
+ decide_unroll_runtime_iterations, unroll_loop_runtime_iterations,
+ decide_peel_simple, decide_unroll_stupid): Use new iv analysis.
+ * predict.c (predict_loops): Use new iv analysis.
+
+ * tree-ssa-loop.c (copy_loop_headers): Predict entry edge from
+ copied loop header to be taken.
+
+ * tree-cfg.c (tree_find_edge_insert_loc,
+ bsi_insert_on_edge_immediate): Return the newly created block.
+ (bsi_commit_edge_inserts_1): Add parameter to
+ tree_find_edge_insert_loc call.
+ * tree-flow.h (bsi_insert_on_edge_immediate): Declaration changed.
+ * tree-ssa-loop-ivopts.c (create_new_iv): Update loop for newly
+ created block.
+
+ * cfg.c (unlink_block): Clean prev_bb and next_bb fields.
+
+ 2004-01-29 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
* tree-scalar-evolution.c (scev_analyze_inner_loop_phi): Add ;.
2004-01-29 Sebastian Pop <sebastian.pop@ensmp.fr>
Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/basic-block.h,v
retrieving revision 1.153.2.39.2.3
diff -c -3 -p -r1.153.2.39.2.3 basic-block.h
*** basic-block.h 22 Jan 2004 01:10:45 -0000 1.153.2.39.2.3
--- basic-block.h 30 Jan 2004 01:31:20 -0000
*************** extern varray_type basic_block_info;
*** 331,336 ****
--- 331,347 ----
#define FOR_EACH_BB_REVERSE(BB) \
FOR_BB_BETWEEN (BB, EXIT_BLOCK_PTR->prev_bb, ENTRY_BLOCK_PTR, prev_bb)
+ /* For iterating over insns in basic block. */
+ #define FOR_BB_INSNS(BB, INSN) \
+ for ((INSN) = BB_HEAD (BB); \
+ (INSN) != NEXT_INSN (BB_END (BB)); \
+ (INSN) = NEXT_INSN (INSN))
+
+ #define FOR_BB_INSNS_REVERSE(BB, INSN) \
+ for ((INSN) = BB_END (BB); \
+ (INSN) != PREV_INSN (BB_HEAD (BB)); \
+ (INSN) = PREV_INSN (INSN))
+
/* Cycles through _all_ basic blocks, even the fake ones (entry and
exit block). */
Index: cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfg.c,v
retrieving revision 1.34.2.19.2.2
diff -c -3 -p -r1.34.2.19.2.2 cfg.c
*** cfg.c 21 Jan 2004 09:24:58 -0000 1.34.2.19.2.2
--- cfg.c 30 Jan 2004 01:31:20 -0000
*************** unlink_block (basic_block b)
*** 229,234 ****
--- 229,236 ----
{
b->next_bb->prev_bb = b->prev_bb;
b->prev_bb->next_bb = b->next_bb;
+ b->prev_bb = NULL;
+ b->next_bb = NULL;
}
/* Sequentially order blocks and compact the arrays. */
Index: cfgloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloop.c,v
retrieving revision 1.14.2.12.2.1
diff -c -3 -p -r1.14.2.12.2.1 cfgloop.c
*** cfgloop.c 3 Jan 2004 20:25:25 -0000 1.14.2.12.2.1
--- cfgloop.c 30 Jan 2004 01:31:20 -0000
*************** get_loop_exit_edges (const struct loop *
*** 1061,1066 ****
--- 1061,1087 ----
return edges;
}
+ /* Counts the number of conditional branches inside LOOP. */
+
+ unsigned
+ num_loop_branches (const struct loop *loop)
+ {
+ unsigned i, n;
+ basic_block * body;
+
+ if (loop->latch == EXIT_BLOCK_PTR)
+ abort ();
+
+ body = get_loop_body (loop);
+ n = 0;
+ for (i = 0; i < loop->num_nodes; i++)
+ if (body[i]->succ && body[i]->succ->succ_next)
+ n++;
+ free (body);
+
+ return n;
+ }
+
/* Adds basic block BB to LOOP. */
void
add_bb_to_loop (basic_block bb, struct loop *loop)
Index: cfgloop.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloop.h,v
retrieving revision 1.2.4.9.2.7
diff -c -3 -p -r1.2.4.9.2.7 cfgloop.h
*** cfgloop.h 29 Jan 2004 18:36:31 -0000 1.2.4.9.2.7
--- cfgloop.h 30 Jan 2004 01:31:20 -0000
*************** struct lpt_decision
*** 39,44 ****
--- 39,45 ----
/* Description of loop for simple loop unrolling. */
struct loop_desc
{
+ bool strange;
int postincr; /* 1 if increment/decrement is done after loop exit condition. */
rtx stride; /* Value added to VAR in each iteration. */
rtx var; /* Loop control variable. */
*************** struct loop
*** 77,87 ****
/* For loop unrolling/peeling decision. */
struct lpt_decision lpt_decision;
- /* Simple loop description. */
- int simple;
- struct loop_desc desc;
- int has_desc;
-
/* Number of loop insns. */
unsigned ninsns;
--- 78,83 ----
*************** extern unsigned get_loop_level (const st
*** 289,294 ****
--- 285,291 ----
extern basic_block *get_loop_body (const struct loop *);
extern basic_block *get_loop_body_in_dom_order (const struct loop *);
extern edge *get_loop_exit_edges (const struct loop *, unsigned *);
+ extern unsigned num_loop_branches (const struct loop *);
extern edge loop_preheader_edge (const struct loop *);
extern edge loop_latch_edge (const struct loop *);
*************** extern void find_simple_exit (struct loo
*** 394,399 ****
--- 391,405 ----
extern void iv_number_of_iterations (struct loop *, rtx, rtx,
struct niter_desc *);
extern void iv_analysis_done (void);
+
+ extern struct niter_desc *get_simple_loop_desc (struct loop *loop);
+ extern void free_simple_loop_desc (struct loop *loop);
+
+ static inline struct niter_desc *
+ simple_loop_desc (struct loop *loop)
+ {
+ return loop->aux;
+ }
/* Loop optimizer initialization. */
extern struct loops *loop_optimizer_init (FILE *);
Index: cfgloopanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloopanal.c,v
retrieving revision 1.2.4.9.2.4
diff -c -3 -p -r1.2.4.9.2.4 cfgloopanal.c
*** cfgloopanal.c 28 Jan 2004 21:07:33 -0000 1.2.4.9.2.4
--- cfgloopanal.c 30 Jan 2004 01:31:21 -0000
*************** count_loop_iterations (struct loop_desc
*** 724,729 ****
--- 724,731 ----
if (!INTEGRAL_MODE_P (mode))
return NULL;
+ desc->strange = false;
+
init = copy_rtx (init ? init : desc->var);
lim = copy_rtx (lim ? lim : desc->lim);
*************** count_loop_iterations (struct loop_desc
*** 813,828 ****
/* Handle strange tests specially. */
if (cond == EQ || cond == GE || cond == GT || cond == GEU
|| cond == GTU)
! return count_strange_loop_iterations (init, lim, cond, desc->postincr,
! stride, mode, desc->inner_mode);
exp = simplify_gen_binary (MINUS, mode, lim, init);
}
else
{
if (cond == EQ || cond == LE || cond == LT || cond == LEU
|| cond == LTU)
! return count_strange_loop_iterations (init, lim, cond, desc->postincr,
! stride, mode, desc->inner_mode);
exp = simplify_gen_binary (MINUS, mode, init, lim);
stride = simplify_gen_unary (NEG, mode, stride, mode);
}
--- 815,836 ----
/* Handle strange tests specially. */
if (cond == EQ || cond == GE || cond == GT || cond == GEU
|| cond == GTU)
! {
! desc->strange = true;
! return count_strange_loop_iterations (init, lim, cond, desc->postincr,
! stride, mode, desc->inner_mode);
! }
exp = simplify_gen_binary (MINUS, mode, lim, init);
}
else
{
if (cond == EQ || cond == LE || cond == LT || cond == LEU
|| cond == LTU)
! {
! desc->strange = true;
! return count_strange_loop_iterations (init, lim, cond, desc->postincr,
! stride, mode, desc->inner_mode);
! }
exp = simplify_gen_binary (MINUS, mode, init, lim);
stride = simplify_gen_unary (NEG, mode, stride, mode);
}
*************** simple_loop_exit_p (struct loop *loop, e
*** 967,973 ****
{
basic_block mod_bb, exit_bb;
int fallthru_out;
! rtx condition;
edge ei, e;
exit_bb = exit_edge->src;
--- 975,981 ----
{
basic_block mod_bb, exit_bb;
int fallthru_out;
! rtx condition, at, insn;
edge ei, e;
exit_bb = exit_edge->src;
*************** simple_loop_exit_p (struct loop *loop, e
*** 994,1000 ****
/* Condition must be a simple comparison in that one of operands
is register and the other one is invariant. */
! if (!(condition = get_condition (BB_END (exit_bb), NULL, false)))
return false;
if (!simple_condition_p (loop, condition, invariant_regs, desc))
--- 1002,1008 ----
/* Condition must be a simple comparison in that one of operands
is register and the other one is invariant. */
! if (!(condition = get_condition (BB_END (exit_bb), &at, false)))
return false;
if (!simple_condition_p (loop, condition, invariant_regs, desc))
*************** simple_loop_exit_p (struct loop *loop, e
*** 1006,1012 ****
return false;
/* OK, it is simple loop. Now just fill in remaining info. */
! desc->postincr = !dominated_by_p (CDI_DOMINATORS, exit_bb, mod_bb);
desc->neg = !fallthru_out;
/* Find initial value of var and alternative values for lim. */
--- 1014,1037 ----
return false;
/* OK, it is simple loop. Now just fill in remaining info. */
! if (exit_bb == mod_bb)
! {
! /* It might be that we are incremented in the middle of the
! condition. */
!
! insn = single_set_regs[REGNO (desc->var)];
! desc->postincr = true;
! for (; insn != NEXT_INSN (BB_END (mod_bb)); insn = NEXT_INSN (insn))
! if (insn == at)
! {
! desc->postincr = false;
! break;
! }
! }
! else
! {
! desc->postincr = !dominated_by_p (CDI_DOMINATORS, exit_bb, mod_bb);
! }
desc->neg = !fallthru_out;
/* Find initial value of var and alternative values for lim. */
Index: loop-iv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/loop-iv.c,v
retrieving revision 1.1.4.2
diff -c -3 -p -r1.1.4.2 loop-iv.c
*** loop-iv.c 29 Jan 2004 16:03:42 -0000 1.1.4.2
--- loop-iv.c 30 Jan 2004 01:31:21 -0000
*************** dump_iv_info (FILE *file, struct rtx_iv
*** 122,136 ****
static void
assign_luids (basic_block bb)
{
! unsigned i, uid;
rtx insn;
! for (i = 0, insn = BB_HEAD (bb);
! insn != NEXT_INSN (BB_END (bb));
! insn = NEXT_INSN (insn), i++)
{
uid = INSN_UID (insn);
! insn_info[uid].luid = i;
insn_info[uid].prev_def = NULL_RTX;
insn_info[uid].iv.analysed = false;
}
--- 122,134 ----
static void
assign_luids (basic_block bb)
{
! unsigned i = 0, uid;
rtx insn;
! FOR_BB_INSNS (bb, insn)
{
uid = INSN_UID (insn);
! insn_info[uid].luid = i++;
insn_info[uid].prev_def = NULL_RTX;
insn_info[uid].iv.analysed = false;
}
*************** mark_sets (basic_block bb, bool dom)
*** 254,262 ****
{
rtx insn, set, def;
! for (insn = BB_HEAD (bb);
! insn != NEXT_INSN (BB_END (bb));
! insn = NEXT_INSN (insn))
{
if (!INSN_P (insn))
continue;
--- 252,258 ----
{
rtx insn, set, def;
! FOR_BB_INSNS (bb, insn)
{
if (!INSN_P (insn))
continue;
*************** simplify_using_initial_values (struct lo
*** 1210,1216 ****
}
}
! for (; insn != PREV_INSN (BB_HEAD (e->src)); insn = PREV_INSN (insn))
{
if (!INSN_P (insn))
continue;
--- 1206,1212 ----
}
}
! FOR_BB_INSNS_REVERSE (e->src, insn)
{
if (!INSN_P (insn))
continue;
*************** iv_number_of_iterations (struct loop *lo
*** 1619,1626 ****
if (GET_CODE (desc->niter_expr) == CONST_INT)
{
desc->const_iter = true;
! desc->niter_max = desc->niter = INTVAL (desc->niter_expr);
}
else if (!desc->niter_max)
desc->niter_max = determine_max_iter (desc);
--- 1615,1624 ----
if (GET_CODE (desc->niter_expr) == CONST_INT)
{
+ unsigned HOST_WIDEST_INT val = INTVAL (desc->niter_expr);
+
desc->const_iter = true;
! desc->niter_max = desc->niter = val & GET_MODE_MASK (desc->mode);
}
else if (!desc->niter_max)
desc->niter_max = determine_max_iter (desc);
*************** find_simple_exit (struct loop *loop, str
*** 1723,1728 ****
--- 1721,1747 ----
}
}
+ #if 0
+ {
+ /* Check that we do not lose wrto older version. */
+ struct loop_desc odesc;
+ if (simple_loop_p (loop, &odesc) && !odesc.strange)
+ {
+ if (!desc->simple_p)
+ abort ();
+
+ if (odesc.const_iter)
+ {
+ if (!desc->const_iter)
+ abort ();
+
+ if (desc->niter != odesc.niter)
+ abort ();
+ }
+ }
+ }
+ #endif
+
if (rtl_dump_file)
{
if (desc->simple_p)
*************** find_simple_exit (struct loop *loop, str
*** 1763,1766 ****
--- 1782,1818 ----
}
free (body);
+ }
+
+ /* Creates a simple loop description of LOOP if it was not computed
+ already. */
+
+ struct niter_desc *
+ get_simple_loop_desc (struct loop *loop)
+ {
+ struct niter_desc *desc = simple_loop_desc (loop);
+
+ if (desc)
+ return desc;
+
+ desc = xmalloc (sizeof (struct niter_desc));
+ iv_analysis_loop_init (loop);
+ find_simple_exit (loop, desc);
+ loop->aux = desc;
+
+ return desc;
+ }
+
+ /* Releases simple loop description for LOOP. */
+
+ void
+ free_simple_loop_desc (struct loop *loop)
+ {
+ struct niter_desc *desc = simple_loop_desc (loop);
+
+ if (!desc)
+ return;
+
+ free (desc);
+ loop->aux = NULL;
}
Index: loop-unroll.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop-unroll.c,v
retrieving revision 1.2.2.6.2.1
diff -c -3 -p -r1.2.2.6.2.1 loop-unroll.c
*** loop-unroll.c 29 Jan 2004 16:03:42 -0000 1.2.2.6.2.1
--- loop-unroll.c 30 Jan 2004 01:31:21 -0000
*************** void
*** 85,91 ****
unroll_and_peel_loops (struct loops *loops, int flags)
{
struct loop *loop, *next;
! int check;
/* First perform complete loop peeling (it is almost surely a win,
and affects parameters for further decision a lot). */
--- 85,92 ----
unroll_and_peel_loops (struct loops *loops, int flags)
{
struct loop *loop, *next;
! bool check;
! unsigned i;
/* First perform complete loop peeling (it is almost surely a win,
and affects parameters for further decision a lot). */
*************** unroll_and_peel_loops (struct loops *loo
*** 110,116 ****
else
next = loop->outer;
! check = 1;
/* And perform the appropriate transformations. */
switch (loop->lpt_decision.decision)
{
--- 111,117 ----
else
next = loop->outer;
! check = true;
/* And perform the appropriate transformations. */
switch (loop->lpt_decision.decision)
{
*************** unroll_and_peel_loops (struct loops *loo
*** 130,136 ****
unroll_loop_stupid (loops, loop);
break;
case LPT_NONE:
! check = 0;
break;
default:
abort ();
--- 131,137 ----
unroll_loop_stupid (loops, loop);
break;
case LPT_NONE:
! check = false;
break;
default:
abort ();
*************** unroll_and_peel_loops (struct loops *loo
*** 144,149 ****
--- 145,177 ----
}
loop = next;
}
+
+ for (i = 1; i < loops->num; i++)
+ if (loops->parray[i])
+ free_simple_loop_desc (loops->parray[i]);
+
+ iv_analysis_done ();
+ }
+
+ /* Check whether exit of the LOOP is at the end of loop body. */
+
+ static bool
+ loop_exit_at_end_p (struct loop *loop)
+ {
+ struct niter_desc *desc = simple_loop_desc (loop);
+ rtx insn;
+
+ if (desc->in_edge->dest != loop->latch)
+ return false;
+
+ /* Check that the latch is empty. */
+ FOR_BB_INSNS (loop->latch, insn)
+ {
+ if (INSN_P (insn))
+ return false;
+ }
+
+ return true;
}
/* Check whether to peel LOOPS (depending on FLAGS) completely and do so. */
*************** peel_loops_completely (struct loops *loo
*** 168,177 ****
next = loop->outer;
loop->lpt_decision.decision = LPT_NONE;
- loop->has_desc = 0;
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Considering loop %d for complete peeling\n",
loop->num);
loop->ninsns = num_loop_insns (loop);
--- 196,204 ----
next = loop->outer;
loop->lpt_decision.decision = LPT_NONE;
if (rtl_dump_file)
! fprintf (rtl_dump_file, "\n;; *** Considering loop %d for complete peeling ***\n",
loop->num);
loop->ninsns = num_loop_insns (loop);
*************** decide_unrolling_and_peeling (struct loo
*** 216,222 ****
loop->lpt_decision.decision = LPT_NONE;
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Considering loop %d\n", loop->num);
/* Do not peel cold areas. */
if (!maybe_hot_bb_p (loop->header))
--- 243,249 ----
loop->lpt_decision.decision = LPT_NONE;
if (rtl_dump_file)
! fprintf (rtl_dump_file, "\n;; *** Considering loop %d ***\n", loop->num);
/* Do not peel cold areas. */
if (!maybe_hot_bb_p (loop->header))
*************** decide_unrolling_and_peeling (struct loo
*** 269,276 ****
static void
decide_peel_once_rolling (struct loop *loop, int flags ATTRIBUTE_UNUSED)
{
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Considering peeling once rolling loop\n");
/* Is the loop small enough? */
if ((unsigned) PARAM_VALUE (PARAM_MAX_ONCE_PEELED_INSNS) < loop->ninsns)
--- 296,305 ----
static void
decide_peel_once_rolling (struct loop *loop, int flags ATTRIBUTE_UNUSED)
{
+ struct niter_desc *desc;
+
if (rtl_dump_file)
! fprintf (rtl_dump_file, "\n;; Considering peeling once rolling loop\n");
/* Is the loop small enough? */
if ((unsigned) PARAM_VALUE (PARAM_MAX_ONCE_PEELED_INSNS) < loop->ninsns)
*************** decide_peel_once_rolling (struct loop *l
*** 281,291 ****
}
/* Check for simple loops. */
! loop->simple = simple_loop_p (loop, &loop->desc);
! loop->has_desc = 1;
/* Check number of iterations. */
! if (!loop->simple || !loop->desc.const_iter || loop->desc.niter != 0)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Unable to prove that the loop rolls exactly once\n");
--- 310,321 ----
}
/* Check for simple loops. */
! desc = get_simple_loop_desc (loop);
/* Check number of iterations. */
! if (!desc->simple_p
! || !desc->const_iter
! || desc->niter != 0)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Unable to prove that the loop rolls exactly once\n");
*************** static void
*** 303,311 ****
decide_peel_completely (struct loop *loop, int flags ATTRIBUTE_UNUSED)
{
unsigned npeel;
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Considering peeling completely\n");
/* Skip non-innermost loops. */
if (loop->inner)
--- 333,342 ----
decide_peel_completely (struct loop *loop, int flags ATTRIBUTE_UNUSED)
{
unsigned npeel;
+ struct niter_desc *desc;
if (rtl_dump_file)
! fprintf (rtl_dump_file, "\n;; Considering peeling completely\n");
/* Skip non-innermost loops. */
if (loop->inner)
*************** decide_peel_completely (struct loop *loo
*** 346,371 ****
}
/* Check for simple loops. */
! if (!loop->has_desc)
! {
! loop->simple = simple_loop_p (loop, &loop->desc);
! loop->has_desc = 1;
! }
/* Check number of iterations. */
! if (!loop->simple || !loop->desc.const_iter)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Unable to prove that the loop iterates constant times\n");
return;
}
! if (loop->desc.niter > npeel - 1)
{
if (rtl_dump_file)
{
fprintf (rtl_dump_file, ";; Not peeling loop completely, rolls too much (");
! fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC,(HOST_WIDEST_INT) loop->desc.niter);
fprintf (rtl_dump_file, " iterations > %d [maximum peelings])\n", npeel);
}
return;
--- 377,399 ----
}
/* Check for simple loops. */
! desc = get_simple_loop_desc (loop);
/* Check number of iterations. */
! if (!desc->simple_p
! || !desc->const_iter)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Unable to prove that the loop iterates constant times\n");
return;
}
! if (desc->niter > npeel - 1)
{
if (rtl_dump_file)
{
fprintf (rtl_dump_file, ";; Not peeling loop completely, rolls too much (");
! fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC, desc->niter);
fprintf (rtl_dump_file, " iterations > %d [maximum peelings])\n", npeel);
}
return;
*************** peel_loop_completely (struct loops *loop
*** 397,404 ****
sbitmap wont_exit;
unsigned HOST_WIDE_INT npeel;
unsigned n_remove_edges, i;
! edge *remove_edges;
! struct loop_desc *desc = &loop->desc;
npeel = desc->niter;
--- 425,432 ----
sbitmap wont_exit;
unsigned HOST_WIDE_INT npeel;
unsigned n_remove_edges, i;
! edge *remove_edges, ei;
! struct niter_desc *desc = simple_loop_desc (loop);
npeel = desc->niter;
*************** peel_loop_completely (struct loops *loop
*** 407,413 ****
wont_exit = sbitmap_alloc (npeel + 1);
sbitmap_ones (wont_exit);
RESET_BIT (wont_exit, 0);
! if (desc->may_be_zero)
RESET_BIT (wont_exit, 1);
remove_edges = xcalloc (npeel, sizeof (edge));
--- 435,441 ----
wont_exit = sbitmap_alloc (npeel + 1);
sbitmap_ones (wont_exit);
RESET_BIT (wont_exit, 0);
! if (desc->noloop_assumptions)
RESET_BIT (wont_exit, 1);
remove_edges = xcalloc (npeel, sizeof (edge));
*************** peel_loop_completely (struct loops *loop
*** 427,445 ****
free (remove_edges);
}
/* Now remove the unreachable part of the last iteration and cancel
the loop. */
! remove_path (loops, desc->in_edge);
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Peeled loop completely, %d times\n", (int) npeel);
}
/* Decide whether to unroll LOOP iterating constant number of times and how much. */
static void
decide_unroll_constant_iterations (struct loop *loop, int flags)
{
! unsigned nunroll, nunroll_by_av, best_copies, best_unroll = -1, n_copies, i;
if (!(flags & UAP_UNROLL))
{
--- 455,478 ----
free (remove_edges);
}
+ ei = desc->in_edge;
+ free_simple_loop_desc (loop);
+
/* Now remove the unreachable part of the last iteration and cancel
the loop. */
! remove_path (loops, ei);
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Peeled loop completely, %d times\n", (int) npeel);
}
/* Decide whether to unroll LOOP iterating constant number of times and how much. */
+
static void
decide_unroll_constant_iterations (struct loop *loop, int flags)
{
! unsigned nunroll, nunroll_by_av, best_copies, best_unroll = 0, n_copies, i;
! struct niter_desc *desc;
if (!(flags & UAP_UNROLL))
{
*************** decide_unroll_constant_iterations (struc
*** 448,454 ****
}
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Considering unrolling loop with constant number of iterations\n");
/* nunroll = total number of copies of the original loop body in
unrolled loop (i.e. if it is 2, we have to duplicate loop body once. */
--- 481,488 ----
}
if (rtl_dump_file)
! fprintf (rtl_dump_file,
! "\n;; Considering unrolling loop with constant number of iterations\n");
/* nunroll = total number of copies of the original loop body in
unrolled loop (i.e. if it is 2, we have to duplicate loop body once. */
*************** decide_unroll_constant_iterations (struc
*** 468,481 ****
}
/* Check for simple loops. */
! if (!loop->has_desc)
! {
! loop->simple = simple_loop_p (loop, &loop->desc);
! loop->has_desc = 1;
! }
/* Check number of iterations. */
! if (!loop->simple || !loop->desc.const_iter)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Unable to prove that the loop iterates constant times\n");
--- 502,511 ----
}
/* Check for simple loops. */
! desc = get_simple_loop_desc (loop);
/* Check number of iterations. */
! if (!desc->simple_p || !desc->const_iter)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Unable to prove that the loop iterates constant times\n");
*************** decide_unroll_constant_iterations (struc
*** 483,489 ****
}
/* Check whether the loop rolls enough to consider. */
! if (loop->desc.niter < 2 * nunroll)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not unrolling loop, doesn't roll\n");
--- 513,519 ----
}
/* Check whether the loop rolls enough to consider. */
! if (desc->niter < 2 * nunroll)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not unrolling loop, doesn't roll\n");
*************** decide_unroll_constant_iterations (struc
*** 497,512 ****
best_copies = 2 * nunroll + 10;
i = 2 * nunroll + 2;
! if ((unsigned) i - 1 >= loop->desc.niter)
! i = loop->desc.niter - 2;
for (; i >= nunroll - 1; i--)
{
! unsigned exit_mod = loop->desc.niter % (i + 1);
! if (loop->desc.postincr)
n_copies = exit_mod + i + 1;
! else if (exit_mod != (unsigned) i || loop->desc.may_be_zero)
n_copies = exit_mod + i + 2;
else
n_copies = i + 1;
--- 527,543 ----
best_copies = 2 * nunroll + 10;
i = 2 * nunroll + 2;
! if (i - 1 >= desc->niter)
! i = desc->niter - 2;
for (; i >= nunroll - 1; i--)
{
! unsigned exit_mod = desc->niter % (i + 1);
! if (!loop_exit_at_end_p (loop))
n_copies = exit_mod + i + 1;
! else if (exit_mod != (unsigned) i
! || desc->noloop_assumptions != NULL_RTX)
n_copies = exit_mod + i + 2;
else
n_copies = i + 1;
*************** decide_unroll_constant_iterations (struc
*** 524,529 ****
--- 555,565 ----
loop->lpt_decision.decision = LPT_UNROLL_CONSTANT;
loop->lpt_decision.times = best_unroll;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ ";; Decided to unroll the constant times rolling loop, %d times.\n",
+ loop->lpt_decision.times);
}
/* Unroll LOOP with constant number of iterations LOOP->LPT_DECISION.TIMES + 1
*************** unroll_loop_constant_iterations (struct
*** 554,564 ****
unsigned n_remove_edges, i;
edge *remove_edges;
unsigned max_unroll = loop->lpt_decision.times;
! struct loop_desc *desc = &loop->desc;
niter = desc->niter;
! if (niter <= (unsigned) max_unroll + 1)
abort (); /* Should not get here (such loop should be peeled instead). */
exit_mod = niter % (max_unroll + 1);
--- 590,600 ----
unsigned n_remove_edges, i;
edge *remove_edges;
unsigned max_unroll = loop->lpt_decision.times;
! struct niter_desc *desc = simple_loop_desc (loop);
niter = desc->niter;
! if (niter <= max_unroll + 1)
abort (); /* Should not get here (such loop should be peeled instead). */
exit_mod = niter % (max_unroll + 1);
*************** unroll_loop_constant_iterations (struct
*** 569,577 ****
remove_edges = xcalloc (max_unroll + exit_mod + 1, sizeof (edge));
n_remove_edges = 0;
! if (desc->postincr)
{
! /* Counter is incremented after the exit test; leave exit test
in the first copy, so that the loops that start with test
of exit condition have continuous body after unrolling. */
--- 605,613 ----
remove_edges = xcalloc (max_unroll + exit_mod + 1, sizeof (edge));
n_remove_edges = 0;
! if (!loop_exit_at_end_p (loop))
{
! /* The exit is not at the end of the loop; leave exit test
in the first copy, so that the loops that start with test
of exit condition have continuous body after unrolling. */
*************** unroll_loop_constant_iterations (struct
*** 580,586 ****
/* Peel exit_mod iterations. */
RESET_BIT (wont_exit, 0);
! if (desc->may_be_zero)
RESET_BIT (wont_exit, 1);
if (exit_mod
--- 616,622 ----
/* Peel exit_mod iterations. */
RESET_BIT (wont_exit, 0);
! if (desc->noloop_assumptions)
RESET_BIT (wont_exit, 1);
if (exit_mod
*************** unroll_loop_constant_iterations (struct
*** 602,613 ****
/* We know that niter >= max_unroll + 2; so we do not need to care of
case when we would exit before reaching the loop. So just peel
! exit_mod + 1 iterations.
! */
! if (exit_mod != (unsigned) max_unroll || desc->may_be_zero)
{
RESET_BIT (wont_exit, 0);
! if (desc->may_be_zero)
RESET_BIT (wont_exit, 1);
if (!duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
--- 638,649 ----
/* We know that niter >= max_unroll + 2; so we do not need to care of
case when we would exit before reaching the loop. So just peel
! exit_mod + 1 iterations. */
! if (exit_mod != max_unroll
! || desc->noloop_assumptions)
{
RESET_BIT (wont_exit, 0);
! if (desc->noloop_assumptions)
RESET_BIT (wont_exit, 1);
if (!duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
*************** static void
*** 647,652 ****
--- 683,689 ----
decide_unroll_runtime_iterations (struct loop *loop, int flags)
{
unsigned nunroll, nunroll_by_av, i;
+ struct niter_desc *desc;
if (!(flags & UAP_UNROLL))
{
*************** decide_unroll_runtime_iterations (struct
*** 655,661 ****
}
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Considering unrolling loop with runtime computable number of iterations\n");
/* nunroll = total number of copies of the original loop body in
unrolled loop (i.e. if it is 2, we have to duplicate loop body once. */
--- 692,699 ----
}
if (rtl_dump_file)
! fprintf (rtl_dump_file,
! "\n;; Considering unrolling loop with runtime computable number of iterations\n");
/* nunroll = total number of copies of the original loop body in
unrolled loop (i.e. if it is 2, we have to duplicate loop body once. */
*************** decide_unroll_runtime_iterations (struct
*** 675,695 ****
}
/* Check for simple loops. */
! if (!loop->has_desc)
! {
! loop->simple = simple_loop_p (loop, &loop->desc);
! loop->has_desc = 1;
! }
/* Check simpleness. */
! if (!loop->simple)
{
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Unable to prove that the number of iterations can be counted in runtime\n");
return;
}
! if (loop->desc.const_iter)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Loop iterates constant times\n");
--- 713,730 ----
}
/* Check for simple loops. */
! desc = get_simple_loop_desc (loop);
/* Check simpleness. */
! if (!desc->simple_p)
{
if (rtl_dump_file)
! fprintf (rtl_dump_file,
! ";; Unable to prove that the number of iterations can be counted in runtime\n");
return;
}
! if (desc->const_iter)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Loop iterates constant times\n");
*************** decide_unroll_runtime_iterations (struct
*** 706,715 ****
/* Success; now force nunroll to be power of 2, as we are unable to
cope with overflows in computation of number of iterations. */
! for (i = 1; 2 * i <= nunroll; i *= 2);
loop->lpt_decision.decision = LPT_UNROLL_RUNTIME;
loop->lpt_decision.times = i - 1;
}
/* Unroll LOOP for that we are able to count number of iterations in runtime
--- 741,756 ----
/* Success; now force nunroll to be power of 2, as we are unable to
cope with overflows in computation of number of iterations. */
! for (i = 1; 2 * i <= nunroll; i *= 2)
! continue;
loop->lpt_decision.decision = LPT_UNROLL_RUNTIME;
loop->lpt_decision.times = i - 1;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ ";; Decided to unroll the runtime computable times rolling loop, %d times.\n",
+ loop->lpt_decision.times);
}
/* Unroll LOOP for that we are able to count number of iterations in runtime
*************** unroll_loop_runtime_iterations (struct l
*** 756,762 ****
edge *remove_edges, e;
bool extra_zero_check, last_may_exit;
unsigned max_unroll = loop->lpt_decision.times;
! struct loop_desc *desc = &loop->desc;
/* Remember blocks whose dominators will have to be updated. */
dom_bbs = xcalloc (n_basic_blocks, sizeof (basic_block));
--- 797,803 ----
edge *remove_edges, e;
bool extra_zero_check, last_may_exit;
unsigned max_unroll = loop->lpt_decision.times;
! struct niter_desc *desc = simple_loop_desc (loop);
/* Remember blocks whose dominators will have to be updated. */
dom_bbs = xcalloc (n_basic_blocks, sizeof (basic_block));
*************** unroll_loop_runtime_iterations (struct l
*** 777,783 ****
}
free (body);
! if (desc->postincr)
{
/* Leave exit in first copy (for explanation why see comment in
unroll_loop_constant_iterations). */
--- 818,824 ----
}
free (body);
! if (!loop_exit_at_end_p (loop))
{
/* Leave exit in first copy (for explanation why see comment in
unroll_loop_constant_iterations). */
*************** unroll_loop_runtime_iterations (struct l
*** 798,804 ****
/* Get expression for number of iterations. */
start_sequence ();
! niter = count_loop_iterations (desc, NULL, NULL);
if (!niter)
abort ();
niter = force_operand (niter, NULL);
--- 839,845 ----
/* Get expression for number of iterations. */
start_sequence ();
! niter = copy_rtx (desc->niter_expr);
if (!niter)
abort ();
niter = force_operand (niter, NULL);
*************** unroll_loop_runtime_iterations (struct l
*** 806,812 ****
/* Count modulo by ANDing it with max_unroll; we use the fact that
the number of unrollings is a power of two, and thus this is correct
even if there is overflow in the computation. */
! niter = expand_simple_binop (GET_MODE (desc->var), AND,
niter,
GEN_INT (max_unroll),
NULL_RTX, 0, OPTAB_LIB_WIDEN);
--- 847,853 ----
/* Count modulo by ANDing it with max_unroll; we use the fact that
the number of unrollings is a power of two, and thus this is correct
even if there is overflow in the computation. */
! niter = expand_simple_binop (desc->mode, AND,
niter,
GEN_INT (max_unroll),
NULL_RTX, 0, OPTAB_LIB_WIDEN);
*************** unroll_loop_runtime_iterations (struct l
*** 824,833 ****
/* Peel the first copy of loop body (almost always we must leave exit test
here; the only exception is when we have extra zero check and the number
! of iterations is reliable (i.e. comes out of NE condition). Also record
! the place of (possible) extra zero check. */
sbitmap_zero (wont_exit);
! if (extra_zero_check && desc->cond == NE)
SET_BIT (wont_exit, 1);
ezc_swtch = loop_preheader_edge (loop)->src;
if (!duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
--- 865,875 ----
/* Peel the first copy of loop body (almost always we must leave exit test
here; the only exception is when we have extra zero check and the number
! of iterations is reliable. Also record the place of (possible) extra
! zero check. */
sbitmap_zero (wont_exit);
! if (extra_zero_check
! && !desc->noloop_assumptions)
SET_BIT (wont_exit, 1);
ezc_swtch = loop_preheader_edge (loop)->src;
if (!duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
*************** static void
*** 917,922 ****
--- 959,965 ----
decide_peel_simple (struct loop *loop, int flags)
{
unsigned npeel;
+ struct niter_desc *desc;
if (!(flags & UAP_PEEL))
{
*************** decide_peel_simple (struct loop *loop, i
*** 925,931 ****
}
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Considering simply peeling loop\n");
/* npeel = number of iterations to peel. */
npeel = PARAM_VALUE (PARAM_MAX_PEELED_INSNS) / loop->ninsns;
--- 968,974 ----
}
if (rtl_dump_file)
! fprintf (rtl_dump_file, "\n;; Considering simply peeling loop\n");
/* npeel = number of iterations to peel. */
npeel = PARAM_VALUE (PARAM_MAX_PEELED_INSNS) / loop->ninsns;
*************** decide_peel_simple (struct loop *loop, i
*** 941,954 ****
}
/* Check for simple loops. */
! if (!loop->has_desc)
! {
! loop->simple = simple_loop_p (loop, &loop->desc);
! loop->has_desc = 1;
! }
/* Check number of iterations. */
! if (loop->simple && loop->desc.const_iter)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Loop iterates constant times\n");
--- 984,993 ----
}
/* Check for simple loops. */
! desc = get_simple_loop_desc (loop);
/* Check number of iterations. */
! if (desc->simple_p && desc->const_iter)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Loop iterates constant times\n");
*************** decide_peel_simple (struct loop *loop, i
*** 957,963 ****
/* Do not simply peel loops with branches inside -- it increases number
of mispredicts. */
! if (loop->desc.n_branches > 1)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not peeling, contains branches\n");
--- 996,1002 ----
/* Do not simply peel loops with branches inside -- it increases number
of mispredicts. */
! if (num_loop_branches (loop) > 1)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not peeling, contains branches\n");
*************** decide_peel_simple (struct loop *loop, i
*** 992,997 ****
--- 1031,1040 ----
/* Success. */
loop->lpt_decision.decision = LPT_PEEL_SIMPLE;
loop->lpt_decision.times = npeel;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file, ";; Decided to simply peel the loop, %d times.\n",
+ loop->lpt_decision.times);
}
/* Peel a LOOP LOOP->LPT_DECISION.TIMES times. The transformation:
*************** static void
*** 1033,1038 ****
--- 1076,1082 ----
decide_unroll_stupid (struct loop *loop, int flags)
{
unsigned nunroll, nunroll_by_av, i;
+ struct niter_desc *desc;
if (!(flags & UAP_UNROLL_ALL))
{
*************** decide_unroll_stupid (struct loop *loop,
*** 1041,1047 ****
}
if (rtl_dump_file)
! fprintf (rtl_dump_file, ";; Considering unrolling loop stupidly\n");
/* nunroll = total number of copies of the original loop body in
unrolled loop (i.e. if it is 2, we have to duplicate loop body once. */
--- 1085,1091 ----
}
if (rtl_dump_file)
! fprintf (rtl_dump_file, "\n;; Considering unrolling loop stupidly\n");
/* nunroll = total number of copies of the original loop body in
unrolled loop (i.e. if it is 2, we have to duplicate loop body once. */
*************** decide_unroll_stupid (struct loop *loop,
*** 1061,1074 ****
}
/* Check for simple loops. */
! if (!loop->has_desc)
! {
! loop->simple = simple_loop_p (loop, &loop->desc);
! loop->has_desc = 1;
! }
/* Check simpleness. */
! if (loop->simple)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; The loop is simple\n");
--- 1105,1114 ----
}
/* Check for simple loops. */
! desc = get_simple_loop_desc (loop);
/* Check simpleness. */
! if (desc->simple_p)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; The loop is simple\n");
*************** decide_unroll_stupid (struct loop *loop,
*** 1077,1083 ****
/* Do not unroll loops with branches inside -- it increases number
of mispredicts. */
! if (loop->desc.n_branches > 1)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not unrolling, contains branches\n");
--- 1117,1123 ----
/* Do not unroll loops with branches inside -- it increases number
of mispredicts. */
! if (num_loop_branches (loop) > 1)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not unrolling, contains branches\n");
*************** decide_unroll_stupid (struct loop *loop,
*** 1085,1091 ****
}
/* If we have profile feedback, check whether the loop rolls. */
! if (loop->header->count && expected_loop_iterations (loop) < 2 * nunroll)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not unrolling loop, doesn't roll\n");
--- 1125,1132 ----
}
/* If we have profile feedback, check whether the loop rolls. */
! if (loop->header->count
! && expected_loop_iterations (loop) < 2 * nunroll)
{
if (rtl_dump_file)
fprintf (rtl_dump_file, ";; Not unrolling loop, doesn't roll\n");
*************** decide_unroll_stupid (struct loop *loop,
*** 1095,1104 ****
/* Success. Now force nunroll to be power of 2, as it seems that this
improves results (partially because of better alignments, partially
because of some dark magic). */
! for (i = 1; 2 * i <= nunroll; i *= 2);
loop->lpt_decision.decision = LPT_UNROLL_STUPID;
loop->lpt_decision.times = i - 1;
}
/* Unroll a LOOP LOOP->LPT_DECISION.TIMES times. The transformation:
--- 1136,1151 ----
/* Success. Now force nunroll to be power of 2, as it seems that this
improves results (partially because of better alignments, partially
because of some dark magic). */
! for (i = 1; 2 * i <= nunroll; i *= 2)
! continue;
loop->lpt_decision.decision = LPT_UNROLL_STUPID;
loop->lpt_decision.times = i - 1;
+
+ if (rtl_dump_file)
+ fprintf (rtl_dump_file,
+ ";; Decided to unroll the loop stupidly, %d times.\n",
+ loop->lpt_decision.times);
}
/* Unroll a LOOP LOOP->LPT_DECISION.TIMES times. The transformation:
Index: predict.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/predict.c,v
retrieving revision 1.71.2.14.2.1
diff -c -3 -p -r1.71.2.14.2.1 predict.c
*** predict.c 21 Jan 2004 01:10:38 -0000 1.71.2.14.2.1
--- predict.c 30 Jan 2004 01:31:21 -0000
*************** predict_loops (struct loops *loops_info,
*** 540,546 ****
unsigned j;
int exits;
struct loop *loop = loops_info->parray[i];
! struct loop_desc desc;
unsigned HOST_WIDE_INT niter;
flow_loop_scan (loop, LOOP_EXIT_EDGES);
--- 540,546 ----
unsigned j;
int exits;
struct loop *loop = loops_info->parray[i];
! struct niter_desc desc;
unsigned HOST_WIDE_INT niter;
flow_loop_scan (loop, LOOP_EXIT_EDGES);
*************** predict_loops (struct loops *loops_info,
*** 548,554 ****
if (simpleloops)
{
! if (simple_loop_p (loop, &desc) && desc.const_iter)
{
int prob;
niter = desc.niter + 1;
--- 548,557 ----
if (simpleloops)
{
! iv_analysis_loop_init (loop);
! find_simple_exit (loop, &desc);
!
! if (desc.simple_p && desc.const_iter)
{
int prob;
niter = desc.niter + 1;
*************** predict_loops (struct loops *loops_info,
*** 606,611 ****
--- 609,617 ----
/ exits);
}
}
+
+ if (simpleloops)
+ iv_analysis_done ();
}
/* Statically estimate the probability that a branch will be taken and produce
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.244.2.5
diff -c -3 -p -r1.1.4.244.2.5 tree-cfg.c
*** tree-cfg.c 25 Jan 2004 20:20:15 -0000 1.1.4.244.2.5
--- tree-cfg.c 30 Jan 2004 01:31:21 -0000
*************** bsi_replace (const block_stmt_iterator *
*** 2571,2580 ****
In all cases, the returned *BSI points to the correct location. The
return value is true if insertion should be done after the location,
! or false if before the location. */
static bool
! tree_find_edge_insert_loc (edge e, block_stmt_iterator *bsi)
{
basic_block dest, src;
tree tmp;
--- 2571,2582 ----
In all cases, the returned *BSI points to the correct location. The
return value is true if insertion should be done after the location,
! or false if before the location. If new basic block has to be created,
! it is stored in *NEW_BB. */
static bool
! tree_find_edge_insert_loc (edge e, block_stmt_iterator *bsi,
! basic_block *new_bb)
{
basic_block dest, src;
tree tmp;
*************** tree_find_edge_insert_loc (edge e, block
*** 2635,2640 ****
--- 2637,2644 ----
/* Otherwise, create a new basic block, and split this edge. */
dest = split_edge (e);
+ if (new_bb)
+ *new_bb = dest;
e = dest->pred;
goto restart;
}
*************** bsi_commit_edge_inserts_1 (edge e)
*** 2677,2683 ****
PENDING_STMT (e) = NULL_TREE;
! if (tree_find_edge_insert_loc (e, &bsi))
bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
else
bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
--- 2681,2687 ----
PENDING_STMT (e) = NULL_TREE;
! if (tree_find_edge_insert_loc (e, &bsi, NULL))
bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
else
bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
*************** bsi_insert_on_edge (edge e, tree stmt)
*** 2694,2714 ****
append_to_statement_list (stmt, &PENDING_STMT (e));
}
! /* Similar to bsi_insert_on_edge+bsi_commit_edge_inserts. */
/* ??? Why in the world do we need this? Only PRE uses it. */
! void
bsi_insert_on_edge_immediate (edge e, tree stmt)
{
block_stmt_iterator bsi;
if (PENDING_STMT (e))
abort ();
! if (tree_find_edge_insert_loc (e, &bsi))
bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
else
bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
}
/*---------------------------------------------------------------------------
--- 2698,2722 ----
append_to_statement_list (stmt, &PENDING_STMT (e));
}
! /* Similar to bsi_insert_on_edge+bsi_commit_edge_inserts. If new block has to
! be created, it is returned. */
/* ??? Why in the world do we need this? Only PRE uses it. */
! basic_block
bsi_insert_on_edge_immediate (edge e, tree stmt)
{
block_stmt_iterator bsi;
+ basic_block new_bb = NULL;
if (PENDING_STMT (e))
abort ();
! if (tree_find_edge_insert_loc (e, &bsi, &new_bb))
bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
else
bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
+
+ return new_bb;
}
/*---------------------------------------------------------------------------
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.177.2.6
diff -c -3 -p -r1.1.4.177.2.6 tree-flow.h
*** tree-flow.h 25 Jan 2004 20:20:16 -0000 1.1.4.177.2.6
--- tree-flow.h 30 Jan 2004 01:31:21 -0000
*************** extern void tree_optimize_tail_calls (bo
*** 448,454 ****
extern edge tree_block_forwards_to (basic_block bb);
extern void bsi_insert_on_edge (edge, tree);
extern void bsi_commit_edge_inserts (int *);
! extern void bsi_insert_on_edge_immediate (edge, tree);
extern void notice_special_calls (tree);
extern void clear_special_calls (void);
extern void compute_dominance_frontiers (bitmap *);
--- 448,454 ----
extern edge tree_block_forwards_to (basic_block bb);
extern void bsi_insert_on_edge (edge, tree);
extern void bsi_commit_edge_inserts (int *);
! extern basic_block bsi_insert_on_edge_immediate (edge, tree);
extern void notice_special_calls (tree);
extern void clear_special_calls (void);
extern void compute_dominance_frontiers (bitmap *);
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop-ivopts.c,v
retrieving revision 1.1.2.2
diff -c -3 -p -r1.1.2.2 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c 25 Jan 2004 22:37:11 -0000 1.1.2.2
--- tree-ssa-loop-ivopts.c 30 Jan 2004 01:31:21 -0000
*************** create_new_iv (struct iv_cand *cand)
*** 2851,2857 ****
initial = force_gimple_operand (base, &stmts,
SSA_NAME_VAR (cand->var_before), false);
if (stmts)
! bsi_insert_on_edge_immediate (loop_preheader_edge (current_loop), stmts);
stmt = create_phi_node (cand->var_before, current_loop->header);
SSA_NAME_DEF_STMT (cand->var_before) = stmt;
--- 2851,2864 ----
initial = force_gimple_operand (base, &stmts,
SSA_NAME_VAR (cand->var_before), false);
if (stmts)
! {
! basic_block new_bb;
! edge pe = loop_preheader_edge (current_loop);
!
! new_bb = bsi_insert_on_edge_immediate (pe, stmts);
! if (new_bb)
! add_bb_to_loop (new_bb, new_bb->pred->src->loop_father);
! }
stmt = create_phi_node (cand->var_before, current_loop->header);
SSA_NAME_DEF_STMT (cand->var_before) = stmt;
Index: tree-ssa-loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop.c,v
retrieving revision 1.1.2.3.2.6
diff -c -3 -p -r1.1.2.3.2.6 tree-ssa-loop.c
*** tree-ssa-loop.c 29 Jan 2004 18:36:37 -0000 1.1.2.3.2.6
--- tree-ssa-loop.c 30 Jan 2004 01:31:21 -0000
*************** copy_loop_headers (void)
*** 192,197 ****
--- 192,201 ----
loop->latch = loop->header;
loop->header = new_header;
+ /* Predict the loop to be entered. */
+ predict_edge_def (loop_preheader_edge (loop), PRED_LOOP_HEADER,
+ TAKEN);
+
/* Ensure that the latch has just a single successor. */
loop_split_edge_with (loop_latch_edge (loop), NULL);
}