[patch] rtl iv analysis merge from killloop branch
Zdenek Dvorak
rakdver@atrey.karlin.mff.cuni.cz
Wed Jan 11 01:12:00 GMT 2006
Hello,
this is the updated version of the patch
http://gcc.gnu.org/ml/gcc-patches/2005-11/msg01839.html.
Only the parts in df.c that were already merged change, plus I extended
the comments at the start of loop-iv.c a bit.
This patch makes loop-iv.c use df.c UD-chains, instead of its own simple
implementation. The way the analysis works is basically unchanged --
we walk the UD chains, analysing the givs recursively by
iv_analyze_expr/iv_analyze_op/iv_analyze_def functions. When header of
the loop is reached, iv_analyze_biv/get_biv_step are called to check
whether the last processed register is a biv. The results are cached
at definitions in DF_REF_DATA (for givs) and in a hashtable of bivs.
The updated patch was bootstrapped & regtested on i686.
Zdenek
* loop-iv.c: Include df.h and hashtab.h.
(enum iv_grd_result): New enum.
(DF_REF_IV, DF_REF_IV_SET): New macros.
(struct biv_entry): New.
(df, bivs): New global variables.
(struct insn_info, insn_info, last_def, bivs, max_insn_no, max_reg_no,
assign_luids, mark_sets, kill_sets, mark_single_set, simple_set_p):
Removed.
(clear_iv_info, latch_dominating_def, record_iv, iv_analyze_expr,
iv_analyze_result, iv_analyze_def, biv_hash, biv_eq,
analyzed_for_bivness_p, record_biv): New functions.
(iv_analysis_loop_init, iv_get_reaching_def, simple_reg_p,
get_biv_step_1, get_biv_step, iv_analyze_biv, iv_analyze_op,
iv_analyze, biv_p, iv_analysis_done): Work with df representation of
UD chains.
(iv_constant, iv_subreg, iv_extend, iv_mult, iv_shift): Do not set
analysed.
(iv_number_of_iterations): Use new interface to iv analysis.
* loop-unroll.c: Do not include varray.h.
(analyze_iv_to_split_insn): Use new interface to iv
analysis.
* loop-unswitch.c (may_unswitch_on): Ditto.
* optabs.c (expand_unop): Make the mode of the REG_EQUAL node be
outmode.
* cfgloop.h (struct rtx_iv): Remove analysed field.
(iv_get_reaching_def): Removed.
(iv_analyze_result, iv_analyze_expr, iv_current_loop_df): Declare.
* Makefile.in (loop-unroll.o): Remove VARRAY_H dependency.
(loop-iv.o): Add df.h and hashtab.h dependency.
Index: loop-unswitch.c
===================================================================
*** loop-unswitch.c (revision 109543)
--- loop-unswitch.c (working copy)
*************** unswitch_loops (struct loops *loops)
*** 172,178 ****
static rtx
may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
{
! rtx test, at, insn, op[2], stest;
struct rtx_iv iv;
unsigned i;
enum machine_mode mode;
--- 172,178 ----
static rtx
may_unswitch_on (basic_block bb, struct loop *loop, rtx *cinsn)
{
! rtx test, at, op[2], stest;
struct rtx_iv iv;
unsigned i;
enum machine_mode mode;
*************** may_unswitch_on (basic_block bb, struct
*** 205,212 ****
if (CONSTANT_P (op[i]))
continue;
! insn = iv_get_reaching_def (at, op[i]);
! if (!iv_analyze (insn, op[i], &iv))
return NULL_RTX;
if (iv.step != const0_rtx
|| iv.first_special)
--- 205,211 ----
if (CONSTANT_P (op[i]))
continue;
! if (!iv_analyze (at, op[i], &iv))
return NULL_RTX;
if (iv.step != const0_rtx
|| iv.first_special)
Index: optabs.c
===================================================================
*** optabs.c (revision 109543)
--- optabs.c (working copy)
*************** expand_unop (enum machine_mode mode, opt
*** 2567,2573 ****
target = gen_reg_rtx (outmode);
emit_libcall_block (insns, target, value,
! gen_rtx_fmt_e (unoptab->code, mode, op0));
return target;
}
--- 2567,2573 ----
target = gen_reg_rtx (outmode);
emit_libcall_block (insns, target, value,
! gen_rtx_fmt_e (unoptab->code, outmode, op0));
return target;
}
Index: loop-unroll.c
===================================================================
*** loop-unroll.c (revision 109543)
--- loop-unroll.c (working copy)
*************** Software Foundation, 51 Franklin Street,
*** 33,39 ****
#include "expr.h"
#include "hashtab.h"
#include "recog.h"
- #include "varray.h"
/* This pass performs loop unrolling and peeling. We only perform these
optimizations on innermost loops (with single exception) because
--- 33,38 ----
*************** analyze_iv_to_split_insn (rtx insn)
*** 1670,1676 ****
if (!biv_p (insn, dest))
return NULL;
! ok = iv_analyze (insn, dest, &iv);
gcc_assert (ok);
if (iv.step == const0_rtx
--- 1669,1675 ----
if (!biv_p (insn, dest))
return NULL;
! ok = iv_analyze_result (insn, dest, &iv);
gcc_assert (ok);
if (iv.step == const0_rtx
Index: loop-iv.c
===================================================================
*** loop-iv.c (revision 109543)
--- loop-iv.c (working copy)
*************** along with GCC; see the file COPYING. I
*** 18,51 ****
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
! /* This is just a very simplistic analysis of induction variables of the loop.
! The major use is for determining the number of iterations of a loop for
! loop unrolling, doloop optimization and branch prediction. For this we
! are only interested in bivs and a fairly limited set of givs that are
! needed in the exit condition. We also only compute the iv information on
! demand.
!
! The interesting registers are determined. A register is interesting if
!
! -- it is set only in the blocks that dominate the latch of the current loop
! -- all its sets are simple -- i.e. in the form we understand
!
! We also number the insns sequentially in each basic block. For a use of the
! interesting reg, it is now easy to find a reaching definition (there may be
! only one).
!
! Induction variable is then simply analyzed by walking the use-def
! chains.
!
! Usage:
!
! iv_analysis_loop_init (loop);
! insn = iv_get_reaching_def (where, reg);
! if (iv_analyze (insn, reg, &iv))
! {
! ...
! }
! iv_analysis_done (); */
#include "config.h"
#include "system.h"
--- 18,52 ----
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
! /* This is a simple analysis of induction variables of the loop. The major use
! is for determining the number of iterations of a loop for loop unrolling,
! doloop optimization and branch prediction. The iv information is computed
! on demand.
!
! Induction variable is analyzed by walking the use-def chains. When a biv
! is found, it is cached in the bivs hash table. When register is proved
! to be a giv, its description is stored to DF_REF_DATA of the def reference.
!
! The analysis works always with one loop -- you must call
! iv_analysis_loop_init (loop) for it. All the other functions then work with
! this loop. When you need to work with another loop, just call
! iv_analysis_loop_init for it. When you no longer need iv analysis, call
! iv_analysis_done () to clean up the memory.
!
! The available functions are:
!
! iv_analyze (insn, reg, iv): Stores the description of the induction variable
! corresponding to the use of register REG in INSN to IV. Returns true if
! REG is an induction variable in INSN. false otherwise.
! If use of REG is not found in INSN, following insns are scanned (so that
! we may call this function on insn returned by get_condition).
! iv_analyze_result (insn, def, iv): Stores to IV the description of the iv
! corresponding to DEF, which is a register defined in INSN.
! iv_analyze_expr (insn, rhs, mode, iv): Stores to IV the description of iv
! corresponding to expression EXPR evaluated at INSN. All registers used bu
! EXPR must also be used in INSN.
! iv_current_loop_df (): Returns the dataflow object for the current loop used
! by iv analysis. */
#include "config.h"
#include "system.h"
*************** Software Foundation, 51 Franklin Street,
*** 60,99 ****
#include "intl.h"
#include "output.h"
#include "toplev.h"
! /* The insn information. */
! struct insn_info
{
! /* Id of the insn. */
! unsigned luid;
! /* The previous definition of the register defined by the single
! set in the insn. */
! rtx prev_def;
! /* The description of the iv. */
! struct rtx_iv iv;
};
! static struct insn_info *insn_info;
! /* The last definition of register. */
! static rtx *last_def;
! /* The bivs. */
! static struct rtx_iv *bivs;
! /* Maximal insn number for that there is place in insn_info array. */
! static unsigned max_insn_no;
! /* Maximal register number for that there is place in bivs and last_def
! arrays. */
! static unsigned max_reg_no;
/* Dumps information about IV to FILE. */
--- 61,121 ----
#include "intl.h"
#include "output.h"
#include "toplev.h"
+ #include "df.h"
+ #include "hashtab.h"
! /* Possible return values of iv_get_reaching_def. */
! enum iv_grd_result
{
! /* More than one reaching def, or reaching def that does not
! dominate the use. */
! GRD_INVALID,
! /* The use is trivial invariant of the loop, i.e. is not changed
! inside the loop. */
! GRD_INVARIANT,
! /* The use is reached by initial value and a value from the
! previous iteration. */
! GRD_MAYBE_BIV,
!
! /* The use has single dominating def. */
! GRD_SINGLE_DOM
! };
!
! /* Information about a biv. */
!
! struct biv_entry
! {
! unsigned regno; /* The register of the biv. */
! struct rtx_iv iv; /* Value of the biv. */
};
! /* Induction variable stored at the reference. */
! #define DF_REF_IV(REF) ((struct rtx_iv *) DF_REF_DATA (REF))
! #define DF_REF_IV_SET(REF, IV) DF_REF_DATA (REF) = (IV)
! /* The current loop. */
! static struct loop *current_loop;
! /* Dataflow information for the current loop. */
! static struct df *df;
! /* Bivs of the current loop. */
! static htab_t bivs;
! /* Return the dataflow object for the current loop. */
! struct df *
! iv_current_loop_df (void)
! {
! return df;
! }
! static bool iv_analyze_op (rtx, rtx, struct rtx_iv *);
/* Dumps information about IV to FILE. */
*************** dump_iv_info (FILE *file, struct rtx_iv
*** 139,161 ****
fprintf (file, " (first special)");
}
- /* Assigns luids to insns in basic block BB. */
-
- 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;
- }
- }
-
/* Generates a subreg to get the least significant part of EXPR (in mode
INNER_MODE) to OUTER_MODE. */
--- 161,166 ----
*************** simple_reg_p (rtx reg)
*** 191,321 ****
if (GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT)
return false;
- if (last_def[r] == const0_rtx)
- return false;
-
return true;
}
! /* Checks whether assignment LHS = RHS is simple enough for us to process. */
! static bool
! simple_set_p (rtx lhs, rtx rhs)
{
! rtx op0, op1;
!
! if (!REG_P (lhs)
! || !simple_reg_p (lhs))
! return false;
!
! if (CONSTANT_P (rhs))
! return true;
! switch (GET_CODE (rhs))
{
! case SUBREG:
! case REG:
! return simple_reg_p (rhs);
!
! case SIGN_EXTEND:
! case ZERO_EXTEND:
! case NEG:
! return simple_reg_p (XEXP (rhs, 0));
!
! case PLUS:
! case MINUS:
! case MULT:
! case ASHIFT:
! op0 = XEXP (rhs, 0);
! op1 = XEXP (rhs, 1);
!
! if (!simple_reg_p (op0)
! && !CONSTANT_P (op0))
! return false;
!
! if (!simple_reg_p (op1)
! && !CONSTANT_P (op1))
! return false;
!
! if (GET_CODE (rhs) == MULT
! && !CONSTANT_P (op0)
! && !CONSTANT_P (op1))
! return false;
!
! if (GET_CODE (rhs) == ASHIFT
! && CONSTANT_P (op0))
! return false;
!
! return true;
! default:
! return false;
}
- }
-
- /* Mark single SET in INSN. */
-
- static rtx
- mark_single_set (rtx insn, rtx set)
- {
- rtx def = SET_DEST (set), src;
- unsigned regno, uid;
-
- src = find_reg_equal_equiv_note (insn);
- if (src)
- src = XEXP (src, 0);
- else
- src = SET_SRC (set);
-
- if (!simple_set_p (SET_DEST (set), src))
- return NULL_RTX;
-
- regno = REGNO (def);
- uid = INSN_UID (insn);
-
- bivs[regno].analysed = false;
- insn_info[uid].prev_def = last_def[regno];
- last_def[regno] = insn;
! return def;
}
! /* Invalidate register REG unless it is equal to EXCEPT. */
! static void
! kill_sets (rtx reg, rtx by ATTRIBUTE_UNUSED, void *except)
{
! if (GET_CODE (reg) == SUBREG)
! reg = SUBREG_REG (reg);
! if (!REG_P (reg))
! return;
! if (reg == except)
! return;
!
! last_def[REGNO (reg)] = const0_rtx;
}
! /* Marks sets in basic block BB. If DOM is true, BB dominates the loop
! latch. */
! static void
! mark_sets (basic_block bb, bool dom)
{
! rtx insn, set, def;
!
! FOR_BB_INSNS (bb, insn)
! {
! if (!INSN_P (insn))
! continue;
!
! if (dom
! && (set = single_set (insn)))
! def = mark_single_set (insn, set);
! else
! def = NULL_RTX;
!
! note_stores (PATTERN (insn), kill_sets, def);
! }
}
/* Prepare the data for an induction variable analysis of a LOOP. */
--- 196,241 ----
if (GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT)
return false;
return true;
}
! /* Clears the information about ivs stored in df. */
! static void
! clear_iv_info (void)
{
! unsigned i;
! struct rtx_iv *iv;
! for (i = 0; i < df->n_defs; i++)
{
! if (!df->defs[i])
! continue;
! iv = DF_REF_IV (df->defs[i]);
! if (!iv)
! continue;
! free (iv);
! DF_REF_IV_SET (df->defs[i], NULL);
}
! htab_empty (bivs);
}
! /* Returns hash value for biv B. */
! static hashval_t
! biv_hash (const void *b)
{
! return ((const struct biv_entry *) b)->regno;
}
! /* Compares biv B and register R. */
! static int
! biv_eq (const void *b, const void *r)
{
! return ((const struct biv_entry *) b)->regno == REGNO ((rtx) r);
}
/* Prepare the data for an induction variable analysis of a LOOP. */
*************** mark_sets (basic_block bb, bool dom)
*** 323,419 ****
void
iv_analysis_loop_init (struct loop *loop)
{
! basic_block *body = get_loop_body_in_dom_order (loop);
! unsigned b;
! if ((unsigned) get_max_uid () >= max_insn_no)
{
! /* Add some reserve for insns and registers produced in optimizations. */
! max_insn_no = get_max_uid () + 100;
! if (insn_info)
! free (insn_info);
! insn_info = xmalloc (max_insn_no * sizeof (struct insn_info));
}
! if ((unsigned) max_reg_num () >= max_reg_no)
{
! max_reg_no = max_reg_num () + 100;
! if (last_def)
! free (last_def);
! last_def = xmalloc (max_reg_no * sizeof (rtx));
! if (bivs)
! free (bivs);
! bivs = xmalloc (max_reg_no * sizeof (struct rtx_iv));
! }
! memset (last_def, 0, max_reg_num () * sizeof (rtx));
! for (b = 0; b < loop->num_nodes; b++)
! {
! assign_luids (body[b]);
! mark_sets (body[b], just_once_each_iteration_p (loop, body[b]));
}
free (body);
}
! /* Gets definition of REG reaching the INSN. If REG is not simple, const0_rtx
! is returned. If INSN is before the first def in the loop, NULL_RTX is
! returned. */
! rtx
! iv_get_reaching_def (rtx insn, rtx reg)
{
! unsigned regno, luid, auid;
! rtx ainsn;
! basic_block bb, abb;
! if (GET_CODE (reg) == SUBREG)
{
! if (!subreg_lowpart_p (reg))
! return const0_rtx;
! reg = SUBREG_REG (reg);
}
- if (!REG_P (reg))
- return NULL_RTX;
! regno = REGNO (reg);
! if (!last_def[regno]
! || last_def[regno] == const0_rtx)
! return last_def[regno];
! bb = BLOCK_FOR_INSN (insn);
! luid = insn_info[INSN_UID (insn)].luid;
! ainsn = last_def[regno];
! while (1)
! {
! abb = BLOCK_FOR_INSN (ainsn);
! if (dominated_by_p (CDI_DOMINATORS, bb, abb))
! break;
! auid = INSN_UID (ainsn);
! ainsn = insn_info[auid].prev_def;
! if (!ainsn)
! return NULL_RTX;
! }
! while (1)
{
! abb = BLOCK_FOR_INSN (ainsn);
! if (abb != bb)
! return ainsn;
!
! auid = INSN_UID (ainsn);
! if (luid > insn_info[auid].luid)
! return ainsn;
!
! ainsn = insn_info[auid].prev_def;
! if (!ainsn)
! return NULL_RTX;
}
}
/* Sets IV to invariant CST in MODE. Always returns true (just for
--- 243,375 ----
void
iv_analysis_loop_init (struct loop *loop)
{
! basic_block *body = get_loop_body_in_dom_order (loop), bb;
! bitmap blocks = BITMAP_ALLOC (NULL);
! unsigned i;
! rtx insn;
! bool first_time = (df == NULL);
! current_loop = loop;
!
! /* Clear the information from the analysis of the previous loop. */
! if (first_time)
{
! df = df_init ();
! bivs = htab_create (10, biv_hash, biv_eq, free);
}
+ else
+ clear_iv_info ();
! for (i = 0; i < loop->num_nodes; i++)
{
! bb = body[i];
! bitmap_set_bit (blocks, bb->index);
! if (first_time)
! continue;
! /* Mark everything in the body of the loop as modified, since this may be
! the case, and we do not keep track of what changes. */
! FOR_BB_INSNS (bb, insn)
! {
! df_insn_modify (df, bb, insn);
! }
}
+ df_analyze_subcfg (df, blocks, DF_UD_CHAIN
+ | DF_RD_CHAIN
+ | DF_RU_CHAIN
+ | DF_HARD_REGS
+ | DF_EQUIV_NOTES);
+
+ BITMAP_FREE (blocks);
free (body);
}
! /* Finds the definition of REG that dominates loop latch and stores
! it to DEF. Returns false if there is not a single definition
! dominating the latch. If REG has no definition in loop, DEF
! is set to NULL and true is returned. */
! static bool
! latch_dominating_def (rtx reg, struct ref **def)
{
! struct ref *single_rd = NULL, *adef;
! struct df_link *def_link;
! unsigned regno = REGNO (reg);
! struct bb_info *bb_info = DF_BB_INFO (df, current_loop->latch);
! for (def_link = df->regs[regno].defs; def_link; def_link = def_link->next)
{
! adef = def_link->ref;
!
! if (!bitmap_bit_p (bb_info->rd_out, DF_REF_ID (adef)))
! continue;
!
! /* More than one reaching definition. */
! if (single_rd)
! return false;
!
! if (!just_once_each_iteration_p (current_loop, DF_REF_BB (adef)))
! return false;
!
! single_rd = adef;
}
! *def = single_rd;
! return true;
! }
!
! /* Gets definition of REG reaching its use in INSN and stores it to DEF. */
! static enum iv_grd_result
! iv_get_reaching_def (rtx insn, rtx reg, struct ref **def)
! {
! struct ref *use, *adef;
! basic_block def_bb, use_bb;
! rtx def_insn;
! bool dom_p;
!
! *def = NULL;
! if (!simple_reg_p (reg))
! return GRD_INVALID;
! if (GET_CODE (reg) == SUBREG)
! reg = SUBREG_REG (reg);
! gcc_assert (REG_P (reg));
! use = df_find_use (df, insn, reg);
! gcc_assert (use != NULL);
! if (!DF_REF_CHAIN (use))
! return GRD_INVARIANT;
! /* More than one reaching def. */
! if (DF_REF_CHAIN (use)->next)
! return GRD_INVALID;
! adef = DF_REF_CHAIN (use)->ref;
! def_insn = DF_REF_INSN (adef);
! def_bb = DF_REF_BB (adef);
! use_bb = BLOCK_FOR_INSN (insn);
! if (use_bb == def_bb)
! dom_p = (DF_INSN_LUID (df, def_insn) < DF_INSN_LUID (df, insn));
! else
! dom_p = dominated_by_p (CDI_DOMINATORS, use_bb, def_bb);
!
! if (dom_p)
{
! *def = adef;
! return GRD_SINGLE_DOM;
}
+
+ /* The definition does not dominate the use. This is still OK if
+ this may be a use of a biv, i.e. if the def_bb dominates loop
+ latch. */
+ if (just_once_each_iteration_p (current_loop, def_bb))
+ return GRD_MAYBE_BIV;
+
+ return GRD_INVALID;
}
/* Sets IV to invariant CST in MODE. Always returns true (just for
*************** iv_constant (struct rtx_iv *iv, rtx cst,
*** 425,431 ****
if (mode == VOIDmode)
mode = GET_MODE (cst);
- iv->analysed = true;
iv->mode = mode;
iv->base = cst;
iv->step = const0_rtx;
--- 381,386 ----
*************** iv_shift (struct rtx_iv *iv, rtx mby)
*** 653,672 ****
}
/* The recursive part of get_biv_step. Gets the value of the single value
! defined in INSN wrto initial value of REG inside loop, in shape described
at get_biv_step. */
static bool
! get_biv_step_1 (rtx insn, rtx reg,
rtx *inner_step, enum machine_mode *inner_mode,
enum rtx_code *extend, enum machine_mode outer_mode,
rtx *outer_step)
{
rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
! rtx next, nextr, def_insn, tmp;
enum rtx_code code;
set = single_set (insn);
rhs = find_reg_equal_equiv_note (insn);
if (rhs)
rhs = XEXP (rhs, 0);
--- 608,633 ----
}
/* The recursive part of get_biv_step. Gets the value of the single value
! defined by DEF wrto initial value of REG inside loop, in shape described
at get_biv_step. */
static bool
! get_biv_step_1 (struct ref *def, rtx reg,
rtx *inner_step, enum machine_mode *inner_mode,
enum rtx_code *extend, enum machine_mode outer_mode,
rtx *outer_step)
{
rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
! rtx next, nextr, tmp;
enum rtx_code code;
+ rtx insn = DF_REF_INSN (def);
+ struct ref *next_def;
+ enum iv_grd_result res;
set = single_set (insn);
+ if (!set)
+ return false;
+
rhs = find_reg_equal_equiv_note (insn);
if (rhs)
rhs = XEXP (rhs, 0);
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 742,752 ****
else
nextr = next;
! def_insn = iv_get_reaching_def (insn, nextr);
! if (def_insn == const0_rtx)
return false;
! if (!def_insn)
{
if (!rtx_equal_p (nextr, reg))
return false;
--- 703,714 ----
else
nextr = next;
! res = iv_get_reaching_def (insn, nextr, &next_def);
!
! if (res == GRD_INVALID || res == GRD_INVARIANT)
return false;
! if (res == GRD_MAYBE_BIV)
{
if (!rtx_equal_p (nextr, reg))
return false;
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 756,762 ****
*inner_mode = outer_mode;
*outer_step = const0_rtx;
}
! else if (!get_biv_step_1 (def_insn, reg,
inner_step, inner_mode, extend, outer_mode,
outer_step))
return false;
--- 718,724 ----
*inner_mode = outer_mode;
*outer_step = const0_rtx;
}
! else if (!get_biv_step_1 (next_def, reg,
inner_step, inner_mode, extend, outer_mode,
outer_step))
return false;
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 803,809 ****
break;
default:
! gcc_unreachable ();
}
return true;
--- 765,771 ----
break;
default:
! return false;
}
return true;
*************** get_biv_step_1 (rtx insn, rtx reg,
*** 813,828 ****
OUTER_STEP + EXTEND_{OUTER_MODE} (SUBREG_{INNER_MODE} (REG + INNER_STEP))
! If the operation cannot be described in this shape, return false. */
static bool
! get_biv_step (rtx reg, rtx *inner_step, enum machine_mode *inner_mode,
! enum rtx_code *extend, enum machine_mode *outer_mode,
! rtx *outer_step)
{
*outer_mode = GET_MODE (reg);
! if (!get_biv_step_1 (last_def[REGNO (reg)], reg,
inner_step, inner_mode, extend, *outer_mode,
outer_step))
return false;
--- 775,791 ----
OUTER_STEP + EXTEND_{OUTER_MODE} (SUBREG_{INNER_MODE} (REG + INNER_STEP))
! If the operation cannot be described in this shape, return false.
! LAST_DEF is the definition of REG that dominates loop latch. */
static bool
! get_biv_step (struct ref *last_def, rtx reg, rtx *inner_step,
! enum machine_mode *inner_mode, enum rtx_code *extend,
! enum machine_mode *outer_mode, rtx *outer_step)
{
*outer_mode = GET_MODE (reg);
! if (!get_biv_step_1 (last_def, reg,
inner_step, inner_mode, extend, *outer_mode,
outer_step))
return false;
*************** get_biv_step (rtx reg, rtx *inner_step,
*** 833,848 ****
return true;
}
/* Determines whether DEF is a biv and if so, stores its description
to *IV. */
static bool
iv_analyze_biv (rtx def, struct rtx_iv *iv)
{
- unsigned regno;
rtx inner_step, outer_step;
enum machine_mode inner_mode, outer_mode;
enum rtx_code extend;
if (dump_file)
{
--- 796,849 ----
return true;
}
+ /* Records information that DEF is induction variable IV. */
+
+ static void
+ record_iv (struct ref *def, struct rtx_iv *iv)
+ {
+ struct rtx_iv *recorded_iv = xmalloc (sizeof (struct rtx_iv));
+
+ *recorded_iv = *iv;
+ DF_REF_IV_SET (def, recorded_iv);
+ }
+
+ /* If DEF was already analyzed for bivness, store the description of the biv to
+ IV and return true. Otherwise return false. */
+
+ static bool
+ analyzed_for_bivness_p (rtx def, struct rtx_iv *iv)
+ {
+ struct biv_entry *biv = htab_find_with_hash (bivs, def, REGNO (def));
+
+ if (!biv)
+ return false;
+
+ *iv = biv->iv;
+ return true;
+ }
+
+ static void
+ record_biv (rtx def, struct rtx_iv *iv)
+ {
+ struct biv_entry *biv = xmalloc (sizeof (struct biv_entry));
+ void **slot = htab_find_slot_with_hash (bivs, def, REGNO (def), INSERT);
+
+ biv->regno = REGNO (def);
+ biv->iv = *iv;
+ gcc_assert (!*slot);
+ *slot = biv;
+ }
+
/* Determines whether DEF is a biv and if so, stores its description
to *IV. */
static bool
iv_analyze_biv (rtx def, struct rtx_iv *iv)
{
rtx inner_step, outer_step;
enum machine_mode inner_mode, outer_mode;
enum rtx_code extend;
+ struct ref *last_def;
if (dump_file)
{
*************** iv_analyze_biv (rtx def, struct rtx_iv *
*** 859,889 ****
return iv_constant (iv, def, VOIDmode);
}
! regno = REGNO (def);
! if (last_def[regno] == const0_rtx)
{
if (dump_file)
fprintf (dump_file, " not simple.\n");
return false;
}
! if (last_def[regno] && bivs[regno].analysed)
{
if (dump_file)
fprintf (dump_file, " already analysed.\n");
-
- *iv = bivs[regno];
return iv->base != NULL_RTX;
}
! if (!last_def[regno])
! {
! iv_constant (iv, def, VOIDmode);
! goto end;
! }
!
! iv->analysed = true;
! if (!get_biv_step (def, &inner_step, &inner_mode, &extend,
&outer_mode, &outer_step))
{
iv->base = NULL_RTX;
--- 860,883 ----
return iv_constant (iv, def, VOIDmode);
}
! if (!latch_dominating_def (def, &last_def))
{
if (dump_file)
fprintf (dump_file, " not simple.\n");
return false;
}
! if (!last_def)
! return iv_constant (iv, def, VOIDmode);
!
! if (analyzed_for_bivness_p (def, iv))
{
if (dump_file)
fprintf (dump_file, " already analysed.\n");
return iv->base != NULL_RTX;
}
! if (!get_biv_step (last_def, def, &inner_step, &inner_mode, &extend,
&outer_mode, &outer_step))
{
iv->base = NULL_RTX;
*************** iv_analyze_biv (rtx def, struct rtx_iv *
*** 913,1031 ****
fprintf (dump_file, "\n");
}
! bivs[regno] = *iv;
!
return iv->base != NULL_RTX;
}
! /* Analyzes operand OP of INSN and stores the result to *IV. */
! static bool
! iv_analyze_op (rtx insn, rtx op, struct rtx_iv *iv)
{
! rtx def_insn;
! unsigned regno;
! bool inv = CONSTANT_P (op);
!
! if (dump_file)
! {
! fprintf (dump_file, "Analyzing operand ");
! print_rtl (dump_file, op);
! fprintf (dump_file, " of insn ");
! print_rtl_single (dump_file, insn);
! }
!
! if (GET_CODE (op) == SUBREG)
! {
! if (!subreg_lowpart_p (op))
! return false;
! if (!iv_analyze_op (insn, SUBREG_REG (op), iv))
! return false;
! return iv_subreg (iv, GET_MODE (op));
! }
! if (!inv)
{
! regno = REGNO (op);
! if (!last_def[regno])
! inv = true;
! else if (last_def[regno] == const0_rtx)
{
! if (dump_file)
! fprintf (dump_file, " not simple.\n");
! return false;
}
}
! if (inv)
{
! iv_constant (iv, op, VOIDmode);
! if (dump_file)
{
! fprintf (dump_file, " ");
! dump_iv_info (dump_file, iv);
! fprintf (dump_file, "\n");
}
! return true;
! }
! def_insn = iv_get_reaching_def (insn, op);
! if (def_insn == const0_rtx)
! {
! if (dump_file)
! fprintf (dump_file, " not simple.\n");
return false;
}
! return iv_analyze (def_insn, op, iv);
! }
!
! /* Analyzes iv DEF defined in INSN and stores the result to *IV. */
!
! bool
! iv_analyze (rtx insn, rtx def, struct rtx_iv *iv)
! {
! unsigned uid;
! rtx set, rhs, mby = NULL_RTX, tmp;
! rtx op0 = NULL_RTX, op1 = NULL_RTX;
! struct rtx_iv iv0, iv1;
! enum machine_mode amode;
! enum rtx_code code;
! if (insn == const0_rtx)
return false;
! if (GET_CODE (def) == SUBREG)
{
! if (!subreg_lowpart_p (def))
return false;
! if (!iv_analyze (insn, SUBREG_REG (def), iv))
return false;
! return iv_subreg (iv, GET_MODE (def));
}
! if (!insn)
! return iv_analyze_biv (def, iv);
if (dump_file)
{
! fprintf (dump_file, "Analyzing def of ");
! print_rtl (dump_file, def);
fprintf (dump_file, " in insn ");
print_rtl_single (dump_file, insn);
}
! uid = INSN_UID (insn);
! if (insn_info[uid].iv.analysed)
{
if (dump_file)
fprintf (dump_file, " already analysed.\n");
! *iv = insn_info[uid].iv;
return iv->base != NULL_RTX;
}
--- 907,1060 ----
fprintf (dump_file, "\n");
}
! record_biv (def, iv);
return iv->base != NULL_RTX;
}
! /* Analyzes expression RHS used at INSN and stores the result to *IV.
! The mode of the induction variable is MODE. */
! bool
! iv_analyze_expr (rtx insn, rtx rhs, enum machine_mode mode, struct rtx_iv *iv)
{
! rtx mby = NULL_RTX, tmp;
! rtx op0 = NULL_RTX, op1 = NULL_RTX;
! struct rtx_iv iv0, iv1;
! enum rtx_code code = GET_CODE (rhs);
! enum machine_mode omode = mode;
! iv->mode = VOIDmode;
! iv->base = NULL_RTX;
! iv->step = NULL_RTX;
! gcc_assert (GET_MODE (rhs) == mode || GET_MODE (rhs) == VOIDmode);
! if (CONSTANT_P (rhs)
! || REG_P (rhs)
! || code == SUBREG)
{
! if (!iv_analyze_op (insn, rhs, iv))
! return false;
!
! if (iv->mode == VOIDmode)
{
! iv->mode = mode;
! iv->extend_mode = mode;
}
+
+ return true;
}
! switch (code)
{
! case REG:
! op0 = rhs;
! break;
! case SIGN_EXTEND:
! case ZERO_EXTEND:
! case NEG:
! op0 = XEXP (rhs, 0);
! omode = GET_MODE (op0);
! break;
!
! case PLUS:
! case MINUS:
! op0 = XEXP (rhs, 0);
! op1 = XEXP (rhs, 1);
! break;
!
! case MULT:
! op0 = XEXP (rhs, 0);
! mby = XEXP (rhs, 1);
! if (!CONSTANT_P (mby))
{
! tmp = op0;
! op0 = mby;
! mby = tmp;
}
! if (!CONSTANT_P (mby))
! return false;
! break;
! case ASHIFT:
! op0 = XEXP (rhs, 0);
! mby = XEXP (rhs, 1);
! if (!CONSTANT_P (mby))
! return false;
! break;
!
! default:
return false;
}
! if (op0
! && !iv_analyze_expr (insn, op0, omode, &iv0))
! return false;
! if (op1
! && !iv_analyze_expr (insn, op1, omode, &iv1))
return false;
! switch (code)
{
! case SIGN_EXTEND:
! case ZERO_EXTEND:
! if (!iv_extend (&iv0, code, mode))
! return false;
! break;
!
! case NEG:
! if (!iv_neg (&iv0))
return false;
+ break;
! case PLUS:
! case MINUS:
! if (!iv_add (&iv0, &iv1, code))
return false;
+ break;
! case MULT:
! if (!iv_mult (&iv0, mby))
! return false;
! break;
!
! case ASHIFT:
! if (!iv_shift (&iv0, mby))
! return false;
! break;
!
! default:
! break;
}
! *iv = iv0;
! return iv->base != NULL_RTX;
! }
!
! /* Analyzes iv DEF and stores the result to *IV. */
!
! static bool
! iv_analyze_def (struct ref *def, struct rtx_iv *iv)
! {
! rtx insn = DF_REF_INSN (def);
! rtx reg = DF_REF_REG (def);
! rtx set, rhs;
if (dump_file)
{
! fprintf (dump_file, "Analysing def of ");
! print_rtl (dump_file, reg);
fprintf (dump_file, " in insn ");
print_rtl_single (dump_file, insn);
}
! if (DF_REF_IV (def))
{
if (dump_file)
fprintf (dump_file, " already analysed.\n");
! *iv = *DF_REF_IV (def);
return iv->base != NULL_RTX;
}
*************** iv_analyze (rtx insn, rtx def, struct rt
*** 1034,1179 ****
iv->step = NULL_RTX;
set = single_set (insn);
rhs = find_reg_equal_equiv_note (insn);
if (rhs)
rhs = XEXP (rhs, 0);
else
rhs = SET_SRC (set);
- code = GET_CODE (rhs);
! if (CONSTANT_P (rhs))
{
! op0 = rhs;
! amode = GET_MODE (def);
}
- else
- {
- switch (code)
- {
- case SUBREG:
- if (!subreg_lowpart_p (rhs))
- goto end;
- op0 = rhs;
- break;
-
- case REG:
- op0 = rhs;
- break;
! case SIGN_EXTEND:
! case ZERO_EXTEND:
! case NEG:
! op0 = XEXP (rhs, 0);
! break;
! case PLUS:
! case MINUS:
! op0 = XEXP (rhs, 0);
! op1 = XEXP (rhs, 1);
! break;
! case MULT:
! op0 = XEXP (rhs, 0);
! mby = XEXP (rhs, 1);
! if (!CONSTANT_P (mby))
! {
! gcc_assert (CONSTANT_P (op0));
! tmp = op0;
! op0 = mby;
! mby = tmp;
! }
! break;
! case ASHIFT:
! gcc_assert (!CONSTANT_P (XEXP (rhs, 0)));
! op0 = XEXP (rhs, 0);
! mby = XEXP (rhs, 1);
! break;
! default:
! gcc_unreachable ();
! }
! amode = GET_MODE (rhs);
! }
! if (op0)
{
! if (!iv_analyze_op (insn, op0, &iv0))
! goto end;
!
! if (iv0.mode == VOIDmode)
{
! iv0.mode = amode;
! iv0.extend_mode = amode;
}
}
! if (op1)
{
! if (!iv_analyze_op (insn, op1, &iv1))
! goto end;
! if (iv1.mode == VOIDmode)
{
! iv1.mode = amode;
! iv1.extend_mode = amode;
}
}
! switch (code)
! {
! case SIGN_EXTEND:
! case ZERO_EXTEND:
! if (!iv_extend (&iv0, code, amode))
! goto end;
! break;
! case NEG:
! if (!iv_neg (&iv0))
! goto end;
! break;
! case PLUS:
! case MINUS:
! if (!iv_add (&iv0, &iv1, code))
! goto end;
! break;
! case MULT:
! if (!iv_mult (&iv0, mby))
! goto end;
! break;
! case ASHIFT:
! if (!iv_shift (&iv0, mby))
! goto end;
! break;
! default:
! break;
}
! *iv = iv0;
! end:
! iv->analysed = true;
! insn_info[uid].iv = *iv;
! if (dump_file)
! {
! print_rtl (dump_file, def);
! fprintf (dump_file, " in insn ");
! print_rtl_single (dump_file, insn);
! fprintf (dump_file, " is ");
! dump_iv_info (dump_file, iv);
! fprintf (dump_file, "\n");
! }
! return iv->base != NULL_RTX;
}
! /* Checks whether definition of register REG in INSN a basic induction
variable. IV analysis must have been initialized (via a call to
iv_analysis_loop_init) for this function to produce a result. */
--- 1063,1191 ----
iv->step = NULL_RTX;
set = single_set (insn);
+ if (!set || SET_DEST (set) != reg)
+ return false;
+
rhs = find_reg_equal_equiv_note (insn);
if (rhs)
rhs = XEXP (rhs, 0);
else
rhs = SET_SRC (set);
! iv_analyze_expr (insn, rhs, GET_MODE (reg), iv);
! record_iv (def, iv);
!
! if (dump_file)
{
! print_rtl (dump_file, reg);
! fprintf (dump_file, " in insn ");
! print_rtl_single (dump_file, insn);
! fprintf (dump_file, " is ");
! dump_iv_info (dump_file, iv);
! fprintf (dump_file, "\n");
}
! return iv->base != NULL_RTX;
! }
! /* Analyzes operand OP of INSN and stores the result to *IV. */
! static bool
! iv_analyze_op (rtx insn, rtx op, struct rtx_iv *iv)
! {
! struct ref *def = NULL;
! enum iv_grd_result res;
! if (dump_file)
! {
! fprintf (dump_file, "Analysing operand ");
! print_rtl (dump_file, op);
! fprintf (dump_file, " of insn ");
! print_rtl_single (dump_file, insn);
! }
! if (CONSTANT_P (op))
! res = GRD_INVARIANT;
! else if (GET_CODE (op) == SUBREG)
! {
! if (!subreg_lowpart_p (op))
! return false;
! if (!iv_analyze_op (insn, SUBREG_REG (op), iv))
! return false;
! return iv_subreg (iv, GET_MODE (op));
! }
! else
{
! res = iv_get_reaching_def (insn, op, &def);
! if (res == GRD_INVALID)
{
! if (dump_file)
! fprintf (dump_file, " not simple.\n");
! return false;
}
}
! if (res == GRD_INVARIANT)
{
! iv_constant (iv, op, VOIDmode);
! if (dump_file)
{
! fprintf (dump_file, " ");
! dump_iv_info (dump_file, iv);
! fprintf (dump_file, "\n");
}
+ return true;
}
! if (res == GRD_MAYBE_BIV)
! return iv_analyze_biv (op, iv);
! return iv_analyze_def (def, iv);
! }
! /* Analyzes value VAL at INSN and stores the result to *IV. */
! bool
! iv_analyze (rtx insn, rtx val, struct rtx_iv *iv)
! {
! rtx reg;
! /* We must find the insn in that val is used, so that we get to UD chains.
! Since the function is sometimes called on result of get_condition,
! this does not necessarily have to be directly INSN; scan also the
! following insns. */
! if (simple_reg_p (val))
! {
! if (GET_CODE (val) == SUBREG)
! reg = SUBREG_REG (val);
! else
! reg = val;
! while (!df_find_use (df, insn, reg))
! insn = NEXT_INSN (insn);
}
! return iv_analyze_op (insn, val, iv);
! }
! /* Analyzes definition of DEF in INSN and stores the result to IV. */
! bool
! iv_analyze_result (rtx insn, rtx def, struct rtx_iv *iv)
! {
! struct ref *adef;
! adef = df_find_def (df, insn, def);
! if (!adef)
! return false;
!
! return iv_analyze_def (adef, iv);
}
! /* Checks whether definition of register REG in INSN is a basic induction
variable. IV analysis must have been initialized (via a call to
iv_analysis_loop_init) for this function to produce a result. */
*************** bool
*** 1181,1194 ****
biv_p (rtx insn, rtx reg)
{
struct rtx_iv iv;
! if (!REG_P (reg))
return false;
! if (last_def[REGNO (reg)] != insn)
return false;
! return iv_analyze_biv (reg, &iv);
}
/* Calculates value of IV at ITERATION-th iteration. */
--- 1193,1214 ----
biv_p (rtx insn, rtx reg)
{
struct rtx_iv iv;
+ struct ref *def, *last_def;
! if (!simple_reg_p (reg))
return false;
! def = df_find_def (df, insn, reg);
! gcc_assert (def != NULL);
! if (!latch_dominating_def (reg, &last_def))
! return false;
! if (last_def != def)
return false;
! if (!iv_analyze_biv (reg, &iv))
! return false;
!
! return iv.step != const0_rtx;
}
/* Calculates value of IV at ITERATION-th iteration. */
*************** get_iv_value (struct rtx_iv *iv, rtx ite
*** 1230,1250 ****
void
iv_analysis_done (void)
{
! max_insn_no = 0;
! max_reg_no = 0;
! if (insn_info)
! {
! free (insn_info);
! insn_info = NULL;
! }
! if (last_def)
! {
! free (last_def);
! last_def = NULL;
! }
! if (bivs)
{
! free (bivs);
bivs = NULL;
}
}
--- 1250,1261 ----
void
iv_analysis_done (void)
{
! if (df)
{
! clear_iv_info ();
! df_finish (df);
! df = NULL;
! htab_delete (bivs);
bivs = NULL;
}
}
*************** static void
*** 1996,2002 ****
iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
struct niter_desc *desc)
{
! rtx op0, op1, delta, step, bound, may_xform, def_insn, tmp, tmp0, tmp1;
struct rtx_iv iv0, iv1, tmp_iv;
rtx assumption, may_not_xform;
enum rtx_code cond;
--- 2007,2013 ----
iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
struct niter_desc *desc)
{
! rtx op0, op1, delta, step, bound, may_xform, tmp, tmp0, tmp1;
struct rtx_iv iv0, iv1, tmp_iv;
rtx assumption, may_not_xform;
enum rtx_code cond;
*************** iv_number_of_iterations (struct loop *lo
*** 2038,2052 ****
goto fail;
op0 = XEXP (condition, 0);
! def_insn = iv_get_reaching_def (insn, op0);
! if (!iv_analyze (def_insn, op0, &iv0))
goto fail;
if (iv0.extend_mode == VOIDmode)
iv0.mode = iv0.extend_mode = mode;
op1 = XEXP (condition, 1);
! def_insn = iv_get_reaching_def (insn, op1);
! if (!iv_analyze (def_insn, op1, &iv1))
goto fail;
if (iv1.extend_mode == VOIDmode)
iv1.mode = iv1.extend_mode = mode;
--- 2049,2061 ----
goto fail;
op0 = XEXP (condition, 0);
! if (!iv_analyze (insn, op0, &iv0))
goto fail;
if (iv0.extend_mode == VOIDmode)
iv0.mode = iv0.extend_mode = mode;
op1 = XEXP (condition, 1);
! if (!iv_analyze (insn, op1, &iv1))
goto fail;
if (iv1.extend_mode == VOIDmode)
iv1.mode = iv1.extend_mode = mode;
Index: cfgloop.h
===================================================================
*** cfgloop.h (revision 109543)
--- cfgloop.h (working copy)
*************** struct rtx_iv
*** 352,360 ****
/* The mode the variable iterates in. */
enum machine_mode mode;
- /* Whether we have already filled the remaining fields. */
- unsigned analysed : 1;
-
/* Whether the first iteration needs to be handled specially. */
unsigned first_special : 1;
};
--- 352,357 ----
*************** struct niter_desc
*** 404,415 ****
};
extern void iv_analysis_loop_init (struct loop *);
- extern rtx iv_get_reaching_def (rtx, rtx);
extern bool iv_analyze (rtx, rtx, struct rtx_iv *);
extern rtx get_iv_value (struct rtx_iv *, rtx);
extern bool biv_p (rtx, rtx);
extern void find_simple_exit (struct loop *, 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);
--- 401,414 ----
};
extern void iv_analysis_loop_init (struct loop *);
extern bool iv_analyze (rtx, rtx, struct rtx_iv *);
+ extern bool iv_analyze_result (rtx, rtx, struct rtx_iv *);
+ extern bool iv_analyze_expr (rtx, rtx, enum machine_mode, struct rtx_iv *);
extern rtx get_iv_value (struct rtx_iv *, rtx);
extern bool biv_p (rtx, rtx);
extern void find_simple_exit (struct loop *, struct niter_desc *);
extern void iv_analysis_done (void);
+ extern struct df *iv_current_loop_df (void);
extern struct niter_desc *get_simple_loop_desc (struct loop *loop);
extern void free_simple_loop_desc (struct loop *loop);
Index: Makefile.in
===================================================================
*** Makefile.in (revision 109543)
--- Makefile.in (working copy)
*************** struct-equiv.o : struct-equiv.c $(CONFIG
*** 2372,2378 ****
$(REGS_H) $(EMIT_RTL_H)
loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H) \
! output.h intl.h
loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h \
$(TM_H) $(TM_P_H) function.h $(FLAGS_H) $(DF_H) $(OBSTACK_H) output.h \
--- 2372,2378 ----
$(REGS_H) $(EMIT_RTL_H)
loop-iv.o : loop-iv.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(BASIC_BLOCK_H) \
hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H) \
! output.h intl.h $(DF_H) $(HASHTAB_H)
loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(EXPR_H) coretypes.h \
$(TM_H) $(TM_P_H) function.h $(FLAGS_H) $(DF_H) $(OBSTACK_H) output.h \
*************** loop-unswitch.o : loop-unswitch.c $(CONF
*** 2388,2394 ****
output.h $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H)
loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
! output.h $(EXPR_H) coretypes.h $(TM_H) $(HASHTAB_H) $(RECOG_H) $(VARRAY_H) \
$(OBSTACK_H)
dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) toplev.h
--- 2388,2394 ----
output.h $(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H)
loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
! output.h $(EXPR_H) coretypes.h $(TM_H) $(HASHTAB_H) $(RECOG_H) \
$(OBSTACK_H)
dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
hard-reg-set.h $(BASIC_BLOCK_H) et-forest.h $(OBSTACK_H) toplev.h
More information about the Gcc-patches
mailing list