diff options
author | Bin Cheng <bin.cheng@arm.com> | 2016-05-09 11:44:03 +0000 |
---|---|---|
committer | Bin Cheng <amker@gcc.gnu.org> | 2016-05-09 11:44:03 +0000 |
commit | 18caa34eb299b8ea583088ce4bbf32cdc37676ff (patch) | |
tree | 0bc305c854d198927d3503e42a9cc89202fc8b3f /gcc/tree-if-conv.c | |
parent | fb334765e2ab959fcf3630e3c4a31ba1cc01a0f2 (diff) | |
download | gcc-18caa34eb299b8ea583088ce4bbf32cdc37676ff.zip gcc-18caa34eb299b8ea583088ce4bbf32cdc37676ff.tar.gz gcc-18caa34eb299b8ea583088ce4bbf32cdc37676ff.tar.bz2 |
tree-if-conv.c (tree-ssa-loop.h): Include header file.
* tree-if-conv.c (tree-ssa-loop.h): Include header file.
(tree-ssa-loop-niter.h): Ditto.
(idx_within_array_bound, ref_within_array_bound): New functions.
(ifcvt_memrefs_wont_trap): Check if array ref is within bound.
Factor out check on writable base object to ...
(base_object_writable): ... here.
gcc/testsuite/
* gcc.dg/tree-ssa/ifc-9.c: New test.
* gcc.dg/tree-ssa/ifc-10.c: New test.
* gcc.dg/tree-ssa/ifc-11.c: New test.
* gcc.dg/tree-ssa/ifc-12.c: New test.
* gcc.dg/vect/pr61194.c: Remove XFAIL.
* gcc.dg/vect/vect-23.c: Remove XFAIL.
* gcc.dg/vect/vect-mask-store-move-1.c: Revise test check.
From-SVN: r236026
Diffstat (limited to 'gcc/tree-if-conv.c')
-rw-r--r-- | gcc/tree-if-conv.c | 123 |
1 files changed, 112 insertions, 11 deletions
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index 3ad8e87..c38e21b 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -106,6 +106,8 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "tree-data-ref.h" #include "tree-scalar-evolution.h" +#include "tree-ssa-loop.h" +#include "tree-ssa-loop-niter.h" #include "tree-ssa-loop-ivopts.h" #include "tree-ssa-address.h" #include "dbgcnt.h" @@ -718,6 +720,105 @@ hash_memrefs_baserefs_and_store_DRs_read_written_info (data_reference_p a) } } +/* Return TRUE if can prove the index IDX of an array reference REF is + within array bound. Return false otherwise. */ + +static bool +idx_within_array_bound (tree ref, tree *idx, void *dta) +{ + bool overflow; + widest_int niter, valid_niter, delta, wi_step; + tree ev, init, step; + tree low, high; + struct loop *loop = (struct loop*) dta; + + /* Only support within-bound access for array references. */ + if (TREE_CODE (ref) != ARRAY_REF) + return false; + + /* For arrays at the end of the structure, we are not guaranteed that they + do not really extend over their declared size. However, for arrays of + size greater than one, this is unlikely to be intended. */ + if (array_at_struct_end_p (ref)) + return false; + + ev = analyze_scalar_evolution (loop, *idx); + ev = instantiate_parameters (loop, ev); + init = initial_condition (ev); + step = evolution_part_in_loop_num (ev, loop->num); + + if (!init || TREE_CODE (init) != INTEGER_CST + || (step && TREE_CODE (step) != INTEGER_CST)) + return false; + + low = array_ref_low_bound (ref); + high = array_ref_up_bound (ref); + + /* The case of nonconstant bounds could be handled, but it would be + complicated. */ + if (TREE_CODE (low) != INTEGER_CST + || !high || TREE_CODE (high) != INTEGER_CST) + return false; + + /* Check if the intial idx is within bound. */ + if (wi::to_widest (init) < wi::to_widest (low) + || wi::to_widest (init) > wi::to_widest (high)) + return false; + + /* The idx is always within bound. */ + if (!step || integer_zerop (step)) + return true; + + if (!max_loop_iterations (loop, &niter)) + return false; + + if (wi::to_widest (step) < 0) + { + delta = wi::to_widest (init) - wi::to_widest (low); + wi_step = -wi::to_widest (step); + } + else + { + delta = wi::to_widest (high) - wi::to_widest (init); + wi_step = wi::to_widest (step); + } + + valid_niter = wi::div_floor (delta, wi_step, SIGNED, &overflow); + /* The iteration space of idx is within array bound. */ + if (!overflow && niter <= valid_niter) + return true; + + return false; +} + +/* Return TRUE if ref is a within bound array reference. */ + +static bool +ref_within_array_bound (gimple *stmt, tree ref) +{ + struct loop *loop = loop_containing_stmt (stmt); + + gcc_assert (loop != NULL); + return for_each_index (&ref, idx_within_array_bound, loop); +} + + +/* Given a memory reference expression T, return TRUE if base object + it refers to is writable. The base object of a memory reference + is the main object being referenced, which is returned by function + get_base_address. */ + +static bool +base_object_writable (tree ref) +{ + tree base_tree = get_base_address (ref); + + return (base_tree + && DECL_P (base_tree) + && decl_binds_to_current_def_p (base_tree) + && !TREE_READONLY (base_tree)); +} + /* Return true when the memory references of STMT won't trap in the if-converted code. There are two things that we have to check for: @@ -765,8 +866,13 @@ ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs) if (DR_W_UNCONDITIONALLY (*master_dr)) return true; - /* If a is unconditionally accessed then ... */ - if (DR_RW_UNCONDITIONALLY (*master_dr)) + /* If a is unconditionally accessed then ... + + Even a is conditional access, we can treat it as an unconditional + one if it's an array reference and all its index are within array + bound. */ + if (DR_RW_UNCONDITIONALLY (*master_dr) + || ref_within_array_bound (stmt, DR_REF (a))) { /* an unconditional read won't trap. */ if (DR_IS_READ (a)) @@ -777,16 +883,11 @@ ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs) if (base_master_dr && DR_BASE_W_UNCONDITIONALLY (*base_master_dr)) return PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES); - else - { - /* or the base is know to be not readonly. */ - tree base_tree = get_base_address (DR_REF (a)); - if (DECL_P (base_tree) - && decl_binds_to_current_def_p (base_tree) - && ! TREE_READONLY (base_tree)) - return PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES); - } + /* or the base is known to be not readonly. */ + else if (base_object_writable (DR_REF (a))) + return PARAM_VALUE (PARAM_ALLOW_STORE_DATA_RACES); } + return false; } |