aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2018-10-12 13:44:35 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2018-10-12 13:44:35 +0000
commit8a5b5b7a8a15cc81d91f0b9ae5320534d7c404d0 (patch)
tree7126686174db7db7ee92215dda96322a84872910
parent2d3a867807bedc27b0fbf2c6e8d4cf557d5e43c9 (diff)
downloadgcc-8a5b5b7a8a15cc81d91f0b9ae5320534d7c404d0.zip
gcc-8a5b5b7a8a15cc81d91f0b9ae5320534d7c404d0.tar.gz
gcc-8a5b5b7a8a15cc81d91f0b9ae5320534d7c404d0.tar.bz2
backport: [multiple changes]
2018-10-12 Richard Biener <rguenther@suse.de> PR c++/54278 Backport from mainline 2017-03-23 Richard Biener <rguenther@suse.de> PR tree-optimization/80032 * gimplify.c (gimple_push_cleanup): Forced unconditional cleanups still have to go to the conditional_cleanups sequence. 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. From-SVN: r265101
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/gimplify.c54
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/g++.dg/opt/pr80032.C121
4 files changed, 180 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8fa30fd..911c49b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+2018-10-12 Richard Biener <rguenther@suse.de>
+
+ PR c++/54278
+ Backport from mainline
+ 2017-03-23 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/80032
+ * gimplify.c (gimple_push_cleanup): Forced unconditional
+ cleanups still have to go to the conditional_cleanups
+ sequence.
+
+ 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.
+
2018-10-12 H.J. Lu <hongjiu.lu@intel.com>
Backport from mainline
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index e55f5b4..e59fa5a 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -5534,10 +5534,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;
@@ -5569,22 +5572,31 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p)
}
val
*/
- tree flag = create_tmp_var (boolean_type_node, "cleanup");
- gassign *ffalse = gimple_build_assign (flag, boolean_false_node);
- gassign *ftrue = gimple_build_assign (flag, boolean_true_node);
-
- cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
- gimplify_stmt (&cleanup, &cleanup_stmts);
- wce = gimple_build_wce (cleanup_stmts);
-
- gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
- gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
- gimplify_seq_add_stmt (pre_p, ftrue);
-
- /* Because of this manipulation, and the EH edges that jump
- threading cannot redirect, the temporary (VAR) will appear
- to be used uninitialized. Don't warn. */
- TREE_NO_WARNING (var) = 1;
+ if (force_uncond)
+ {
+ gimplify_stmt (&cleanup, &cleanup_stmts);
+ wce = gimple_build_wce (cleanup_stmts);
+ gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
+ }
+ else
+ {
+ tree flag = create_tmp_var (boolean_type_node, "cleanup");
+ gassign *ffalse = gimple_build_assign (flag, boolean_false_node);
+ gassign *ftrue = gimple_build_assign (flag, boolean_true_node);
+
+ cleanup = build3 (COND_EXPR, void_type_node, flag, cleanup, NULL);
+ gimplify_stmt (&cleanup, &cleanup_stmts);
+ wce = gimple_build_wce (cleanup_stmts);
+
+ gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, ffalse);
+ gimplify_seq_add_stmt (&gimplify_ctxp->conditional_cleanups, wce);
+ gimplify_seq_add_stmt (pre_p, ftrue);
+
+ /* Because of this manipulation, and the EH edges that jump
+ threading cannot redirect, the temporary (VAR) will appear
+ to be used uninitialized. Don't warn. */
+ TREE_NO_WARNING (var) = 1;
+ }
}
else
{
@@ -5661,11 +5673,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 (cleanup)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 726699b..f933ad2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2018-10-12 Richard Biener <rguenther@suse.de>
+
+ PR c++/54278
+ Backport from mainline
+ 2017-03-21 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/80032
+ * g++.dg/opt/pr80032.C: New testcase.
+
2018-09-07 Janus Weil <janus@gcc.gnu.org>
Backported from trunk
diff --git a/gcc/testsuite/g++.dg/opt/pr80032.C b/gcc/testsuite/g++.dg/opt/pr80032.C
new file mode 100644
index 0000000..8475fdb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr80032.C
@@ -0,0 +1,121 @@
+// PR tree-optimization/80032
+/* { dg-do compile } */
+/* { dg-require-effective-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;
+ }
+}