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 <rguent...@suse.de> Date: Thu, 14 Jun 2018 15:04:13 +0200 Subject: [PATCH] fix-pr86076 2018-06-15 Richard Biener <rguent...@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)