aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2017-03-21 11:43:45 +0000
committerRichard Biener <rguenther@suse.de>2017-03-21 11:43:45 +0000
commitdce221e16ffb829fa95a2159d7f2a84e51f74782 (patch)
treeb7ff424f8729b56a0c9c67b0f850a1672a1c2b49
parentc093dc96f70a4207ab93798da640fa5202268585 (diff)
2017-03-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/80032 * gimplify.c (gimple_push_cleanup): Add force_uncond parameter, if set force the cleanup to happen unconditionally. (gimplify_target_expr): Push inserted clobbers with force_uncond to avoid them being removed by control-dependent DCE. * g++.dg/opt/pr80032.C: New testcase. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@246314 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/gimplify.c15
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/opt/pr80032.C120
4 files changed, 140 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f48f6d39aac..d679a5c014e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2017-03-21 Richard Biener <rguenther@suse.de>
+ PR tree-optimization/80032
+ * gimplify.c (gimple_push_cleanup): Add force_uncond parameter,
+ if set force the cleanup to happen unconditionally.
+ (gimplify_target_expr): Push inserted clobbers with force_uncond
+ to avoid them being removed by control-dependent DCE.
+
+2017-03-21 Richard Biener <rguenther@suse.de>
+
PR tree-optimization/80122
* tree-inline.c (copy_bb): Do not expans va-arg packs or
va_arg_pack_len when the inlined call stmt requires pack
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index fbf136fbce4..06f984cec01 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6288,10 +6288,13 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p)
/* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
is the cleanup action required. EH_ONLY is true if the cleanup should
- only be executed if an exception is thrown, not on normal exit. */
+ only be executed if an exception is thrown, not on normal exit.
+ If FORCE_UNCOND is true perform the cleanup unconditionally; this is
+ only valid for clobbers. */
static void
-gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p)
+gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p,
+ bool force_uncond = false)
{
gimple *wce;
gimple_seq cleanup_stmts = NULL;
@@ -6301,7 +6304,7 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p)
if (seen_error ())
return;
- if (gimple_conditional_context ())
+ if (gimple_conditional_context () && ! force_uncond)
{
/* If we're in a conditional context, this is more complex. We only
want to run the cleanup if we actually ran the initialization that
@@ -6426,11 +6429,7 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
NULL);
TREE_THIS_VOLATILE (clobber) = true;
clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
- if (cleanup)
- cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
- clobber);
- else
- cleanup = clobber;
+ gimple_push_cleanup (temp, clobber, false, pre_p, true);
}
if (asan_poisoned_variables && dbg_cnt (asan_use_after_scope))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 68705a7de06..08fcb72ca55 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2017-03-21 Richard Biener <rguenther@suse.de>
+ PR tree-optimization/80032
+ * g++.dg/opt/pr80032.C: New testcase.
+
+2017-03-21 Richard Biener <rguenther@suse.de>
+
PR tree-optimization/80122
* gcc.dg/torture/pr80122.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/opt/pr80032.C b/gcc/testsuite/g++.dg/opt/pr80032.C
new file mode 100644
index 00000000000..9cdad6838a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr80032.C
@@ -0,0 +1,120 @@
+// PR tree-optimization/80032
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+// If DCE removes too many CLOBBERs then stack usage goes through the
+// roof as stack slots can no longer be shared.
+// { dg-additional-options "-Wstack-usage=200" { target x86_64-*-* i?86-*-* } }
+
+typedef unsigned a;
+namespace test {
+ enum b { c };
+ class ADataContainer;
+ class BitMask;
+ namespace api {
+ enum DataStore { candidate };
+ }
+ using d = api::DataStore;
+ namespace db {
+ class e;
+ class f;
+ class g;
+ class ManagedObjectConst {
+ public:
+ ManagedObjectConst(const ManagedObjectConst &);
+ bool isFieldDefault(a, d) const;
+ ADataContainer &getFieldDefault(a, d) const;
+ g *h;
+ e *i;
+ f *j;
+ };
+ struct FieldInfo {
+ FieldInfo(ManagedObjectConst, a, d);
+ ManagedObjectConst k;
+ };
+ b compare(const FieldInfo &, const ADataContainer &);
+ class ManagedObject : public ManagedObjectConst {};
+ }
+ using namespace db;
+ void FN(ManagedObject &k, const BitMask &) {
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ if (!k.isFieldDefault(8, d::candidate) &&
+ !compare(FieldInfo(k, 11, d::candidate),
+ k.getFieldDefault(11, d::candidate)) == c)
+ return;
+ }
+}