re PR tree-optimization/80032 (C++ excessive stack usage (no stack reuse))

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: r246314
This commit is contained in:
Richard Biener 2017-03-21 11:43:45 +00:00 committed by Richard Biener
parent da2ce5f993
commit e650ea2a5e
4 changed files with 140 additions and 8 deletions

View File

@ -1,3 +1,11 @@
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

View File

@ -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))
{

View File

@ -1,3 +1,8 @@
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

View File

@ -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;
}
}