diff options
author | davidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-07-28 05:08:24 +0000 |
---|---|---|
committer | davidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-07-28 05:08:24 +0000 |
commit | a7ae69c98e103894686adad9d2f7ab004798b56f (patch) | |
tree | 4aac93f0b4fa63b70f418feead28f5de88f862ef /gcc | |
parent | 574b6863d712ba3dc22f08fe8d6fa1d7e58ca8d0 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/tree-flow.h | 4 | ||||
-rw-r--r-- | gcc/tree-ssa-address.c | 53 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivopts.c | 7 |
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; } |