re PR tree-optimization/87609 (miscompilation with restrict and loop)
authorRichard Biener <rguenther@suse.de>
Fri, 22 Feb 2019 08:38:14 +0000 (08:38 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 22 Feb 2019 08:38:14 +0000 (08:38 +0000)
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

gcc/ChangeLog
gcc/cfghooks.c
gcc/cfghooks.h
gcc/cfgrtl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/restrict-7.c [new file with mode: 0644]
gcc/tree-cfg.c

index a35b0aa1a5197157b14521ccf2c74df7a0706e5e..7397b50465a418eae146218d001819c35b8ec918 100644 (file)
@@ -1,3 +1,17 @@
+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
index 6562beae61642059c8188d7023f5d0880f761c99..a1d603a207ec7791a3101060e1126c395507ea62 100644 (file)
@@ -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)
        {
index 8244f5a5ac7688ea3ae8a87150085d34b5e484e2..e9385c99443846df52fd92c616d5e29cbc14c3a0 100644 (file)
@@ -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);
index 56564c2fda7aa03b0283e545fd222066dfd1dc39..08e534f2485cd2bfde214617357a06ceb2a8cb31 100644 (file)
@@ -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;
 }
index 78d9d2c82e47760e11258ec826c266b3882bfa39..7cb6b240d0c924c50955d192ae10e2128f781a00 100644 (file)
@@ -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 (file)
index 0000000..1073710
--- /dev/null
@@ -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;
+}
index f196428a4c4ef639406fe7cafcbfbcb25957fdad..eac70274c171cf3e25c7638666cf51e7464cad16 100644 (file)
@@ -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.  */