From: Robin Dapp <[email protected]>
This patch adds a nowrap_bound field to data_reference which denotes the
upper bound under which the DR is non wrapping.
dr_analyze_innermost, create_data_ref, and find_data_references_in_stmt
get an additional parameter to control whether or not a no-wrap bound
should be recorded.
gcc/ChangeLog:
* tree-data-ref.cc (dr_analyze_innermost): Add nowrap-bound param.
(dr_analyze_indices): Likewise.
(create_data_ref): Likewise.
(find_data_references_in_stmt): Add allow_assumptions param.
* tree-data-ref.h (struct data_reference): Add nowrap_bound.
(DR_NOWRAP_BOUND): New.
(dr_analyze_innermost): Pass on nowrap_bound.
(find_data_references_in_stmt): Likewise.
---
gcc/tree-data-ref.cc | 77 +++++++++++++++++++++++++++++++++-----------
gcc/tree-data-ref.h | 13 ++++++--
2 files changed, 68 insertions(+), 22 deletions(-)
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index 1114903784e..2d6ddb14a23 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -1129,11 +1129,15 @@ canonicalize_base_object_address (tree addr)
dummy outermost loop. In other cases perform loop analysis.
Return true if the analysis succeeded and store the results in DRB if so.
- BB analysis can only fail for bitfield or reversed-storage accesses. */
+ BB analysis can only fail for bitfield or reversed-storage accesses.
+
+ If NOWRAP_BOUND is nonzero, allow simple_iv to record no-wrap bounds.
+ Then, store non-trivial bounds in NOWRAP_BOUND. */
opt_result
dr_analyze_innermost (innermost_loop_behavior *drb, tree ref,
- class loop *loop, const gimple *stmt)
+ class loop *loop, const gimple *stmt,
+ tree *nowrap_bound)
{
poly_int64 pbitsize, pbitpos;
tree base, poffset;
@@ -1195,9 +1199,11 @@ dr_analyze_innermost (innermost_loop_behavior *drb, tree
ref,
base = build_fold_addr_expr (base);
}
+ bool allow_wrapping = (nowrap_bound != nullptr);
+
if (in_loop)
{
- if (!simple_iv (loop, loop, base, &base_iv, true))
+ if (!simple_iv (loop, loop, base, &base_iv, true, allow_wrapping))
return opt_result::failure_at
(stmt, "failed: evolution of base is not affine.\n");
}
@@ -1206,25 +1212,35 @@ dr_analyze_innermost (innermost_loop_behavior *drb,
tree ref,
base_iv.base = base;
base_iv.step = ssize_int (0);
base_iv.no_overflow = true;
+ base_iv.nowrap_bound = NULL_TREE;
}
if (!poffset)
{
offset_iv.base = ssize_int (0);
offset_iv.step = ssize_int (0);
+ offset_iv.nowrap_bound = NULL_TREE;
}
else
{
if (!in_loop)
- {
- offset_iv.base = poffset;
- offset_iv.step = ssize_int (0);
- }
- else if (!simple_iv (loop, loop, poffset, &offset_iv, true))
+ {
+ offset_iv.base = poffset;
+ offset_iv.step = ssize_int (0);
+ offset_iv.nowrap_bound = NULL_TREE;
+ }
+ else if (!simple_iv (loop, loop, poffset, &offset_iv, true,
+ allow_wrapping))
return opt_result::failure_at
(stmt, "failed: evolution of offset is not affine.\n");
}
+ if (nowrap_bound)
+ {
+ *nowrap_bound = base_iv.nowrap_bound;
+ scev_add_nowrap_bound (nowrap_bound, offset_iv.nowrap_bound);
+ }
+
init = ssize_int (pbytepos);
/* Subtract any constant component from the base and add it to INIT instead.
@@ -1320,10 +1336,14 @@ base_supports_access_fn_components_p (tree base)
}
/* Determines the base object and the list of indices of memory reference
- DR, analyzed in LOOP and instantiated before NEST. */
+ DR, analyzed in LOOP and instantiated before NEST.
+
+ If NOWRAP_BOUND is nonzero, pass it to scev which will then store
+ the bound under which we do not wrap. */
static void
-dr_analyze_indices (struct indices *dri, tree ref, edge nest, loop_p loop)
+dr_analyze_indices (struct indices *dri, tree ref, edge nest, loop_p loop,
+ tree *nowrap_bound = nullptr)
{
/* If analyzing a basic-block there are no indices to analyze
and thus no access functions. */
@@ -1358,7 +1378,7 @@ dr_analyze_indices (struct indices *dri, tree ref, edge
nest, loop_p loop)
if (TREE_CODE (ref) == ARRAY_REF)
{
tree op = TREE_OPERAND (ref, 1);
- tree access_fn = analyze_scalar_evolution (loop, op);
+ tree access_fn = analyze_scalar_evolution (loop, op, nowrap_bound);
access_fn = instantiate_scev (nest, loop, access_fn);
access_fns.safe_push (access_fn);
}
@@ -1390,7 +1410,7 @@ dr_analyze_indices (struct indices *dri, tree ref, edge
nest, loop_p loop)
if (TREE_CODE (ref) == MEM_REF)
{
tree op = TREE_OPERAND (ref, 0);
- tree access_fn = analyze_scalar_evolution (loop, op);
+ tree access_fn = analyze_scalar_evolution (loop, op, nowrap_bound);
access_fn = instantiate_scev (nest, loop, access_fn);
STRIP_NOPS (access_fn);
if (TREE_CODE (access_fn) == POLYNOMIAL_CHREC)
@@ -1496,11 +1516,16 @@ free_data_ref (data_reference_p dr)
Return the data_reference description of MEMREF. NEST is the outermost
loop in which the reference should be instantiated, LOOP is the loop
- in which the data reference should be analyzed. */
+ in which the data reference should be analyzed.
+
+ If ALLOW_ASSUMPTIONS is true, pass an empty no-wrap bound to scev and
+ have it store its assumptions there. If we got a nontrivial
+ assumption, save it in DR's DR_NOWRAP_BOUND. */
struct data_reference *
create_data_ref (edge nest, loop_p loop, tree memref, gimple *stmt,
- bool is_read, bool is_conditional_in_stmt)
+ bool is_read, bool is_conditional_in_stmt,
+ bool allow_assumptions)
{
struct data_reference *dr;
@@ -1517,11 +1542,16 @@ create_data_ref (edge nest, loop_p loop, tree memref,
gimple *stmt,
DR_IS_READ (dr) = is_read;
DR_IS_CONDITIONAL_IN_STMT (dr) = is_conditional_in_stmt;
+ tree nowrap_bound = NULL_TREE;
dr_analyze_innermost (&DR_INNERMOST (dr), memref,
- nest != NULL ? loop : NULL, stmt);
- dr_analyze_indices (&dr->indices, DR_REF (dr), nest, loop);
+ nest != NULL ? loop : NULL, stmt,
+ allow_assumptions ? &nowrap_bound : nullptr);
+ dr_analyze_indices (&dr->indices, DR_REF (dr), nest, loop,
+ allow_assumptions ? &nowrap_bound : nullptr);
dr_analyze_alias (dr);
+ DR_NOWRAP_BOUND (dr) = nowrap_bound;
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
unsigned i;
@@ -1541,6 +1571,11 @@ create_data_ref (edge nest, loop_p loop, tree memref,
gimple *stmt,
fprintf (dump_file, "\n\tstep alignment: %d", DR_STEP_ALIGNMENT (dr));
fprintf (dump_file, "\n\tbase_object: ");
print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM);
+ if (DR_NOWRAP_BOUND (dr))
+ {
+ fprintf (dump_file, "\n\tnowrap bound: ");
+ print_generic_expr (dump_file, DR_NOWRAP_BOUND (dr), TDF_SLIM);
+ }
fprintf (dump_file, "\n");
for (i = 0; i < DR_NUM_DIMENSIONS (dr); i++)
{
@@ -6025,11 +6060,14 @@ loop_nest_has_data_refs (loop_p loop)
/* Stores the data references in STMT to DATAREFS. If there is an unanalyzable
reference, returns false, otherwise returns true. NEST is the outermost
- loop of the loop nest in which the references should be analyzed. */
+ loop of the loop nest in which the references should be analyzed.
+ ALLOW_ASSUMPTIONS determines whether or not no-wrap assumptions
+ are allowed. */
opt_result
find_data_references_in_stmt (class loop *nest, gimple *stmt,
- vec<data_reference_p> *datarefs)
+ vec<data_reference_p> *datarefs,
+ bool allow_assumptions)
{
auto_vec<data_ref_loc, 2> references;
data_reference_p dr;
@@ -6042,7 +6080,8 @@ find_data_references_in_stmt (class loop *nest, gimple
*stmt,
{
dr = create_data_ref (nest ? loop_preheader_edge (nest) : NULL,
loop_containing_stmt (stmt), ref.ref,
- stmt, ref.is_read, ref.is_conditional_in_stmt);
+ stmt, ref.is_read, ref.is_conditional_in_stmt,
+ allow_assumptions);
gcc_assert (dr != NULL);
datarefs->safe_push (dr);
}
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index e25f98d2966..deb264ded2e 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -172,6 +172,10 @@ struct data_reference
/* Behavior of the memory reference in the innermost loop. */
struct innermost_loop_behavior innermost;
+ /* Upper bound for the number of loop iterations for which this DR's
+ IV does not wrap. */
+ tree nowrap_bound;
+
/* Subscripts of this data reference. */
struct indices indices;
@@ -201,6 +205,7 @@ struct data_reference
#define DR_OFFSET_ALIGNMENT(DR) (DR)->innermost.offset_alignment
#define DR_STEP_ALIGNMENT(DR) (DR)->innermost.step_alignment
#define DR_INNERMOST(DR) (DR)->innermost
+#define DR_NOWRAP_BOUND(DR) (DR)->nowrap_bound
typedef struct data_reference *data_reference_p;
@@ -520,7 +525,8 @@ typedef struct data_dependence_relation *ddr_p;
opt_result dr_analyze_innermost (innermost_loop_behavior *, tree,
- class loop *, const gimple *);
+ class loop *, const gimple *,
+ tree * = nullptr);
extern bool compute_data_dependences_for_loop (class loop *, bool,
vec<loop_p> *,
vec<data_reference_p> *,
@@ -543,13 +549,14 @@ extern void free_dependence_relations (vec<ddr_p>& );
extern void free_data_ref (data_reference_p);
extern void free_data_refs (vec<data_reference_p>& );
extern opt_result find_data_references_in_stmt (class loop *, gimple *,
- vec<data_reference_p> *);
+ vec<data_reference_p> *,
+ bool = false);
extern bool graphite_find_data_references_in_stmt (edge, loop_p, gimple *,
vec<data_reference_p> *);
tree find_data_references_in_loop (class loop *, vec<data_reference_p> *);
bool loop_nest_has_data_refs (loop_p loop);
struct data_reference *create_data_ref (edge, loop_p, tree, gimple *, bool,
- bool);
+ bool, bool = false);
extern bool find_loop_nest (class loop *, vec<loop_p> *);
extern struct data_dependence_relation *initialize_data_dependence_relation
(struct data_reference *, struct data_reference *, vec<loop_p>);
--
2.54.0