diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2009-05-08 06:51:12 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gcc.gnu.org> | 2009-05-08 06:51:12 +0000 |
commit | 1bfdbb292206491f4874a8b3dfa2dbb2d0c833e3 (patch) | |
tree | 25983327877f8281329815e9a674e6f487f23d30 /gcc/loop-invariant.c | |
parent | 7e79080ad4a95295a120444587af4002cf0078de (diff) | |
download | gcc-1bfdbb292206491f4874a8b3dfa2dbb2d0c833e3.zip gcc-1bfdbb292206491f4874a8b3dfa2dbb2d0c833e3.tar.gz gcc-1bfdbb292206491f4874a8b3dfa2dbb2d0c833e3.tar.bz2 |
re PR rtl-optimization/33928 (30% performance slowdown in floating-point code caused by r118475)
2009-05-08 Paolo Bonzini <bonzini@gnu.org>
PR rtl-optimization/33928
* loop-invariant.c (struct use): Add addr_use_p.
(struct def): Add n_addr_uses.
(struct invariant): Add cheap_address.
(create_new_invariant): Set cheap_address.
(record_use): Accept df_ref. Set addr_use_p and update n_addr_uses.
(record_uses): Pass df_ref to record_use.
(get_inv_cost): Do not add inv->cost to comp_cost for cheap addresses used
only as such.
From-SVN: r147270
Diffstat (limited to 'gcc/loop-invariant.c')
-rw-r--r-- | gcc/loop-invariant.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index 82e1829..3d718b1 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -71,7 +71,7 @@ struct use { 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. */ }; @@ -82,6 +82,7 @@ struct def 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. */ }; @@ -111,6 +112,9 @@ struct 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; @@ -679,9 +683,16 @@ create_new_invariant (struct def *def, rtx insn, bitmap depends_on, /* 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; @@ -708,17 +719,19 @@ create_new_invariant (struct def *def, rtx insn, bitmap depends_on, /* 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 @@ -865,14 +878,14 @@ record_uses (rtx insn) 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); } } @@ -992,7 +1005,9 @@ get_inv_cost (struct invariant *inv, int *comp_cost, unsigned *regs_needed) 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 { |