===================================================================
@@ -1066,7 +1066,7 @@ can_duplicate_block_p (const_basic_block
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;
@@ -1082,7 +1082,7 @@ duplicate_block (basic_block bb, edge e,
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);
@@ -1337,6 +1337,7 @@ copy_bbs (basic_block *bbs, unsigned n,
unsigned i, j;
basic_block bb, new_bb, dom_bb;
edge e;
+ copy_bb_data id;
/* Mark the blocks to be copied. This is used by edge creation hooks
to decide whether to reallocate PHI nodes capacity to avoid reallocating
@@ -1349,7 +1350,7 @@ copy_bbs (basic_block *bbs, unsigned n,
{
/* 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;
if (bb->loop_father)
{
===================================================================
@@ -54,6 +54,19 @@ struct profile_record
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
{
@@ -112,7 +125,7 @@ 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. */
@@ -227,7 +240,8 @@ extern void tidy_fallthru_edges (void);
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);
===================================================================
@@ -4250,7 +4250,7 @@ duplicate_insn_chain (rtx_insn *from, rt
/* 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;
@@ -5080,9 +5080,9 @@ rtl_can_remove_branch_p (const_edge e)
}
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;
}
===================================================================
@@ -0,0 +1,27 @@
+/* { 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;
+}
===================================================================
@@ -6164,7 +6164,7 @@ gimple_can_duplicate_bb_p (const_basic_b
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;
@@ -6228,6 +6228,36 @@ gimple_duplicate_bb (basic_block bb)
&& (!VAR_P (base) || !DECL_HAS_VALUE_EXPR_P (base)))
DECL_NONSHAREABLE (base) = 1;
}
+
+ 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) != 0)
+ {
+ 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. */