aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBin Cheng <bin.cheng@arm.com>2015-10-27 05:26:27 +0000
committerBin Cheng <amker@gcc.gnu.org>2015-10-27 05:26:27 +0000
commit5b92e1895eea1ea9a7eb69553af8d173bd62e134 (patch)
tree10a6570c4bb4a7278ecda3f038b6b918f6ce1ac7
parentbda9c2451e766ec289ce746e803d863832b23f51 (diff)
downloadgcc-5b92e1895eea1ea9a7eb69553af8d173bd62e134.zip
gcc-5b92e1895eea1ea9a7eb69553af8d173bd62e134.tar.gz
gcc-5b92e1895eea1ea9a7eb69553af8d173bd62e134.tar.bz2
loop-invariant.c (struct def): New field can_prop_to_addr_uses.
* loop-invariant.c (struct def): New field can_prop_to_addr_uses. (inv_can_prop_to_addr_use): New function. (record_use): Call can_prop_to_addr_uses, set the new field. (get_inv_cost): Count cost if inv can't be propagated into its address uses. From-SVN: r229402
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/loop-invariant.c45
2 files changed, 51 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9eb9f6c..0a2e2ad 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2015-10-27 Bin Cheng <bin.cheng@arm.com>
+
+ * loop-invariant.c (struct def): New field can_prop_to_addr_uses.
+ (inv_can_prop_to_addr_use): New function.
+ (record_use): Call can_prop_to_addr_uses, set the new field.
+ (get_inv_cost): Count cost if inv can't be propagated into its
+ address uses.
+
2015-10-26 Doug Evans <dje@google.com>
* config/linux.h (INCLUDE_DEFAULTS): Add INCLUDE_DEFAULTS_MUSL_LOCAL.
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 52c8ae8..7ac38c6 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -99,6 +99,8 @@ struct def
unsigned n_uses; /* Number of such uses. */
unsigned n_addr_uses; /* Number of uses in addresses. */
unsigned invno; /* The corresponding invariant. */
+ bool can_prop_to_addr_uses; /* True if the corresponding inv can be
+ propagated into its address uses. */
};
/* The data stored for each invariant. */
@@ -762,6 +764,34 @@ create_new_invariant (struct def *def, rtx_insn *insn, bitmap depends_on,
return inv;
}
+/* Given invariant DEF and its address USE, check if the corresponding
+ invariant expr can be propagated into the use or not. */
+
+static bool
+inv_can_prop_to_addr_use (struct def *def, df_ref use)
+{
+ struct invariant *inv;
+ rtx *pos = DF_REF_REAL_LOC (use), def_set;
+ rtx_insn *use_insn = DF_REF_INSN (use);
+ rtx_insn *def_insn;
+ bool ok;
+
+ inv = invariants[def->invno];
+ /* No need to check if address expression is expensive. */
+ if (!inv->cheap_address)
+ return false;
+
+ def_insn = inv->insn;
+ def_set = single_set (def_insn);
+ if (!def_set)
+ return false;
+
+ validate_unshare_change (use_insn, pos, SET_SRC (def_set), true);
+ ok = verify_changes (0);
+ cancel_changes (0);
+ return ok;
+}
+
/* Record USE at DEF. */
static void
@@ -777,7 +807,16 @@ record_use (struct def *def, df_ref use)
def->uses = u;
def->n_uses++;
if (u->addr_use_p)
- def->n_addr_uses++;
+ {
+ /* Initialize propagation information if this is the first addr
+ use of the inv def. */
+ if (def->n_addr_uses == 0)
+ def->can_prop_to_addr_uses = true;
+
+ def->n_addr_uses++;
+ if (def->can_prop_to_addr_uses && !inv_can_prop_to_addr_use (def, use))
+ def->can_prop_to_addr_uses = false;
+ }
}
/* Finds the invariants USE depends on and store them to the DEPENDS_ON
@@ -1158,7 +1197,9 @@ get_inv_cost (struct invariant *inv, int *comp_cost, unsigned *regs_needed,
if (!inv->cheap_address
|| inv->def->n_uses == 0
- || inv->def->n_addr_uses < inv->def->n_uses)
+ || inv->def->n_addr_uses < inv->def->n_uses
+ /* Count cost if the inv can't be propagated into address uses. */
+ || !inv->def->can_prop_to_addr_uses)
(*comp_cost) += inv->cost * inv->eqno;
#ifdef STACK_REGS