+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
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;
/* Mark the blocks to be copied. This is used by edge creation hooks
to decide whether to reallocate PHI nodes capacity to avoid reallocating
{
/* 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)
{
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);
/* 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;
}
+2019-02-22 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/87609
+ * gcc.dg/torture/restrict-7.c: New testcase.
+
2019-02-21 Jakub Jelinek <jakub@redhat.com>
PR c++/89285
--- /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 (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. */