[lno] Unswitching on trees
Zdenek Dvorak
rakdver@atrey.karlin.mff.cuni.cz
Sun Mar 21 13:33:00 GMT 2004
Hello,
this patch adds unswitching on trees. This should eventually replace
the rtl level unswitching (once loop versioning handles loops with
multiple exits).
Zdenek
Index: ChangeLog.lno
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/ChangeLog.lno,v
retrieving revision 1.1.2.96
diff -c -3 -p -r1.1.2.96 ChangeLog.lno
*** ChangeLog.lno 21 Mar 2004 03:19:33 -0000 1.1.2.96
--- ChangeLog.lno 21 Mar 2004 13:30:58 -0000
***************
*** 1,3 ****
--- 1,22 ----
+ 2004-03-21 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * tree-ssa-loop-unswitch.o: New file.
+ * Makefile.in (tree-ssa-loop-unswitch.o): Add.
+ (tree-ssa-loop-im.o): Add flags.h dependency.
+ * flags.h (flag_unswitch_loops): Declaration moved from ...
+ * toplev.h (flag_unswitch_loops): ... here.
+ * tree-flow.h (tree_ssa_loop_version): Declaration changed.
+ (tree_ssa_unswitch_loops, estimate_loop_size): Declare.
+ * tree-ssa-loop-im.c: Include flags.h.
+ (movement_possibility, stmt_cost, move_computations_stmt):
+ Handle unswitchable conditions.
+ * tree-ssa-loop-ivcanon.c (estimate_loop_size): Export.
+ * tree-ssa-loop-ivopts.c (find_interesting_uses_cond): Handle
+ if (0) and if (1).
+ * tree-ssa-loop-manip.c (tree_ssa_loop_version): Return the newly
+ created loop.
+ * tree-ssa-loop.c (tree_ssa_loop_opt): Call tree_ssa_unswitch_loops.
+
2004-03-20 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
Merge from tree-ssa branch (lno-merge-20040321).
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.158.2.22
diff -c -3 -p -r1.903.2.158.2.22 Makefile.in
*** Makefile.in 21 Mar 2004 03:19:34 -0000 1.903.2.158.2.22
--- Makefile.in 21 Mar 2004 13:30:58 -0000
*************** OBJS-common = \
*** 876,887 ****
tree-ssa-phiopt.o tree-ssa-forwprop.o tree-nested.o tree-ssa-dse.o \
tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o tree-iterator.o \
tree-phinodes.o tree-ssanames.o tree-sra.o tree-complex.o tree-ssa-loop.o \
tree-vectorizer.o tree-ssa-loop-im.o tree-ssa-loop-manip.o \
tree-ssa-loop-ivopts.o tree-ssa-loop-ivcanon.o tree-dg.o loop-invariant.o \
alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
cfgloopanal.o cfgloopmanip.o loop-iv.o loop-init.o loop-unswitch.o \
! loop-unroll.o loop-doloop.o tree-ssa-return.o \
cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \
dbxout.o debug.o df.o diagnostic.o dojump.o doloop.o dominance.o \
dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o \
--- 876,888 ----
tree-ssa-phiopt.o tree-ssa-forwprop.o tree-nested.o tree-ssa-dse.o \
tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o tree-iterator.o \
tree-phinodes.o tree-ssanames.o tree-sra.o tree-complex.o tree-ssa-loop.o \
+ tree-ssa-loop-unswitch.o \
tree-vectorizer.o tree-ssa-loop-im.o tree-ssa-loop-manip.o \
tree-ssa-loop-ivopts.o tree-ssa-loop-ivcanon.o tree-dg.o loop-invariant.o \
alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
cfgloopanal.o cfgloopmanip.o loop-iv.o loop-init.o loop-unswitch.o \
! loop-unroll.o loop-doloop.o tree-ssa-return.o \
cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \
dbxout.o debug.o df.o diagnostic.o dojump.o doloop.o dominance.o \
dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o \
*************** tree-ssa-loop.o : tree-ssa-loop.c $(TREE
*** 1645,1650 ****
--- 1646,1655 ----
output.h diagnostic.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
tree-pass.h flags.h
tree-ssa-loop-im.o : tree-ssa-loop-im.c $(TREE_FLOW_H) $(CONFIG_H) \
+ $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) cfgloop.h domwalk.h $(PARAMS_H)\
+ output.h diagnostic.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
+ tree-pass.h flags.h
+ tree-ssa-loop-unswitch.o : tree-ssa-loop-unswitch.c $(TREE_FLOW_H) $(CONFIG_H) \
$(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) cfgloop.h domwalk.h $(PARAMS_H)\
output.h diagnostic.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
tree-pass.h
Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.86.2.41.2.11
diff -c -3 -p -r1.86.2.41.2.11 flags.h
*** flags.h 21 Mar 2004 03:19:59 -0000 1.86.2.41.2.11
--- flags.h 21 Mar 2004 13:30:58 -0000
*************** extern int flag_reduce_all_givs;
*** 294,299 ****
--- 294,302 ----
/* Nonzero enables loop unrolling. */
extern int flag_unroll_loops;
+ /* Nonzero enables loop unswitching. */
+ extern int flag_unswitch_loops;
+
/* Nonzero for -fcse-follow-jumps:
have cse follow jumps to do a more extensive job. */
Index: toplev.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.h,v
retrieving revision 1.87.2.12.2.5
diff -c -3 -p -r1.87.2.12.2.5 toplev.h
*** toplev.h 21 Mar 2004 03:20:19 -0000 1.87.2.12.2.5
--- toplev.h 21 Mar 2004 13:30:58 -0000
*************** extern int flag_rerun_cse_after_loop;
*** 121,127 ****
extern int flag_thread_jumps;
extern int flag_tracer;
extern int flag_unroll_all_loops;
- extern int flag_unswitch_loops;
extern int flag_cprop_registers;
extern int time_report;
extern int flag_new_regalloc;
--- 121,126 ----
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.177.2.17
diff -c -3 -p -r1.1.4.177.2.17 tree-flow.h
*** tree-flow.h 21 Mar 2004 03:20:20 -0000 1.1.4.177.2.17
--- tree-flow.h 21 Mar 2004 13:30:58 -0000
*************** bool tree_duplicate_loop_to_header_edge
*** 606,615 ****
void create_iv (tree, tree, tree, struct loop *, block_stmt_iterator *, bool,
tree *, tree *);
void test_loop_versioning (struct loops *loops);
! bool tree_ssa_loop_version (struct loops *, struct loop *, tree);
bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
void linear_transform_loops (struct loops *, varray_type);
void loop_commit_inserts (void);
/* In tree-flow-inline.h */
static inline int phi_arg_from_edge (tree, edge);
--- 606,617 ----
void create_iv (tree, tree, tree, struct loop *, block_stmt_iterator *, bool,
tree *, tree *);
void test_loop_versioning (struct loops *loops);
! struct loop *tree_ssa_loop_version (struct loops *, struct loop *, tree);
bool for_each_index (tree *, bool (*) (tree, tree *, void *), void *);
void linear_transform_loops (struct loops *, varray_type);
void loop_commit_inserts (void);
+ void tree_ssa_unswitch_loops (struct loops *loops);
+ unsigned estimate_loop_size (struct loop *loop);
/* In tree-flow-inline.h */
static inline int phi_arg_from_edge (tree, edge);
Index: tree-ssa-loop-im.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop-im.c,v
retrieving revision 1.1.2.9
diff -c -3 -p -r1.1.2.9 tree-ssa-loop-im.c
*** tree-ssa-loop-im.c 21 Mar 2004 03:20:22 -0000 1.1.2.9
--- tree-ssa-loop-im.c 21 Mar 2004 13:30:58 -0000
*************** Software Foundation, 59 Temple Place - S
*** 36,41 ****
--- 36,42 ----
#include "domwalk.h"
#include "params.h"
#include "tree-pass.h"
+ #include "flags.h"
/* A list of dependencies. */
*************** movement_possibility (tree stmt)
*** 144,149 ****
--- 145,160 ----
{
tree lhs, rhs;
+ if (flag_unswitch_loops
+ && TREE_CODE (stmt) == COND_EXPR)
+ {
+ /* If we perform unswitching, force the operands of the invariant
+ condition to be moved out of the loop. */
+ get_stmt_operands (stmt);
+
+ return MOVE_POSSIBLE;
+ }
+
if (TREE_CODE (stmt) != MODIFY_EXPR)
return MOVE_IMPOSSIBLE;
*************** stmt_cost (tree stmt)
*** 245,250 ****
--- 256,265 ----
tree lhs, rhs;
unsigned cost = 1;
+ /* Always try to create possibilities for unswitching. */
+ if (TREE_CODE (stmt) == COND_EXPR)
+ return 20;
+
lhs = TREE_OPERAND (stmt, 0);
rhs = TREE_OPERAND (stmt, 1);
*************** move_computations_stmt (struct dom_walk_
*** 527,532 ****
--- 542,552 ----
bsi_next (&bsi);
continue;
}
+
+ /* We do not really want to move conditionals out of the loop; we just
+ placed it here to force its operands to be moved if neccesary. */
+ if (TREE_CODE (stmt) == COND_EXPR)
+ continue;
if (dump_file && (dump_flags & TDF_DETAILS))
{
Index: tree-ssa-loop-ivcanon.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop-ivcanon.c,v
retrieving revision 1.1.2.5
diff -c -3 -p -r1.1.2.5 tree-ssa-loop-ivcanon.c
*** tree-ssa-loop-ivcanon.c 21 Mar 2004 03:20:22 -0000 1.1.2.5
--- tree-ssa-loop-ivcanon.c 21 Mar 2004 13:30:58 -0000
*************** create_canonical_iv (struct loop *loop,
*** 319,325 ****
/* Computes an estimated number of insns in LOOP. */
! static unsigned
estimate_loop_size (struct loop *loop)
{
basic_block *body = get_loop_body (loop);
--- 319,325 ----
/* Computes an estimated number of insns in LOOP. */
! unsigned
estimate_loop_size (struct loop *loop)
{
basic_block *body = get_loop_body (loop);
Index: tree-ssa-loop-ivopts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop-ivopts.c,v
retrieving revision 1.1.2.16
diff -c -3 -p -r1.1.2.16 tree-ssa-loop-ivopts.c
*** tree-ssa-loop-ivopts.c 21 Mar 2004 03:20:22 -0000 1.1.2.16
--- tree-ssa-loop-ivopts.c 21 Mar 2004 13:30:58 -0000
*************** find_interesting_uses_cond (tree stmt, t
*** 1959,1964 ****
--- 1959,1968 ----
const_iv.step = NULL_TREE;
+ if (integer_zerop (*cond_p)
+ || integer_nonzerop (*cond_p))
+ return;
+
if (TREE_CODE (*cond_p) == SSA_NAME)
{
op0_p = cond_p;
Index: tree-ssa-loop-manip.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop-manip.c,v
retrieving revision 1.1.2.5
diff -c -3 -p -r1.1.2.5 tree-ssa-loop-manip.c
*** tree-ssa-loop-manip.c 17 Mar 2004 18:39:43 -0000 1.1.2.5
--- tree-ssa-loop-manip.c 21 Mar 2004 13:30:58 -0000
*************** is the loop transformed in another way (
*** 653,698 ****
may be a run time test for things that were not resolved by static
analysis (overlapping ranges (anti-aliasing), alignment, etc.). */
! bool
! tree_ssa_loop_version (struct loops *loops,
! struct loop * loop,
! tree cond_expr)
{
edge entry, latch_edge;
basic_block first_head, second_head, condition_bb;
int irred_flag;
struct loop *nloop;
- sbitmap zero_bitmap;
/* CHECKME: Loop versioning does not handle nested loop at this point. */
if (loop->inner)
! return false;
/* Record entry and latch edges for the loop */
entry = loop_preheader_edge (loop);
- /* CHECKME: We split entry edge later in loop versioning. tree_split_edge() does not
- set bb flags appropriately if entry edge is marked as EDGE_IRREDUCILE_LOOP. Skip
- such looos for now. */
- if (entry->flags & EDGE_IRREDUCIBLE_LOOP)
- return false;
-
/* Note down head of loop as first_head. */
first_head = entry->dest;
- zero_bitmap = sbitmap_alloc (2);
- sbitmap_zero (zero_bitmap);
-
/* Duplicate loop. */
irred_flag = entry->flags & EDGE_IRREDUCIBLE_LOOP;
entry->flags &= ~EDGE_IRREDUCIBLE_LOOP;
if (!tree_duplicate_loop_to_header_edge (loop, entry, loops, 1,
! zero_bitmap, NULL, NULL, NULL, 0))
! return false;
!
entry->flags |= irred_flag;
-
/* After duplication entry edge now points to new loop head blcok.
Note down new head as second_head. */
second_head = entry->dest;
--- 653,687 ----
may be a run time test for things that were not resolved by static
analysis (overlapping ranges (anti-aliasing), alignment, etc.). */
! struct loop *
! tree_ssa_loop_version (struct loops *loops, struct loop * loop, tree cond_expr)
{
edge entry, latch_edge;
basic_block first_head, second_head, condition_bb;
int irred_flag;
struct loop *nloop;
/* CHECKME: Loop versioning does not handle nested loop at this point. */
if (loop->inner)
! return NULL;
/* Record entry and latch edges for the loop */
entry = loop_preheader_edge (loop);
/* Note down head of loop as first_head. */
first_head = entry->dest;
/* Duplicate loop. */
irred_flag = entry->flags & EDGE_IRREDUCIBLE_LOOP;
entry->flags &= ~EDGE_IRREDUCIBLE_LOOP;
if (!tree_duplicate_loop_to_header_edge (loop, entry, loops, 1,
! NULL, NULL, NULL, NULL, 0))
! {
! entry->flags |= irred_flag;
! return NULL;
! }
entry->flags |= irred_flag;
/* After duplication entry edge now points to new loop head blcok.
Note down new head as second_head. */
second_head = entry->dest;
*************** tree_ssa_loop_version (struct loops *loo
*** 724,732 ****
loop_split_edge_with (loop_latch_edge (loop), NULL);
loop_split_edge_with (loop_latch_edge (nloop), NULL);
! free (zero_bitmap);
!
! return true;
}
--- 713,719 ----
loop_split_edge_with (loop_latch_edge (loop), NULL);
loop_split_edge_with (loop_latch_edge (nloop), NULL);
! return nloop;
}
Index: tree-ssa-loop-unswitch.c
===================================================================
RCS file: tree-ssa-loop-unswitch.c
diff -N tree-ssa-loop-unswitch.c
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- tree-ssa-loop-unswitch.c 21 Mar 2004 13:30:58 -0000
***************
*** 0 ****
--- 1,281 ----
+ /* Loop unswitching.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+ #include "config.h"
+ #include "system.h"
+ #include "coretypes.h"
+ #include "tm.h"
+ #include "tree.h"
+ #include "rtl.h"
+ #include "tm_p.h"
+ #include "hard-reg-set.h"
+ #include "basic-block.h"
+ #include "output.h"
+ #include "diagnostic.h"
+ #include "tree-flow.h"
+ #include "tree-dump.h"
+ #include "timevar.h"
+ #include "cfgloop.h"
+ #include "domwalk.h"
+ #include "params.h"
+ #include "tree-pass.h"
+
+ /* This file implements the loop unswitching, i.e. transformation of loops like
+
+ while (A)
+ {
+ if (inv)
+ B;
+
+ X;
+
+ if (!inv)
+ C;
+ }
+
+ where inv is the loop invariant, into
+
+ if (inv)
+ {
+ while (A)
+ {
+ B;
+ X;
+ }
+ }
+ else
+ {
+ while (A)
+ {
+ X;
+ C;
+ }
+ }
+
+ Inv is considered invariant iff the values it compares are both invariant;
+ tree-ssa-loop-im.c ensures that all the suitable conditions are in this
+ shape. */
+
+ static struct loop *tree_unswitch_loop (struct loops *, struct loop *, basic_block,
+ tree);
+ static void tree_unswitch_single_loop (struct loops *, struct loop *, int);
+ static tree tree_may_unswitch_on (basic_block, struct loop *);
+
+ /* Main entry point. Perform loop unswitching on all suitable LOOPS. */
+
+ void
+ tree_ssa_unswitch_loops (struct loops *loops)
+ {
+ int i, num;
+ struct loop *loop;
+
+ /* Go through inner loops (only original ones). */
+ num = loops->num;
+
+ for (i = 1; i < num; i++)
+ {
+ /* Removed loop? */
+ loop = loops->parray[i];
+ if (!loop)
+ continue;
+
+ if (loop->inner)
+ continue;
+
+ tree_unswitch_single_loop (loops, loop, 0);
+ #ifdef ENABLE_CHECKING
+ verify_dominators (CDI_DOMINATORS);
+ verify_loop_structure (loops);
+ #endif
+ }
+ }
+
+ /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
+ basic blocks (for what it means see comments below). */
+
+ static tree
+ tree_may_unswitch_on (basic_block bb, struct loop *loop)
+ {
+ tree stmt, def, cond;
+ basic_block def_bb;
+ use_optype uses;
+ unsigned i;
+
+ /* BB must end in a simple conditional jump. */
+ stmt = last_stmt (bb);
+ if (!stmt || TREE_CODE (stmt) != COND_EXPR)
+ return NULL_TREE;
+
+ /* Condition must be invariant. */
+ get_stmt_operands (stmt);
+ uses = STMT_USE_OPS (stmt);
+ for (i = 0; i < NUM_USES (uses); i++)
+ {
+ def = SSA_NAME_DEF_STMT (USE_OP (uses, i));
+ def_bb = bb_for_stmt (def);
+ if (def_bb
+ && flow_bb_inside_loop_p (loop, def_bb))
+ return NULL_TREE;
+ }
+
+ cond = COND_EXPR_COND (stmt);
+ /* To keep the things simple, we do not directly remove the conditions,
+ but just replace tests with 0/1. Prevent the infinite loop where we
+ would unswitch again on such a condition. */
+ if (integer_zerop (cond) || integer_nonzerop (cond))
+ return NULL_TREE;
+
+ return cond;
+ }
+
+ /* Simplifies COND using checks in front of the entry of the LOOP. Just very
+ simplish (sufficient to prevent us from duplicating loop in unswitching
+ unneccesarily). */
+
+ static tree
+ simplify_using_entry_checks (struct loop *loop, tree cond)
+ {
+ edge e = loop_preheader_edge (loop);
+ tree stmt;
+
+ while (1)
+ {
+ stmt = last_stmt (e->src);
+ if (stmt
+ && TREE_CODE (stmt) == COND_EXPR
+ && operand_equal_p (COND_EXPR_COND (stmt), cond, 0))
+ return (e->flags & EDGE_TRUE_VALUE
+ ? boolean_true_node
+ : boolean_false_node);
+
+ if (e->src->pred->pred_next)
+ return cond;
+
+ e = e->src->pred;
+ if (e->src == ENTRY_BLOCK_PTR)
+ return cond;
+ }
+ }
+
+ /* Unswitch single LOOP. NUM is number of unswitchings done; we do not allow
+ it to grow too much, it is too easy to create example on that the code would
+ grow exponentially. */
+
+ static void
+ tree_unswitch_single_loop (struct loops *loops, struct loop *loop, int num)
+ {
+ basic_block *bbs;
+ struct loop *nloop;
+ unsigned i;
+ tree cond = NULL_TREE, stmt;
+
+ /* Do not unswitch too much. */
+ if (num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, ";; Not unswitching anymore, hit max level\n");
+ return;
+ }
+
+ /* Only unswitch innermost loops. */
+ if (loop->inner)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, ";; Not unswitching, not innermost loop\n");
+ return;
+ }
+
+ /* The loop should not be too large, to limit code growth. */
+ if (estimate_loop_size (loop)
+ > (unsigned) PARAM_VALUE (PARAM_MAX_UNSWITCH_INSNS))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, ";; Not unswitching, loop too big\n");
+ return;
+ }
+
+ i = 0;
+ bbs = get_loop_body (loop);
+
+ while (1)
+ {
+ /* Find a bb to unswitch on. */
+ for (; i < loop->num_nodes; i++)
+ if ((cond = tree_may_unswitch_on (bbs[i], loop)))
+ break;
+
+ if (i == loop->num_nodes)
+ {
+ free (bbs);
+ return;
+ }
+
+ cond = simplify_using_entry_checks (loop, cond);
+ stmt = last_stmt (bbs[i]);
+ if (integer_nonzerop (cond))
+ {
+ /* Remove false path. */
+ COND_EXPR_COND (stmt) = boolean_true_node;
+ }
+ else if (integer_zerop (cond))
+ {
+ /* Remove true path. */
+ COND_EXPR_COND (stmt) = boolean_false_node;
+ }
+ else
+ break;
+
+ modify_stmt (stmt);
+ i++;
+ }
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, ";; Unswitching loop\n");
+
+ /* Unswitch the loop on this condition. */
+ nloop = tree_unswitch_loop (loops, loop, bbs[i], cond);
+ if (!nloop)
+ return;
+
+ /* Invoke itself on modified loops. */
+ tree_unswitch_single_loop (loops, nloop, num + 1);
+ tree_unswitch_single_loop (loops, loop, num + 1);
+ }
+
+ /* Unswitch a LOOP w.r. to given basic block UNSWITCH_ON. We only support
+ unswitching of innermost loops. COND is the condition determining which
+ loop is entered -- the new loop is entered if COND is true. Returns NULL
+ if impossible, new loop otherwise. */
+
+ static struct loop *
+ tree_unswitch_loop (struct loops *loops, struct loop *loop,
+ basic_block unswitch_on, tree cond)
+ {
+ /* Some sanity checking. */
+ if (!flow_bb_inside_loop_p (loop, unswitch_on))
+ abort ();
+ if (!unswitch_on->succ || !unswitch_on->succ->succ_next ||
+ unswitch_on->succ->succ_next->succ_next)
+ abort ();
+ if (loop->inner)
+ abort ();
+
+ return tree_ssa_loop_version (loops, loop, unshare_expr (cond));
+ }
Index: tree-ssa-loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-loop.c,v
retrieving revision 1.1.2.3.2.15
diff -c -3 -p -r1.1.2.3.2.15 tree-ssa-loop.c
*** tree-ssa-loop.c 21 Mar 2004 03:20:22 -0000 1.1.2.3.2.15
--- tree-ssa-loop.c 21 Mar 2004 13:30:58 -0000
*************** tree_ssa_loop_opt (void)
*** 87,92 ****
--- 87,96 ----
/* Move the expensive loop invariants. */
tree_ssa_lim (loops);
+ /* Unswitch the loops. */
+ if (flag_unswitch_loops)
+ tree_ssa_unswitch_loops (loops);
+
/* Optimize the induction variables. */
tree_ssa_iv_optimize (loops);
More information about the Gcc-patches
mailing list