From: Richard Biener Date: Tue, 21 Mar 2017 11:43:45 +0000 (+0000) Subject: re PR tree-optimization/80032 (C++ excessive stack usage (no stack reuse)) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e650ea2a5efcd806b5f1aafc2db980d083fbfd7c;p=gcc.git re PR tree-optimization/80032 (C++ excessive stack usage (no stack reuse)) 2017-03-21 Richard Biener 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: r246314 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f48f6d39aac..d679a5c014e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2017-03-21 Richard Biener + + 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 PR tree-optimization/80122 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,3 +1,8 @@ +2017-03-21 Richard Biener + + PR tree-optimization/80032 + * g++.dg/opt/pr80032.C: New testcase. + 2017-03-21 Richard Biener PR tree-optimization/80122 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; + } +}