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
This commit is contained in:
parent
fb334765e2
commit
18caa34eb2
@ -1,3 +1,12 @@
|
||||
2016-05-09 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2016-05-09 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
|
||||
|
||||
* config/arm/arm.md (probe_stack): Add modes to set source
|
||||
|
@ -1,3 +1,13 @@
|
||||
2016-05-09 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2016-05-09 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR fortran/70937
|
||||
|
22
gcc/testsuite/gcc.dg/tree-ssa/ifc-10.c
Normal file
22
gcc/testsuite/gcc.dg/tree-ssa/ifc-10.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Ofast -fdump-tree-ifcvt-stats" } */
|
||||
/* { dg-require-visibility "" } */
|
||||
|
||||
int b[256] = {0}, y;
|
||||
void bar (int *);
|
||||
int foo (int x, int n)
|
||||
{
|
||||
int i;
|
||||
int a[128];
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
a[i] = i;
|
||||
if (x > i)
|
||||
b[i] = y;
|
||||
}
|
||||
bar (a);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
|
20
gcc/testsuite/gcc.dg/tree-ssa/ifc-11.c
Normal file
20
gcc/testsuite/gcc.dg/tree-ssa/ifc-11.c
Normal file
@ -0,0 +1,20 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Ofast -fdump-tree-ifcvt-stats" } */
|
||||
/* { dg-require-visibility "" } */
|
||||
|
||||
int a[1024] = {0.0};
|
||||
int b[1024] = {0.0};
|
||||
int c[1024] = {0.0};
|
||||
int foo (float *x)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < 1024; i++)
|
||||
{
|
||||
c[i] = (x[i] > 0.0) ? a[i] : b[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
|
25
gcc/testsuite/gcc.dg/tree-ssa/ifc-12.c
Normal file
25
gcc/testsuite/gcc.dg/tree-ssa/ifc-12.c
Normal file
@ -0,0 +1,25 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Ofast -fdump-tree-ifcvt-stats" } */
|
||||
/* { dg-require-visibility "" } */
|
||||
|
||||
struct st
|
||||
{
|
||||
int a[1024];
|
||||
int b[1024];
|
||||
};
|
||||
|
||||
struct st s = {0};
|
||||
int foo (int x)
|
||||
{
|
||||
int i;
|
||||
struct st *p = &s;
|
||||
|
||||
for (i = 0; i < 1024; i++)
|
||||
{
|
||||
if (x > i)
|
||||
p->a[i] = p->b[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
|
22
gcc/testsuite/gcc.dg/tree-ssa/ifc-9.c
Normal file
22
gcc/testsuite/gcc.dg/tree-ssa/ifc-9.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-Ofast -fdump-tree-ifcvt-stats" } */
|
||||
/* { dg-require-visibility "" } */
|
||||
|
||||
extern int b[256], y;
|
||||
void bar (int *, int);
|
||||
int foo (int x, int n)
|
||||
{
|
||||
int i;
|
||||
int a[128];
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
a[i] = i;
|
||||
if (x > i)
|
||||
y = b[i];
|
||||
}
|
||||
bar (a, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
|
@ -38,4 +38,4 @@ int main()
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
|
||||
|
@ -123,5 +123,5 @@ int main (void)
|
||||
return main1 ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail *-*-* } } } */
|
||||
/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */
|
||||
|
@ -15,4 +15,4 @@ void foo (int n)
|
||||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Move stmt to created bb" 6 "vect" { target { i?86-*-* x86_64-*-* } } } } */
|
||||
/* { dg-final { scan-tree-dump-times "Move stmt to created bb" 4 "vect" { target { i?86-*-* x86_64-*-* } } } } */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user