diff options
author | Christian Borntraeger <borntraeger@de.ibm.com> | 2010-05-19 10:36:40 +0000 |
---|---|---|
committer | Andreas Krebbel <krebbel@gcc.gnu.org> | 2010-05-19 10:36:40 +0000 |
commit | 81f3232690f1ad1fea044d6e6b60930acd7f16e7 (patch) | |
tree | c0ee374b336bbee90595123d3e694375b657303f /gcc | |
parent | 8abd2cbee209b2db1252d82bd3fb3908489df71f (diff) | |
download | gcc-81f3232690f1ad1fea044d6e6b60930acd7f16e7.zip gcc-81f3232690f1ad1fea044d6e6b60930acd7f16e7.tar.gz gcc-81f3232690f1ad1fea044d6e6b60930acd7f16e7.tar.bz2 |
tree-ssa-loop-prefetch.c (mem_ref_group, ar_data): Change step to tree.
2010-05-19 Christian Borntraeger <borntraeger@de.ibm.com>
* tree-ssa-loop-prefetch.c (mem_ref_group, ar_data): Change step
to tree.
(dump_mem_ref): Adopt debug code to handle a tree as step. This
also checks for a constant int vs. non-constant but
loop-invariant steps.
(find_or_create_group): Change the sort algorithm to only consider
steps that are constant ints.
(idx_analyze_ref): Adopt code to handle a tree instead of a
HOST_WIDE_INT for step.
(gather_memory_references_ref): Handle tree instead of int and be
prepared to see a NULL_TREE.
(prune_ref_by_self_reuse, prune_ref_by_group_reuse): Do not prune
prefetches if the step cannot be calculated at compile time.
(issue_prefetch_ref): Issue prefetches for non-constant but
loop-invariant steps.
From-SVN: r159557
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-prefetch.c | 107 |
2 files changed, 93 insertions, 32 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5af3ae5..30ed7cb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2010-05-19 Christian Borntraeger <borntraeger@de.ibm.com> + + * tree-ssa-loop-prefetch.c (mem_ref_group, ar_data): Change step + to tree. + (dump_mem_ref): Adopt debug code to handle a tree as step. This + also checks for a constant int vs. non-constant but + loop-invariant steps. + (find_or_create_group): Change the sort algorithm to only consider + steps that are constant ints. + (idx_analyze_ref): Adopt code to handle a tree instead of a + HOST_WIDE_INT for step. + (gather_memory_references_ref): Handle tree instead of int and be + prepared to see a NULL_TREE. + (prune_ref_by_self_reuse, prune_ref_by_group_reuse): Do not prune + prefetches if the step cannot be calculated at compile time. + (issue_prefetch_ref): Issue prefetches for non-constant but + loop-invariant steps. + 2010-05-18 Nathan Froyd <froydnj@codesourcery.com> Revert: diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index 4d85f54..becde89 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -216,7 +216,7 @@ along with GCC; see the file COPYING3. If not see struct mem_ref_group { tree base; /* Base of the reference. */ - HOST_WIDE_INT step; /* Step of the reference. */ + tree step; /* Step of the reference. */ struct mem_ref *refs; /* References in the group. */ struct mem_ref_group *next; /* Next group of references. */ }; @@ -271,7 +271,10 @@ dump_mem_ref (FILE *file, struct mem_ref *ref) fprintf (file, " group %p (base ", (void *) ref->group); print_generic_expr (file, ref->group->base, TDF_SLIM); fprintf (file, ", step "); - fprintf (file, HOST_WIDE_INT_PRINT_DEC, ref->group->step); + if (cst_and_fits_in_hwi (ref->group->step)) + fprintf (file, HOST_WIDE_INT_PRINT_DEC, int_cst_value (ref->group->step)); + else + print_generic_expr (file, ref->group->step, TDF_TREE); fprintf (file, ")\n"); fprintf (file, " delta "); @@ -287,19 +290,20 @@ dump_mem_ref (FILE *file, struct mem_ref *ref) exist. */ static struct mem_ref_group * -find_or_create_group (struct mem_ref_group **groups, tree base, - HOST_WIDE_INT step) +find_or_create_group (struct mem_ref_group **groups, tree base, tree step) { struct mem_ref_group *group; for (; *groups; groups = &(*groups)->next) { - if ((*groups)->step == step + if (operand_equal_p ((*groups)->step, step, 0) && operand_equal_p ((*groups)->base, base, 0)) return *groups; - /* Keep the list of groups sorted by decreasing step. */ - if ((*groups)->step < step) + /* If step is an integer constant, keep the list of groups sorted + by decreasing step. */ + if (cst_and_fits_in_hwi ((*groups)->step) && cst_and_fits_in_hwi (step) + && int_cst_value ((*groups)->step) < int_cst_value (step)) break; } @@ -384,7 +388,7 @@ struct ar_data { struct loop *loop; /* Loop of the reference. */ gimple stmt; /* Statement of the reference. */ - HOST_WIDE_INT *step; /* Step of the memory reference. */ + tree *step; /* Step of the memory reference. */ HOST_WIDE_INT *delta; /* Offset of the memory reference. */ }; @@ -396,7 +400,7 @@ idx_analyze_ref (tree base, tree *index, void *data) { struct ar_data *ar_data = (struct ar_data *) data; tree ibase, step, stepsize; - HOST_WIDE_INT istep, idelta = 0, imult = 1; + HOST_WIDE_INT idelta = 0, imult = 1; affine_iv iv; if (TREE_CODE (base) == MISALIGNED_INDIRECT_REF @@ -404,15 +408,11 @@ idx_analyze_ref (tree base, tree *index, void *data) return false; if (!simple_iv (ar_data->loop, loop_containing_stmt (ar_data->stmt), - *index, &iv, false)) + *index, &iv, true)) return false; ibase = iv.base; step = iv.step; - if (!cst_and_fits_in_hwi (step)) - return false; - istep = int_cst_value (step); - if (TREE_CODE (ibase) == POINTER_PLUS_EXPR && cst_and_fits_in_hwi (TREE_OPERAND (ibase, 1))) { @@ -425,6 +425,12 @@ idx_analyze_ref (tree base, tree *index, void *data) ibase = build_int_cst (TREE_TYPE (ibase), 0); } + if (*ar_data->step == NULL_TREE) + *ar_data->step = step; + else + *ar_data->step = fold_build2 (PLUS_EXPR, sizetype, + fold_convert (sizetype, *ar_data->step), + fold_convert (sizetype, step)); if (TREE_CODE (base) == ARRAY_REF) { stepsize = array_ref_element_size (base); @@ -432,11 +438,12 @@ idx_analyze_ref (tree base, tree *index, void *data) return false; imult = int_cst_value (stepsize); - istep *= imult; + *ar_data->step = fold_build2 (MULT_EXPR, sizetype, + fold_convert (sizetype, *ar_data->step), + fold_convert (sizetype, step)); idelta *= imult; } - *ar_data->step += istep; *ar_data->delta += idelta; *index = ibase; @@ -450,7 +457,7 @@ idx_analyze_ref (tree base, tree *index, void *data) static bool analyze_ref (struct loop *loop, tree *ref_p, tree *base, - HOST_WIDE_INT *step, HOST_WIDE_INT *delta, + tree *step, HOST_WIDE_INT *delta, gimple stmt) { struct ar_data ar_data; @@ -458,7 +465,7 @@ analyze_ref (struct loop *loop, tree *ref_p, tree *base, HOST_WIDE_INT bit_offset; tree ref = *ref_p; - *step = 0; + *step = NULL_TREE; *delta = 0; /* First strip off the component references. Ignore bitfields. */ @@ -493,8 +500,8 @@ static bool gather_memory_references_ref (struct loop *loop, struct mem_ref_group **refs, tree ref, bool write_p, gimple stmt) { - tree base; - HOST_WIDE_INT step, delta; + tree base, step; + HOST_WIDE_INT delta; struct mem_ref_group *agrp; if (get_base_address (ref) == NULL) @@ -502,6 +509,9 @@ gather_memory_references_ref (struct loop *loop, struct mem_ref_group **refs, if (!analyze_ref (loop, &ref, &base, &step, &delta, stmt)) return false; + /* If analyze_ref fails the default is a NULL_TREE. We can stop here. */ + if (step == NULL_TREE) + return false; /* Now we know that REF = &BASE + STEP * iter + DELTA, where DELTA and STEP are integer constants. */ @@ -576,8 +586,16 @@ gather_memory_references (struct loop *loop, bool *no_other_refs, unsigned *ref_ static void prune_ref_by_self_reuse (struct mem_ref *ref) { - HOST_WIDE_INT step = ref->group->step; - bool backward = step < 0; + HOST_WIDE_INT step; + bool backward; + + /* If the step size is non constant, we cannot calculate prefetch_mod. */ + if (!cst_and_fits_in_hwi (ref->group->step)) + return; + + step = int_cst_value (ref->group->step); + + backward = step < 0; if (step == 0) { @@ -661,8 +679,8 @@ static void prune_ref_by_group_reuse (struct mem_ref *ref, struct mem_ref *by, bool by_is_before) { - HOST_WIDE_INT step = ref->group->step; - bool backward = step < 0; + HOST_WIDE_INT step; + bool backward; HOST_WIDE_INT delta_r = ref->delta, delta_b = by->delta; HOST_WIDE_INT delta = delta_b - delta_r; HOST_WIDE_INT hit_from; @@ -673,6 +691,16 @@ prune_ref_by_group_reuse (struct mem_ref *ref, struct mem_ref *by, tree ref_type; int align_unit; + /* If the step is non constant we cannot calculate prefetch_before. */ + if (!cst_and_fits_in_hwi (ref->group->step)) { + return; + } + + step = int_cst_value (ref->group->step); + + backward = step < 0; + + if (delta == 0) { /* If the references has the same address, only prefetch the @@ -986,7 +1014,7 @@ static void issue_prefetch_ref (struct mem_ref *ref, unsigned unroll_factor, unsigned ahead) { HOST_WIDE_INT delta; - tree addr, addr_base, write_p, local; + tree addr, addr_base, write_p, local, forward; gimple prefetch; gimple_stmt_iterator bsi; unsigned n_prefetches, ap; @@ -1009,13 +1037,28 @@ issue_prefetch_ref (struct mem_ref *ref, unsigned unroll_factor, unsigned ahead) for (ap = 0; ap < n_prefetches; ap++) { - /* Determine the address to prefetch. */ - delta = (ahead + ap * ref->prefetch_mod) * ref->group->step; - addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, - addr_base, size_int (delta)); - addr = force_gimple_operand_gsi (&bsi, unshare_expr (addr), true, NULL, - true, GSI_SAME_STMT); - + if (cst_and_fits_in_hwi (ref->group->step)) + { + /* Determine the address to prefetch. */ + delta = (ahead + ap * ref->prefetch_mod) * + int_cst_value (ref->group->step); + addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, + addr_base, size_int (delta)); + addr = force_gimple_operand_gsi (&bsi, unshare_expr (addr), true, NULL, + true, GSI_SAME_STMT); + } + else + { + /* The step size is non-constant but loop-invariant. We use the + heuristic to simply prefetch ahead iterations ahead. */ + forward = fold_build2 (MULT_EXPR, sizetype, + fold_convert (sizetype, ref->group->step), + fold_convert (sizetype, size_int (ahead))); + addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, addr_base, + forward); + addr = force_gimple_operand_gsi (&bsi, unshare_expr (addr), true, + NULL, true, GSI_SAME_STMT); + } /* Create the prefetch instruction. */ prefetch = gimple_build_call (built_in_decls[BUILT_IN_PREFETCH], 3, addr, write_p, local); |