diff options
author | Richard Biener <rguenther@suse.de> | 2018-10-12 13:44:35 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2018-10-12 13:44:35 +0000 |
commit | 8a5b5b7a8a15cc81d91f0b9ae5320534d7c404d0 (patch) | |
tree | 7126686174db7db7ee92215dda96322a84872910 | |
parent | 2d3a867807bedc27b0fbf2c6e8d4cf557d5e43c9 (diff) | |
download | gcc-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/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/gimplify.c | 54 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/pr80032.C | 121 |
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; + } +} |