Commit e650ea2a by Richard Biener Committed by Richard Biener

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
parent da2ce5f9
2017-03-21 Richard Biener <rguenther@suse.de> 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 PR tree-optimization/80122
* tree-inline.c (copy_bb): Do not expans va-arg packs or * tree-inline.c (copy_bb): Do not expans va-arg packs or
va_arg_pack_len when the inlined call stmt requires pack va_arg_pack_len when the inlined call stmt requires pack
......
...@@ -6288,10 +6288,13 @@ gimplify_cleanup_point_expr (tree *expr_p, gimple_seq *pre_p) ...@@ -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 /* Insert a cleanup marker for gimplify_cleanup_point_expr. CLEANUP
is the cleanup action required. EH_ONLY is true if the cleanup should 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 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 *wce;
gimple_seq cleanup_stmts = NULL; gimple_seq cleanup_stmts = NULL;
...@@ -6301,7 +6304,7 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p) ...@@ -6301,7 +6304,7 @@ gimple_push_cleanup (tree var, tree cleanup, bool eh_only, gimple_seq *pre_p)
if (seen_error ()) if (seen_error ())
return; return;
if (gimple_conditional_context ()) if (gimple_conditional_context () && ! force_uncond)
{ {
/* If we're in a conditional context, this is more complex. We only /* 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 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) ...@@ -6426,11 +6429,7 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
NULL); NULL);
TREE_THIS_VOLATILE (clobber) = true; TREE_THIS_VOLATILE (clobber) = true;
clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber); clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
if (cleanup) gimple_push_cleanup (temp, clobber, false, pre_p, true);
cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
clobber);
else
cleanup = clobber;
} }
if (asan_poisoned_variables && dbg_cnt (asan_use_after_scope)) if (asan_poisoned_variables && dbg_cnt (asan_use_after_scope))
{ {
......
2017-03-21 Richard Biener <rguenther@suse.de> 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 PR tree-optimization/80122
* gcc.dg/torture/pr80122.c: New testcase. * gcc.dg/torture/pr80122.c: New testcase.
......
// 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;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment