/* RTL-level loop invariant motion.
- Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+ Free Software Foundation, Inc.
This file is part of GCC.
#include "df.h"
#include "hashtab.h"
#include "except.h"
+#include "params.h"
/* The data stored for the loop. */
{
rtx *pos; /* Position of the use. */
rtx insn; /* The insn in that the use occurs. */
-
+ unsigned addr_use_p; /* Whether the use occurs in an address. */
struct use *next; /* Next use in the list. */
};
struct use *uses; /* The list of uses that are uniquely reached
by it. */
unsigned n_uses; /* Number of such uses. */
+ unsigned n_addr_uses; /* Number of uses in addresses. */
unsigned invno; /* The corresponding invariant. */
};
/* Whether to move the invariant. */
bool move;
+ /* Whether the invariant is cheap when used as an address. */
+ bool cheap_address;
+
/* Cost of the invariant. */
unsigned cost;
/* If the set is simple, usually by moving it we move the whole store out of
the loop. Otherwise we save only cost of the computation. */
if (def)
- inv->cost = rtx_cost (set, SET, speed);
+ {
+ inv->cost = rtx_cost (set, SET, speed);
+ inv->cheap_address = address_cost (SET_SRC (set), word_mode,
+ speed) < COSTS_N_INSNS (1);
+ }
else
- inv->cost = rtx_cost (SET_SRC (set), SET, speed);
+ {
+ inv->cost = rtx_cost (SET_SRC (set), SET, speed);
+ inv->cheap_address = false;
+ }
inv->move = false;
inv->reg = NULL_RTX;
/* Record USE at DEF. */
static void
-record_use (struct def *def, rtx *use, rtx insn)
+record_use (struct def *def, df_ref use)
{
struct use *u = XNEW (struct use);
- gcc_assert (REG_P (*use));
-
- u->pos = use;
- u->insn = insn;
+ u->pos = DF_REF_REAL_LOC (use);
+ u->insn = DF_REF_INSN (use);
+ u->addr_use_p = (DF_REF_TYPE (use) == DF_REF_REG_MEM_LOAD
+ || DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE);
u->next = def->uses;
def->uses = u;
def->n_uses++;
+ if (u->addr_use_p)
+ def->n_addr_uses++;
}
/* Finds the invariants USE depends on and store them to the DEPENDS_ON
return;
/* We cannot make trapping insn executed, unless it was executed before. */
- if (may_trap_after_code_motion_p (PATTERN (insn)) && !always_reached)
+ if (may_trap_or_fault_p (PATTERN (insn)) && !always_reached)
return;
depends_on = BITMAP_ALLOC (NULL);
df_ref use = *use_rec;
inv = invariant_for_use (use);
if (inv)
- record_use (inv->def, DF_REF_REAL_LOC (use), DF_REF_INSN (use));
+ record_use (inv->def, use);
}
for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++)
{
df_ref use = *use_rec;
inv = invariant_for_use (use);
if (inv)
- record_use (inv->def, DF_REF_REAL_LOC (use), DF_REF_INSN (use));
+ record_use (inv->def, use);
}
}
inv->stamp = actual_stamp;
(*regs_needed)++;
- (*comp_cost) += inv->cost;
+ if (!inv->cheap_address
+ || inv->def->n_addr_uses < inv->def->n_uses)
+ (*comp_cost) += inv->cost;
#ifdef STACK_REGS
{
/* Process the loops, innermost first. */
FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST)
{
- move_single_loop_invariants (loop);
+ /* move_single_loop_invariants for very large loops
+ is time consuming and might need a lot of memory. */
+ if (loop->num_nodes <= (unsigned) LOOP_INVARIANT_MAX_BBS_IN_LOOP)
+ move_single_loop_invariants (loop);
}
FOR_EACH_LOOP (li, loop, 0)