aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/ipa-split.c32
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr68470.C36
4 files changed, 72 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 48256e9..f908fe6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-01 Richard Biener <rguenther@suse.de>
+
+ PR ipa/68470
+ * ipa-split.c (split_function): Handle main part not returning.
+
2015-12-01 Ilya Enkovich <enkovich.gnu@gmail.com>
PR middle-end/68595
diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c
index be33dda..56c954b 100644
--- a/gcc/ipa-split.c
+++ b/gcc/ipa-split.c
@@ -1205,7 +1205,6 @@ split_function (basic_block return_bb, struct split_point *split_point,
edge e;
edge_iterator ei;
tree retval = NULL, real_retval = NULL, retbnd = NULL;
- bool split_part_return_p = false;
bool with_bounds = chkp_function_instrumented_p (current_function_decl);
gimple *last_stmt = NULL;
unsigned int i;
@@ -1246,12 +1245,28 @@ split_function (basic_block return_bb, struct split_point *split_point,
args_to_pass.safe_push (arg);
}
- /* See if the split function will return. */
+ /* See if the split function or the main part will return. */
+ bool main_part_return_p = false;
+ bool split_part_return_p = false;
FOR_EACH_EDGE (e, ei, return_bb->preds)
- if (bitmap_bit_p (split_point->split_bbs, e->src->index))
- break;
- if (e)
- split_part_return_p = true;
+ {
+ if (bitmap_bit_p (split_point->split_bbs, e->src->index))
+ split_part_return_p = true;
+ else
+ main_part_return_p = true;
+ }
+ /* The main part also returns if we we split on a fallthru edge
+ and the split part returns. */
+ if (split_part_return_p)
+ FOR_EACH_EDGE (e, ei, split_point->entry_bb->preds)
+ {
+ if (! bitmap_bit_p (split_point->split_bbs, e->src->index)
+ && single_succ_p (e->src))
+ {
+ main_part_return_p = true;
+ break;
+ }
+ }
/* Add return block to what will become the split function.
We do not return; no return block is needed. */
@@ -1295,6 +1310,11 @@ split_function (basic_block return_bb, struct split_point *split_point,
else
bitmap_set_bit (split_point->split_bbs, return_bb->index);
+ /* If the main part doesn't return pretend the return block wasn't
+ found for all of the following. */
+ if (! main_part_return_p)
+ return_bb = EXIT_BLOCK_PTR_FOR_FN (cfun);
+
/* If RETURN_BB has virtual operand PHIs, they must be removed and the
virtual operand marked for renaming as we change the CFG in a way that
tree-inline is not able to compensate for.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 07a9e52..8263c1b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2015-12-01 Richard Biener <rguenther@suse.de>
+
+ PR ipa/68470
+ * g++.dg/torture/pr68470.C: New testcase.
+
2015-12-01 Ilya Enkovich <enkovich.gnu@gmail.com>
PR middle-end/68595
diff --git a/gcc/testsuite/g++.dg/torture/pr68470.C b/gcc/testsuite/g++.dg/torture/pr68470.C
new file mode 100644
index 0000000..5dd558d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr68470.C
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+
+void deallocate(void *);
+void *a;
+
+struct C {
+ virtual void m_fn1();
+};
+
+struct D {
+ C *m_fn2() {
+ if (a)
+ __builtin_abort();
+ }
+};
+D getd();
+
+struct vec_int {
+ int _M_start;
+ ~vec_int() {
+ if (_M_start)
+ deallocate(&_M_start);
+ }
+};
+vec_int *b;
+
+struct I {
+ virtual void m_fn3();
+};
+
+void I::m_fn3() {
+ if (a)
+ getd().m_fn2()->m_fn1();
+ b->~vec_int();
+}
+