aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2019-02-22 08:38:14 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2019-02-22 08:38:14 +0000
commit229d576cde53ac4396583da3642ca969cca413d1 (patch)
tree90ee3349ab449b0ce61e8104f5c1086026142119
parent3c8b06dcc68be1ba6dbb01fbbd32ba2a337dd3b8 (diff)
downloadgcc-229d576cde53ac4396583da3642ca969cca413d1.zip
gcc-229d576cde53ac4396583da3642ca969cca413d1.tar.gz
gcc-229d576cde53ac4396583da3642ca969cca413d1.tar.bz2
re PR tree-optimization/87609 (miscompilation with restrict and loop)
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. * gcc.dg/torture/restrict-7.c: New testcase. From-SVN: r269098
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/cfghooks.c7
-rw-r--r--gcc/cfghooks.h18
-rw-r--r--gcc/cfgrtl.c6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/restrict-7.c27
-rw-r--r--gcc/tree-cfg.c32
7 files changed, 100 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a35b0aa..7397b50 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,19 @@
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
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index 6562bea..a1d603a 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -1066,7 +1066,7 @@ can_duplicate_block_p (const_basic_block bb)
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, basic_block after)
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, basic_block *new_bbs,
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, basic_block *new_bbs,
{
/* 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)
{
diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h
index 8244f5a..e9385c9 100644
--- a/gcc/cfghooks.h
+++ b/gcc/cfghooks.h
@@ -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);
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 56564c2..08e534f 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -4250,7 +4250,7 @@ duplicate_insn_chain (rtx_insn *from, rtx_insn *to)
/* 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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 78d9d2c..7cb6b24 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+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
diff --git a/gcc/testsuite/gcc.dg/torture/restrict-7.c b/gcc/testsuite/gcc.dg/torture/restrict-7.c
new file mode 100644
index 0000000..1073710
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/restrict-7.c
@@ -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;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index f196428..eac7027 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -6164,7 +6164,7 @@ gimple_can_duplicate_bb_p (const_basic_block bb ATTRIBUTE_UNUSED)
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. */