Commit cb20f7e8 by Zdenek Dvorak Committed by Steven Bosscher

Commit part of Zdenek's larger loop-invariant.c patch.

	* loop-invariant.c (df): New global variable.
	(find_defs, check_dependencies, find_invariant_insn, record_uses,
	find_invariants_bb, find_invariants_body, find_invariants,
	find_invariants_to_move, move_invariants, free_inv_motion_data,
	move_single_loop_invariants, move_loop_invariants): Do not pass df in
	arguments.

Co-Authored-By: Steven Bosscher <stevenb@suse.de>

From-SVN: r108605
parent 0a942fea
2005-12-15 Zdenek Dvorak <dvorakz@suse.cz>
Steven Bosscher <stevenb@suse.de>
* loop-invariant.c (df): New global variable.
(find_defs, check_dependencies, find_invariant_insn, record_uses,
find_invariants_bb, find_invariants_body, find_invariants,
find_invariants_to_move, move_invariants, free_inv_motion_data,
move_single_loop_invariants, move_loop_invariants): Do not pass df in
arguments.
2005-12-15 Jakub Jelinek <jakub@redhat.com> 2005-12-15 Jakub Jelinek <jakub@redhat.com>
* varasm.c (default_unique_section_1): Use special section * varasm.c (default_unique_section_1): Use special section
......
/* Rtl-level loop invariant motion. /* RTL-level loop invariant motion.
Copyright (C) 2004, 2005 Free Software Foundation, Inc. Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it 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 under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any Free Software Foundation; either version 2, or (at your option) any
later version. later version.
GCC is distributed in the hope that it will be useful, but WITHOUT GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details. for more details.
You should have received a copy of the GNU General Public License 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 along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */ 02110-1301, USA. */
/* This implements the loop invariant motion pass. It is very simple /* This implements the loop invariant motion pass. It is very simple
(no calls, libcalls, etc.). This should be sufficient to cleanup things like (no calls, libcalls, etc.). This should be sufficient to cleanup things
address arithmetics -- other more complicated invariants should be like address arithmetics -- other more complicated invariants should be
eliminated on tree level either in tree-ssa-loop-im.c or in tree-ssa-pre.c. eliminated on tree level either in tree-ssa-loop-im.c or in tree-ssa-pre.c.
We proceed loop by loop -- it is simpler than trying to handle things We proceed loop by loop -- it is simpler than trying to handle things
globally and should not lose much. First we inspect all sets inside loop globally and should not lose much. First we inspect all sets inside loop
and create a dependency graph on insns (saying "to move this insn, you must and create a dependency graph on insns (saying "to move this insn, you must
...@@ -31,7 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA ...@@ -31,7 +31,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
We then need to determine what to move. We estimate the number of registers We then need to determine what to move. We estimate the number of registers
used and move as many invariants as possible while we still have enough free used and move as many invariants as possible while we still have enough free
registers. We prefer the expensive invariants. registers. We prefer the expensive invariants.
Then we move the selected invariants out of the loop, creating a new Then we move the selected invariants out of the loop, creating a new
temporaries for them if necessary. */ temporaries for them if necessary. */
...@@ -103,7 +103,7 @@ struct invariant ...@@ -103,7 +103,7 @@ struct invariant
/* Whether to move the invariant. */ /* Whether to move the invariant. */
bool move; bool move;
/* Cost if the invariant. */ /* Cost of the invariant. */
unsigned cost; unsigned cost;
/* The invariants it depends on. */ /* The invariants it depends on. */
...@@ -128,6 +128,10 @@ DEF_VEC_ALLOC_P(invariant_p, heap); ...@@ -128,6 +128,10 @@ DEF_VEC_ALLOC_P(invariant_p, heap);
static VEC(invariant_p,heap) *invariants; static VEC(invariant_p,heap) *invariants;
/* The dataflow object. */
static struct df *df;
/* Test for possibility of invariantness of X. */ /* Test for possibility of invariantness of X. */
static bool static bool
...@@ -259,7 +263,7 @@ find_exits (struct loop *loop, basic_block *body, ...@@ -259,7 +263,7 @@ find_exits (struct loop *loop, basic_block *body,
} }
continue; continue;
} }
/* Use the data stored for the subloop to decide whether we may exit /* Use the data stored for the subloop to decide whether we may exit
through it. It is sufficient to do this for header of the loop, through it. It is sufficient to do this for header of the loop,
as other basic blocks inside it must be dominated by it. */ as other basic blocks inside it must be dominated by it. */
...@@ -298,11 +302,11 @@ may_assign_reg_p (rtx x) ...@@ -298,11 +302,11 @@ may_assign_reg_p (rtx x)
|| REGNO_REG_CLASS (REGNO (x)) != NO_REGS)); || REGNO_REG_CLASS (REGNO (x)) != NO_REGS));
} }
/* Finds definitions that may correspond to invariants in LOOP with body BODY. /* Finds definitions that may correspond to invariants in LOOP with body
DF is the dataflow object. */ BODY. */
static void static void
find_defs (struct loop *loop, basic_block *body, struct df *df) find_defs (struct loop *loop, basic_block *body)
{ {
unsigned i; unsigned i;
bitmap blocks = BITMAP_ALLOC (NULL); bitmap blocks = BITMAP_ALLOC (NULL);
...@@ -374,10 +378,10 @@ record_use (struct def *def, rtx *use, rtx insn) ...@@ -374,10 +378,10 @@ record_use (struct def *def, rtx *use, rtx insn)
} }
/* Finds the invariants INSN depends on and store them to the DEPENDS_ON /* Finds the invariants INSN depends on and store them to the DEPENDS_ON
bitmap. DF is the dataflow object. */ bitmap. */
static bool static bool
check_dependencies (rtx insn, struct df *df, bitmap depends_on) check_dependencies (rtx insn, bitmap depends_on)
{ {
struct df_link *uses, *defs; struct df_link *uses, *defs;
struct ref *use, *def; struct ref *use, *def;
...@@ -412,12 +416,10 @@ check_dependencies (rtx insn, struct df *df, bitmap depends_on) ...@@ -412,12 +416,10 @@ check_dependencies (rtx insn, struct df *df, bitmap depends_on)
/* Finds invariant in INSN. ALWAYS_REACHED is true if the insn is always /* Finds invariant in INSN. ALWAYS_REACHED is true if the insn is always
executed. ALWAYS_EXECUTED is true if the insn is always executed, executed. ALWAYS_EXECUTED is true if the insn is always executed,
unless the program ends due to a function call. DF is the dataflow unless the program ends due to a function call. */
object. */
static void static void
find_invariant_insn (rtx insn, bool always_reached, bool always_executed, find_invariant_insn (rtx insn, bool always_reached, bool always_executed)
struct df *df)
{ {
struct ref *ref; struct ref *ref;
struct def *def; struct def *def;
...@@ -430,7 +432,7 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed, ...@@ -430,7 +432,7 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed,
|| find_reg_note (insn, REG_LIBCALL, NULL_RTX) || find_reg_note (insn, REG_LIBCALL, NULL_RTX)
|| find_reg_note (insn, REG_NO_CONFLICT, NULL_RTX)) || find_reg_note (insn, REG_NO_CONFLICT, NULL_RTX))
return; return;
set = single_set (insn); set = single_set (insn);
if (!set) if (!set)
return; return;
...@@ -456,7 +458,7 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed, ...@@ -456,7 +458,7 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed,
} }
depends_on = BITMAP_ALLOC (NULL); depends_on = BITMAP_ALLOC (NULL);
if (!check_dependencies (insn, df, depends_on)) if (!check_dependencies (insn, depends_on))
{ {
BITMAP_FREE (depends_on); BITMAP_FREE (depends_on);
return; return;
...@@ -474,11 +476,10 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed, ...@@ -474,11 +476,10 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed,
create_new_invariant (def, insn, depends_on, always_executed); create_new_invariant (def, insn, depends_on, always_executed);
} }
/* Record registers used in INSN that have a unique invariant definition. /* Record registers used in INSN that have a unique invariant definition. */
DF is the dataflow object. */
static void static void
record_uses (rtx insn, struct df *df) record_uses (rtx insn)
{ {
struct df_link *uses, *defs; struct df_link *uses, *defs;
struct ref *use, *def; struct ref *use, *def;
...@@ -505,25 +506,22 @@ record_uses (rtx insn, struct df *df) ...@@ -505,25 +506,22 @@ record_uses (rtx insn, struct df *df)
/* Finds invariants in INSN. ALWAYS_REACHED is true if the insn is always /* Finds invariants in INSN. ALWAYS_REACHED is true if the insn is always
executed. ALWAYS_EXECUTED is true if the insn is always executed, executed. ALWAYS_EXECUTED is true if the insn is always executed,
unless the program ends due to a function call. DF is the dataflow unless the program ends due to a function call. */
object. */
static void static void
find_invariants_insn (rtx insn, bool always_reached, bool always_executed, find_invariants_insn (rtx insn, bool always_reached, bool always_executed)
struct df *df)
{ {
find_invariant_insn (insn, always_reached, always_executed, df); find_invariant_insn (insn, always_reached, always_executed);
record_uses (insn, df); record_uses (insn);
} }
/* Finds invariants in basic block BB. ALWAYS_REACHED is true if the /* Finds invariants in basic block BB. ALWAYS_REACHED is true if the
basic block is always executed. ALWAYS_EXECUTED is true if the basic basic block is always executed. ALWAYS_EXECUTED is true if the basic
block is always executed, unless the program ends due to a function block is always executed, unless the program ends due to a function
call. DF is the dataflow object. */ call. */
static void static void
find_invariants_bb (basic_block bb, bool always_reached, bool always_executed, find_invariants_bb (basic_block bb, bool always_reached, bool always_executed)
struct df *df)
{ {
rtx insn; rtx insn;
...@@ -532,7 +530,7 @@ find_invariants_bb (basic_block bb, bool always_reached, bool always_executed, ...@@ -532,7 +530,7 @@ find_invariants_bb (basic_block bb, bool always_reached, bool always_executed,
if (!INSN_P (insn)) if (!INSN_P (insn))
continue; continue;
find_invariants_insn (insn, always_reached, always_executed, df); find_invariants_insn (insn, always_reached, always_executed);
if (always_reached if (always_reached
&& CALL_P (insn) && CALL_P (insn)
...@@ -544,26 +542,24 @@ find_invariants_bb (basic_block bb, bool always_reached, bool always_executed, ...@@ -544,26 +542,24 @@ find_invariants_bb (basic_block bb, bool always_reached, bool always_executed,
/* Finds invariants in LOOP with body BODY. ALWAYS_REACHED is the bitmap of /* Finds invariants in LOOP with body BODY. ALWAYS_REACHED is the bitmap of
basic blocks in BODY that are always executed. ALWAYS_EXECUTED is the basic blocks in BODY that are always executed. ALWAYS_EXECUTED is the
bitmap of basic blocks in BODY that are always executed unless the program bitmap of basic blocks in BODY that are always executed unless the program
ends due to a function call. DF is the dataflow object. */ ends due to a function call. */
static void static void
find_invariants_body (struct loop *loop, basic_block *body, find_invariants_body (struct loop *loop, basic_block *body,
bitmap always_reached, bitmap always_executed, bitmap always_reached, bitmap always_executed)
struct df *df)
{ {
unsigned i; unsigned i;
for (i = 0; i < loop->num_nodes; i++) for (i = 0; i < loop->num_nodes; i++)
find_invariants_bb (body[i], find_invariants_bb (body[i],
bitmap_bit_p (always_reached, i), bitmap_bit_p (always_reached, i),
bitmap_bit_p (always_executed, i), bitmap_bit_p (always_executed, i));
df);
} }
/* Finds invariants in LOOP. DF is the dataflow object. */ /* Finds invariants in LOOP. */
static void static void
find_invariants (struct loop *loop, struct df *df) find_invariants (struct loop *loop)
{ {
bitmap may_exit = BITMAP_ALLOC (NULL); bitmap may_exit = BITMAP_ALLOC (NULL);
bitmap always_reached = BITMAP_ALLOC (NULL); bitmap always_reached = BITMAP_ALLOC (NULL);
...@@ -575,8 +571,8 @@ find_invariants (struct loop *loop, struct df *df) ...@@ -575,8 +571,8 @@ find_invariants (struct loop *loop, struct df *df)
compute_always_reached (loop, body, may_exit, always_reached); compute_always_reached (loop, body, may_exit, always_reached);
compute_always_reached (loop, body, has_exit, always_executed); compute_always_reached (loop, body, has_exit, always_executed);
find_defs (loop, body, df); find_defs (loop, body);
find_invariants_body (loop, body, always_reached, always_executed, df); find_invariants_body (loop, body, always_reached, always_executed);
BITMAP_FREE (always_reached); BITMAP_FREE (always_reached);
BITMAP_FREE (always_executed); BITMAP_FREE (always_executed);
...@@ -721,10 +717,10 @@ set_move_mark (unsigned invno) ...@@ -721,10 +717,10 @@ set_move_mark (unsigned invno)
} }
} }
/* Determines which invariants to move. DF is the dataflow object. */ /* Determines which invariants to move. */
static void static void
find_invariants_to_move (struct df *df) find_invariants_to_move (void)
{ {
unsigned i, regs_used, n_inv_uses, regs_needed = 0, new_regs; unsigned i, regs_used, n_inv_uses, regs_needed = 0, new_regs;
struct invariant *inv = NULL; struct invariant *inv = NULL;
...@@ -764,10 +760,10 @@ find_invariants_to_move (struct df *df) ...@@ -764,10 +760,10 @@ find_invariants_to_move (struct df *df)
} }
} }
/* Move invariant INVNO out of the LOOP. DF is the dataflow object. */ /* Move invariant INVNO out of the LOOP. */
static void static void
move_invariant_reg (struct loop *loop, unsigned invno, struct df *df) move_invariant_reg (struct loop *loop, unsigned invno)
{ {
struct invariant *inv = VEC_index (invariant_p, invariants, invno); struct invariant *inv = VEC_index (invariant_p, invariants, invno);
unsigned i; unsigned i;
...@@ -784,7 +780,7 @@ move_invariant_reg (struct loop *loop, unsigned invno, struct df *df) ...@@ -784,7 +780,7 @@ move_invariant_reg (struct loop *loop, unsigned invno, struct df *df)
{ {
EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, i, bi) EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, i, bi)
{ {
move_invariant_reg (loop, i, df); move_invariant_reg (loop, i);
} }
} }
...@@ -828,10 +824,10 @@ move_invariant_reg (struct loop *loop, unsigned invno, struct df *df) ...@@ -828,10 +824,10 @@ move_invariant_reg (struct loop *loop, unsigned invno, struct df *df)
} }
/* Move selected invariant out of the LOOP. Newly created regs are marked /* Move selected invariant out of the LOOP. Newly created regs are marked
in TEMPORARY_REGS. DF is the dataflow object. */ in TEMPORARY_REGS. */
static void static void
move_invariants (struct loop *loop, struct df *df) move_invariants (struct loop *loop)
{ {
struct invariant *inv; struct invariant *inv;
unsigned i; unsigned i;
...@@ -839,7 +835,7 @@ move_invariants (struct loop *loop, struct df *df) ...@@ -839,7 +835,7 @@ move_invariants (struct loop *loop, struct df *df)
for (i = 0; VEC_iterate (invariant_p, invariants, i, inv); i++) for (i = 0; VEC_iterate (invariant_p, invariants, i, inv); i++)
{ {
if (inv->move) if (inv->move)
move_invariant_reg (loop, i, df); move_invariant_reg (loop, i);
} }
} }
...@@ -853,11 +849,10 @@ init_inv_motion_data (void) ...@@ -853,11 +849,10 @@ init_inv_motion_data (void)
invariants = VEC_alloc (invariant_p, heap, 100); invariants = VEC_alloc (invariant_p, heap, 100);
} }
/* Frees the data allocated by invariant motion. DF is the dataflow /* Frees the data allocated by invariant motion. */
object. */
static void static void
free_inv_motion_data (struct df *df) free_inv_motion_data (void)
{ {
unsigned i; unsigned i;
struct def *def; struct def *def;
...@@ -885,18 +880,18 @@ free_inv_motion_data (struct df *df) ...@@ -885,18 +880,18 @@ free_inv_motion_data (struct df *df)
VEC_free (invariant_p, heap, invariants); VEC_free (invariant_p, heap, invariants);
} }
/* Move the invariants out of the LOOP. DF is the dataflow object. */ /* Move the invariants out of the LOOP. */
static void static void
move_single_loop_invariants (struct loop *loop, struct df *df) move_single_loop_invariants (struct loop *loop)
{ {
init_inv_motion_data (); init_inv_motion_data ();
find_invariants (loop, df); find_invariants (loop);
find_invariants_to_move (df); find_invariants_to_move ();
move_invariants (loop, df); move_invariants (loop);
free_inv_motion_data (df); free_inv_motion_data ();
} }
/* Releases the auxiliary data for LOOP. */ /* Releases the auxiliary data for LOOP. */
...@@ -917,7 +912,8 @@ move_loop_invariants (struct loops *loops) ...@@ -917,7 +912,8 @@ move_loop_invariants (struct loops *loops)
{ {
struct loop *loop; struct loop *loop;
unsigned i; unsigned i;
struct df *df = df_init ();
df = df_init ();
/* Process the loops, innermost first. */ /* Process the loops, innermost first. */
loop = loops->tree_root; loop = loops->tree_root;
...@@ -926,7 +922,7 @@ move_loop_invariants (struct loops *loops) ...@@ -926,7 +922,7 @@ move_loop_invariants (struct loops *loops)
while (loop != loops->tree_root) while (loop != loops->tree_root)
{ {
move_single_loop_invariants (loop, df); move_single_loop_invariants (loop);
if (loop->next) if (loop->next)
{ {
......
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