summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authordavidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-28 05:08:24 +0000
committerdavidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-28 05:08:24 +0000
commita7ae69c98e103894686adad9d2f7ab004798b56f (patch)
tree4aac93f0b4fa63b70f418feead28f5de88f862ef /gcc
parent574b6863d712ba3dc22f08fe8d6fa1d7e58ca8d0 (diff)
downloadgcc-a7ae69c98e103894686adad9d2f7ab004798b56f.tar.gz
Fix to expose more LIM when creating mem_ref
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@162616 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/tree-flow.h4
-rw-r--r--gcc/tree-ssa-address.c53
-rw-r--r--gcc/tree-ssa-loop-ivopts.c7
4 files changed, 58 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 438f2db9df2..1d0b5356c66 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2010-07-27 Xinliang David Li <davidxl@google.com>
+ * tree-flow.h (create_mem_ref): Add one new parameter.
+ * tree-ssa-address.c (create_mem_ref): New parameter.
+ (addr_to_parts): Ditto.
+ (move_variant_to_index): New function.
+ * tree-ssa-loop-ivopts.c (rewrite_use_address): Pass new argument.
+
2010-07-27 Bernd Schmidt <bernds@codesourcery.com>
* rtl.def (DEBUG_INSN, INSN, JUMP_INSN, CALL_INSN, NOTE): Swap operands
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 6209a844df3..abbf9172a1c 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -832,8 +832,8 @@ struct mem_address
};
struct affine_tree_combination;
-tree create_mem_ref (gimple_stmt_iterator *, tree, tree,
- struct affine_tree_combination *, tree, bool);
+tree create_mem_ref (gimple_stmt_iterator *, tree,
+ struct affine_tree_combination *, tree, tree, tree, bool);
rtx addr_for_mem_ref (struct mem_address *, addr_space_t, bool);
void get_address_description (tree, struct mem_address *);
tree maybe_fold_tmr (tree);
diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c
index f49bf14caea..474a7986a23 100644
--- a/gcc/tree-ssa-address.c
+++ b/gcc/tree-ssa-address.c
@@ -470,6 +470,31 @@ move_pointer_to_base (struct mem_address *parts, aff_tree *addr)
aff_combination_remove_elt (addr, i);
}
+/* Moves the loop variant part V in linear address ADDR to be the index
+ of PARTS. */
+
+static void
+move_variant_to_index (struct mem_address *parts, aff_tree *addr, tree v)
+{
+ unsigned i;
+ tree val = NULL_TREE;
+
+ gcc_assert (!parts->index);
+ for (i = 0; i < addr->n; i++)
+ {
+ val = addr->elts[i].val;
+ if (operand_equal_p (val, v, 0))
+ break;
+ }
+
+ if (i == addr->n)
+ return;
+
+ parts->index = fold_convert (sizetype, val);
+ parts->step = double_int_to_tree (sizetype, addr->elts[i].coef);
+ aff_combination_remove_elt (addr, i);
+}
+
/* Adds ELT to PARTS. */
static void
@@ -573,7 +598,8 @@ most_expensive_mult_to_index (tree type, struct mem_address *parts,
/* Splits address ADDR for a memory access of type TYPE into PARTS.
If BASE_HINT is non-NULL, it specifies an SSA name to be used
- preferentially as base of the reference.
+ preferentially as base of the reference, and IV_CAND is the selected
+ iv candidate used in ADDR.
TODO -- be more clever about the distribution of the elements of ADDR
to PARTS. Some architectures do not support anything but single
@@ -583,8 +609,9 @@ most_expensive_mult_to_index (tree type, struct mem_address *parts,
addressing modes is useless. */
static void
-addr_to_parts (tree type, aff_tree *addr, tree base_hint,
- struct mem_address *parts, bool speed)
+addr_to_parts (tree type, aff_tree *addr, tree iv_cand,
+ tree base_hint, struct mem_address *parts,
+ bool speed)
{
tree part;
unsigned i;
@@ -602,9 +629,17 @@ addr_to_parts (tree type, aff_tree *addr, tree base_hint,
/* Try to find a symbol. */
move_fixed_address_to_symbol (parts, addr);
+ /* No need to do address parts reassociation if the number of parts
+ is <= 2 -- in that case, no loop invariant code motion can be
+ exposed. */
+
+ if (!base_hint && (addr->n > 2))
+ move_variant_to_index (parts, addr, iv_cand);
+
/* First move the most expensive feasible multiplication
to index. */
- most_expensive_mult_to_index (type, parts, addr, speed);
+ if (!parts->index)
+ most_expensive_mult_to_index (type, parts, addr, speed);
/* Try to find a base of the reference. Since at the moment
there is no reliable way how to distinguish between pointer and its
@@ -644,17 +679,19 @@ gimplify_mem_ref_parts (gimple_stmt_iterator *gsi, struct mem_address *parts)
/* Creates and returns a TARGET_MEM_REF for address ADDR. If necessary
computations are emitted in front of GSI. TYPE is the mode
- of created memory reference. */
+ of created memory reference. IV_CAND is the selected iv candidate in ADDR,
+ and BASE_HINT is non NULL if IV_CAND comes from a base address
+ object. */
tree
-create_mem_ref (gimple_stmt_iterator *gsi, tree type, tree alias_ptr_type,
- aff_tree *addr, tree base_hint, bool speed)
+create_mem_ref (gimple_stmt_iterator *gsi, tree type, aff_tree *addr,
+ tree alias_ptr_type, tree iv_cand, tree base_hint, bool speed)
{
tree mem_ref, tmp;
tree atype;
struct mem_address parts;
- addr_to_parts (type, addr, base_hint, &parts, speed);
+ addr_to_parts (type, addr, iv_cand, base_hint, &parts, speed);
gimplify_mem_ref_parts (gsi, &parts);
mem_ref = create_mem_ref_raw (type, alias_ptr_type, &parts);
if (mem_ref)
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index ae299886064..478a0190250 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -5745,7 +5745,7 @@ rewrite_use_address (struct ivopts_data *data,
aff_tree aff;
gimple_stmt_iterator bsi = gsi_for_stmt (use->stmt);
tree base_hint = NULL_TREE;
- tree ref;
+ tree ref, iv;
bool ok;
adjust_iv_update_pos (cand, use);
@@ -5767,9 +5767,10 @@ rewrite_use_address (struct ivopts_data *data,
if (cand->iv->base_object)
base_hint = var_at_stmt (data->current_loop, cand, use->stmt);
- ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p),
+ iv = var_at_stmt (data->current_loop, cand, use->stmt);
+ ref = create_mem_ref (&bsi, TREE_TYPE (*use->op_p), &aff,
reference_alias_ptr_type (*use->op_p),
- &aff, base_hint, data->speed);
+ iv, base_hint, data->speed);
copy_ref_info (ref, *use->op_p);
*use->op_p = ref;
}