[PATCH] Fix PR86076

Richard Biener rguenther@suse.de
Fri Jun 15 07:23:00 GMT 2018


The following fixes move-sese-region-to-function to not clobber
shared trees when it changes BLOCK references.

Invariant addresses are somewhat special in that they are allowed
to be shared (by the verifier) but are actually copied by
unshare_expr and friends.

Maybe that's something we should change (not allow tree sharing
of those).

Anyway, bootstrapped and tested on x86_64-unknown-linux-gnu,
applied to trunk and queued for backports.

Richard.

>From 4dab04aa51d234815a44e1d844c515fa18f97dc3 Mon Sep 17 00:00:00 2001
From: Richard Guenther <rguenther@suse.de>
Date: Thu, 14 Jun 2018 15:04:13 +0200
Subject: [PATCH] fix-pr86076

2018-06-15  Richard Biener  <rguenther@suse.de>

	PR middle-end/86076
	* tree-cfg.c (move_stmt_op): unshare invariant addresses
	before adjusting their block.

	* gcc.dg/pr86076.c: New testcase.

diff --git a/gcc/testsuite/gcc.dg/pr86076.c b/gcc/testsuite/gcc.dg/pr86076.c
new file mode 100644
index 00000000000..019ced3cbf5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr86076.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-parallelize-loops=2 -fno-tree-dce -fno-tree-pre -fno-tree-vrp --param max-loop-header-insns=1" } */
+
+int __attribute__ ((noinline))
+lv (int tm)
+{
+  (void) tm;
+
+  return 0;
+}
+
+void
+o7 (int uu)
+{
+  while (uu < 1)
+    while (uu != 0)
+      {
+	short int ca;
+
+	ca = lv (0);
+	(void) ca;
+	++uu;
+      }
+
+  lv (lv (0));
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 5f6defa6fe7..e7d16ca0a14 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -6742,7 +6742,16 @@ move_stmt_op (tree *tp, int *walk_subtrees, void *data)
 	;
       else if (block == p->orig_block
 	       || p->orig_block == NULL_TREE)
-	TREE_SET_BLOCK (t, p->new_block);
+	{
+	  /* tree_node_can_be_shared says we can share invariant
+	     addresses but unshare_expr copies them anyways.  Make sure
+	     to unshare before adjusting the block in place - we do not
+	     always see a copy here.  */
+	  if (TREE_CODE (t) == ADDR_EXPR
+	      && is_gimple_min_invariant (t))
+	    *tp = t = unshare_expr (t);
+	  TREE_SET_BLOCK (t, p->new_block);
+	}
       else if (flag_checking)
 	{
 	  while (block && TREE_CODE (block) == BLOCK && block != p->orig_block)



More information about the Gcc-patches mailing list