+2019-09-05 Richard Biener <rguenther@suse.de>
+
+ * lto-streamer.h (LTO_minor_version): Bump.
+
+ Backport from mainline
+ 2019-05-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90328
+ * tree-data-ref.h (dr_may_alias_p): Pass in the actual loop nest.
+ * tree-data-ref.c (dr_may_alias_p): Check whether the clique
+ is valid in the loop nest before using it.
+ (initialize_data_dependence_relation): Adjust.
+ * graphite-scop-detection.c (build_alias_set): Pass the SCOP enclosing
+ loop as loop-nest to dr_may_alias_p.
+
+ 2019-03-08 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/89578
+ * cfgloop.h (struct loop): Add owned_clique field.
+ * cfgloopmanip.c (copy_loop_info): Copy it.
+ * tree-cfg.c (gimple_duplicate_bb): Do not remap owned_clique
+ cliques.
+ * tree-inline.c (copy_loops): Remap owned_clique.
+ * lto-streamer-in.c (input_cfg): Stream owned_clique.
+ * lto-streamer-out.c (output_cfg): Likewise.
+
+ 2019-02-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87609
+ * tree-cfg.c (gimple_duplicate_bb): Only remap inlined cliques.
+
+ 2019-02-22 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/87609
+ * cfghooks.h (dependence_hash): New typedef.
+ (struct copy_bb_data): New type.
+ (cfg_hooks::duplicate_block): Adjust to take a copy_bb_data argument.
+ (duplicate_block): Likewise.
+ * cfghooks.c (duplicate_block): Pass down copy_bb_data.
+ (copy_bbs): Create and pass down copy_bb_data.
+ * cfgrtl.c (cfg_layout_duplicate_bb): Adjust.
+ (rtl_duplicate_bb): Likewise.
+ * tree-cfg.c (gimple_duplicate_bb): If the copy_bb_data arg is not NULL
+ remap dependence info.
+
+ 2019-02-22 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/87609
+ * tree-core.h (tree_base): Document special clique values.
+ * tree-inline.c (remap_dependence_clique): Do not use the
+ special clique value of one.
+ (maybe_set_dependence_info): Use clique one.
+ (clear_dependence_clique): New callback.
+ (compute_dependence_clique): Clear clique one from all refs
+ before assigning it (again).
+
2019-09-04 Iain Sandoe <iain@sandoe.co.uk>
Backport from mainline
AFTER. */
basic_block
-duplicate_block (basic_block bb, edge e, basic_block after)
+duplicate_block (basic_block bb, edge e, basic_block after, copy_bb_data *id)
{
edge s, n;
basic_block new_bb;
gcc_checking_assert (can_duplicate_block_p (bb));
- new_bb = cfg_hooks->duplicate_block (bb);
+ new_bb = cfg_hooks->duplicate_block (bb, id);
if (after)
move_block_after (new_bb, after);
unsigned i, j;
basic_block bb, new_bb, dom_bb;
edge e;
+ copy_bb_data id;
/* Duplicate bbs, update dominators, assign bbs to loops. */
for (i = 0; i < n; i++)
{
/* Duplicate. */
bb = bbs[i];
- new_bb = new_bbs[i] = duplicate_block (bb, NULL, after);
+ new_bb = new_bbs[i] = duplicate_block (bb, NULL, after, &id);
after = new_bb;
bb->flags |= BB_DUPLICATED;
if (bb->loop_father)
bool run;
};
+typedef int_hash <unsigned short, 0> dependence_hash;
+
+/* Optional data for duplicate_block. */
+
+struct copy_bb_data
+{
+ copy_bb_data() : dependence_map (NULL) {}
+ ~copy_bb_data () { delete dependence_map; }
+
+ /* A map from the copied BBs dependence info cliques to
+ equivalents in the BBs duplicated to. */
+ hash_map<dependence_hash, unsigned short> *dependence_map;
+};
struct cfg_hooks
{
bool (*can_duplicate_block_p) (const_basic_block a);
/* Duplicate block A. */
- basic_block (*duplicate_block) (basic_block a);
+ basic_block (*duplicate_block) (basic_block a, copy_bb_data *);
/* Higher level functions representable by primitive operations above if
we didn't have some oddities in RTL and Tree representations. */
extern void predict_edge (edge e, enum br_predictor predictor, int probability);
extern bool predicted_by_p (const_basic_block bb, enum br_predictor predictor);
extern bool can_duplicate_block_p (const_basic_block);
-extern basic_block duplicate_block (basic_block, edge, basic_block);
+extern basic_block duplicate_block (basic_block, edge, basic_block,
+ copy_bb_data * = NULL);
extern bool block_ends_with_call_p (basic_block bb);
extern bool empty_block_p (basic_block);
extern basic_block split_block_before_cond_jump (basic_block);
/* True if the loop is part of an oacc kernels region. */
unsigned in_oacc_kernels_region : 1;
+ /* If this loop was inlined the main clique of the callee which does
+ not need remapping when copying the loop body. */
+ unsigned short owned_clique;
+
/* For SIMD loops, this is a unique identifier of the loop, referenced
by IFN_GOMP_SIMD_VF, IFN_GOMP_SIMD_LANE and IFN_GOMP_SIMD_LAST_LANE
builtins. */
target->warned_aggressive_loop_optimizations
|= loop->warned_aggressive_loop_optimizations;
target->in_oacc_kernels_region = loop->in_oacc_kernels_region;
+ target->owned_clique = loop->owned_clique;
}
/* Copies copy of LOOP as subloop of TARGET loop, placing newly
/* Create a duplicate of the basic block BB. */
static basic_block
-cfg_layout_duplicate_bb (basic_block bb)
+cfg_layout_duplicate_bb (basic_block bb, copy_bb_data *)
{
rtx_insn *insn;
basic_block new_bb;
}
static basic_block
-rtl_duplicate_bb (basic_block bb)
+rtl_duplicate_bb (basic_block bb, copy_bb_data *id)
{
- bb = cfg_layout_duplicate_bb (bb);
+ bb = cfg_layout_duplicate_bb (bb, id);
bb->aux = NULL;
return bb;
}
int i, j;
int *all_vertices;
+ struct loop *nest
+ = find_common_loop (scop->scop_info->region.entry->dest->loop_father,
+ scop->scop_info->region.exit->src->loop_father);
+
FOR_EACH_VEC_ELT (scop->drs, i, dr1)
for (j = i+1; scop->drs.iterate (j, &dr2); j++)
- if (dr_may_alias_p (dr1->dr, dr2->dr, true))
+ if (dr_may_alias_p (dr1->dr, dr2->dr, nest))
{
add_edge (g, i, j);
add_edge (g, j, i);
/* Read OMP SIMD related info. */
loop->safelen = streamer_read_hwi (ib);
+ loop->owned_clique = streamer_read_hwi (ib);
loop->dont_vectorize = streamer_read_hwi (ib);
loop->force_vectorize = streamer_read_hwi (ib);
loop->simduid = stream_read_tree (ib, data_in);
/* Write OMP SIMD related info. */
streamer_write_hwi (ob, loop->safelen);
+ streamer_write_hwi (ob, loop->owned_clique);
streamer_write_hwi (ob, loop->dont_vectorize);
streamer_write_hwi (ob, loop->force_vectorize);
stream_write_tree (ob, loop->simduid, true);
form followed by the data for the string. */
#define LTO_major_version 6
-#define LTO_minor_version 1
+#define LTO_minor_version 2
typedef unsigned char lto_decl_flags_t;
+2019-09-05 Richard Biener <rguenther@suse.de>
+
+ Backport from mainline
+ 2019-05-06 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/90328
+ * gcc.dg/torture/pr90328.c: New testcase.
+
+ 2019-02-22 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/87609
+ * gcc.dg/torture/restrict-7.c: New testcase.
+
2019-09-04 Iain Sandoe <iain@sandoe.co.uk>
Backport from mainline.
--- /dev/null
+/* { dg-do run } */
+
+void g(int*__restrict x, int*y)
+{
+ *x = *y;
+}
+
+void __attribute__((noinline,noclone)) f(int* a,int* b)
+{
+ for(int i=0;i<1024;++i)
+ g(a+i,b+i);
+}
+
+int main()
+{
+ int x[1025];
+ for (int i = 0; i < 1025; ++i)
+ x[i] = i+1;
+ f(x+1, x);
+ for (int i = 0; i < 1025; ++i)
+ if (x[i] != 1)
+ __builtin_abort ();
+ return 0;
+}
--- /dev/null
+/* { dg-do run } */
+
+extern void abort (void);
+
+static inline __attribute__((always_inline)) void
+copy(int *restrict a, int *restrict b)
+{
+ *b = *a;
+ *a = 7;
+}
+
+void __attribute__((noinline))
+floppy(int mat[static 2], unsigned idxs[static 3])
+{
+ for (int i = 0; i < 3; i++)
+ copy(&mat[i%2], &mat[idxs[i]]);
+}
+
+int main()
+{
+ int mat[2] = {10, 20};
+ unsigned idxs[3] = {1, 0, 1};
+ floppy(mat, idxs);
+ if (mat[0] != 7 || mat[1] != 10)
+ abort ();
+ return 0;
+}
preserve SSA form. */
static basic_block
-gimple_duplicate_bb (basic_block bb)
+gimple_duplicate_bb (basic_block bb, copy_bb_data *id)
{
basic_block new_bb;
gimple_stmt_iterator gsi_tgt;
&& (!VAR_P (base) || !DECL_HAS_VALUE_EXPR_P (base)))
DECL_NONSHAREABLE (base) = 1;
}
+
+ /* If requested remap dependence info of cliques brought in
+ via inlining. */
+ if (id)
+ for (unsigned i = 0; i < gimple_num_ops (copy); ++i)
+ {
+ tree op = gimple_op (copy, i);
+ if (!op)
+ continue;
+ if (TREE_CODE (op) == ADDR_EXPR
+ || TREE_CODE (op) == WITH_SIZE_EXPR)
+ op = TREE_OPERAND (op, 0);
+ while (handled_component_p (op))
+ op = TREE_OPERAND (op, 0);
+ if ((TREE_CODE (op) == MEM_REF
+ || TREE_CODE (op) == TARGET_MEM_REF)
+ && MR_DEPENDENCE_CLIQUE (op) > 1
+ && MR_DEPENDENCE_CLIQUE (op) != bb->loop_father->owned_clique)
+ {
+ if (!id->dependence_map)
+ id->dependence_map = new hash_map<dependence_hash,
+ unsigned short>;
+ bool existed;
+ unsigned short &newc = id->dependence_map->get_or_insert
+ (MR_DEPENDENCE_CLIQUE (op), &existed);
+ if (!existed)
+ {
+ gcc_assert (MR_DEPENDENCE_CLIQUE (op) <= cfun->last_clique);
+ newc = ++cfun->last_clique;
+ }
+ MR_DEPENDENCE_CLIQUE (op) = newc;
+ }
+ }
/* Create new names for all the definitions created by COPY and
add replacement mappings for each new name. */
expression trees and specify known data non-dependences. For
two memory references in a function they are known to not
alias if dependence_info.clique are equal and dependence_info.base
- are distinct. */
+ are distinct. Clique number zero means there is no information,
+ clique number one is populated from function global information
+ and thus needs no remapping on transforms like loop unrolling. */
struct {
unsigned short clique;
unsigned short base;
bool
dr_may_alias_p (const struct data_reference *a, const struct data_reference *b,
- bool loop_nest)
+ struct loop *loop_nest)
{
tree addr_a = DR_BASE_OBJECT (a);
tree addr_b = DR_BASE_OBJECT (b);
if ((TREE_CODE (addr_a) == MEM_REF || TREE_CODE (addr_a) == TARGET_MEM_REF)
&& (TREE_CODE (addr_b) == MEM_REF || TREE_CODE (addr_b) == TARGET_MEM_REF)
+ /* For cross-iteration dependences the cliques must be valid for the
+ whole loop, not just individual iterations. */
+ && (!loop_nest
+ || MR_DEPENDENCE_CLIQUE (addr_a) == 1
+ || MR_DEPENDENCE_CLIQUE (addr_a) == loop_nest->owned_clique)
&& MR_DEPENDENCE_CLIQUE (addr_a) == MR_DEPENDENCE_CLIQUE (addr_b)
&& MR_DEPENDENCE_BASE (addr_a) != MR_DEPENDENCE_BASE (addr_b))
return false;
}
/* If the data references do not alias, then they are independent. */
- if (!dr_may_alias_p (a, b, loop_nest.exists ()))
+ if (!dr_may_alias_p (a, b, loop_nest.exists () ? loop_nest[0] : NULL))
{
DDR_ARE_DEPENDENT (res) = chrec_known;
return res;
vec<data_reference_p> *);
extern bool dr_may_alias_p (const struct data_reference *,
- const struct data_reference *, bool);
+ const struct data_reference *, struct loop *);
extern bool dr_equal_offsets_p (struct data_reference *,
struct data_reference *);
bool existed;
unsigned short &newc = id->dependence_map->get_or_insert (clique, &existed);
if (!existed)
- newc = ++cfun->last_clique;
+ {
+ /* Clique 1 is reserved for local ones set by PTA. */
+ if (cfun->last_clique == 0)
+ cfun->last_clique = 1;
+ newc = ++cfun->last_clique;
+ }
return newc;
}
dest_loop->simduid = remap_decl (src_loop->simduid, id);
cfun->has_simduid_loops = true;
}
-
+ if (id->src_cfun->last_clique != 0)
+ dest_loop->owned_clique
+ = remap_dependence_clique (id,
+ src_loop->owned_clique
+ ? src_loop->owned_clique : 1);
/* Recurse. */
copy_loops (id, dest_loop, src_loop);
}
if (MR_DEPENDENCE_CLIQUE (ref) == 0)
{
if (clique == 0)
- clique = ++cfun->last_clique;
+ {
+ if (cfun->last_clique == 0)
+ cfun->last_clique = 1;
+ clique = 1;
+ }
if (restrict_var->ruid == 0)
restrict_var->ruid = ++last_ruid;
MR_DEPENDENCE_CLIQUE (ref) = clique;
return false;
}
+/* Clear dependence info for the clique DATA. */
+
+static bool
+clear_dependence_clique (gimple *, tree base, tree, void *data)
+{
+ unsigned short clique = (uintptr_t)data;
+ if ((TREE_CODE (base) == MEM_REF
+ || TREE_CODE (base) == TARGET_MEM_REF)
+ && MR_DEPENDENCE_CLIQUE (base) == clique)
+ {
+ MR_DEPENDENCE_CLIQUE (base) = 0;
+ MR_DEPENDENCE_BASE (base) = 0;
+ }
+
+ return false;
+}
+
/* Compute the set of independend memory references based on restrict
tags and their conservative propagation to the points-to sets. */
static void
compute_dependence_clique (void)
{
+ /* First clear the special "local" clique. */
+ basic_block bb;
+ if (cfun->last_clique != 0)
+ FOR_EACH_BB_FN (bb, cfun)
+ for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
+ !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ walk_stmt_load_store_ops (stmt, (void *)(uintptr_t) 1,
+ clear_dependence_clique,
+ clear_dependence_clique);
+ }
+
unsigned short clique = 0;
unsigned short last_ruid = 0;
bitmap rvars = BITMAP_ALLOC (NULL);