Commit 87e2a8fd by Xinliang David Li Committed by Xinliang David Li

Implement -freuse-stack= option

From-SVN: r189413
parent 2f011375
2012-07-10 Xinliang David Li <davidxl@google.com>
* doc/invoke.texi: New option documented.
* flag-types.h: New enum type.
* gimplify.c (gimplify_bind_expr): Control
clobber generation with new option.
(gimplify_target_expr): Ditto.
common.opt: New option.
2012-07-10 Julian Brown <julian@codesourcery.com> 2012-07-10 Julian Brown <julian@codesourcery.com>
* config/arm/arm.md (movsi): Don't split symbol refs here. * config/arm/arm.md (movsi): Don't split symbol refs here.
......
...@@ -1247,6 +1247,22 @@ fif-conversion2 ...@@ -1247,6 +1247,22 @@ fif-conversion2
Common Report Var(flag_if_conversion2) Optimization Common Report Var(flag_if_conversion2) Optimization
Perform conversion of conditional jumps to conditional execution Perform conversion of conditional jumps to conditional execution
fstack-reuse=
Common Joined RejectNegative Enum(stack_reuse_level) Var(flag_stack_reuse) Init(SR_ALL)
-fstack-reuse=[all|named_vars|none] Set stack reuse level for local variables.
Enum
Name(stack_reuse_level) Type(enum stack_reuse_level) UnknownError(unknown Stack Reuse Level %qs)
EnumValue
Enum(stack_reuse_level) String(all) Value(SR_ALL)
EnumValue
Enum(stack_reuse_level) String(named_vars) Value(SR_NAMED_VARS)
EnumValue
Enum(stack_reuse_level) String(none) Value(SR_NONE)
ftree-loop-if-convert ftree-loop-if-convert
Common Report Var(flag_tree_loop_if_convert) Init(-1) Optimization Common Report Var(flag_tree_loop_if_convert) Init(-1) Optimization
Convert conditional jumps in innermost loops to branchless equivalents Convert conditional jumps in innermost loops to branchless equivalents
......
...@@ -990,6 +990,7 @@ See S/390 and zSeries Options. ...@@ -990,6 +990,7 @@ See S/390 and zSeries Options.
-fstack-limit-register=@var{reg} -fstack-limit-symbol=@var{sym} @gol -fstack-limit-register=@var{reg} -fstack-limit-symbol=@var{sym} @gol
-fno-stack-limit -fsplit-stack @gol -fno-stack-limit -fsplit-stack @gol
-fleading-underscore -ftls-model=@var{model} @gol -fleading-underscore -ftls-model=@var{model} @gol
-fstack-reuse=@var{reuse_level} @gol
-ftrapv -fwrapv -fbounds-check @gol -ftrapv -fwrapv -fbounds-check @gol
-fvisibility -fstrict-volatile-bitfields -fsync-libcalls} -fvisibility -fstrict-volatile-bitfields -fsync-libcalls}
@end table @end table
...@@ -19307,6 +19308,84 @@ indices used to access arrays are within the declared range. This is ...@@ -19307,6 +19308,84 @@ indices used to access arrays are within the declared range. This is
currently only supported by the Java and Fortran front ends, where currently only supported by the Java and Fortran front ends, where
this option defaults to true and false respectively. this option defaults to true and false respectively.
@item -fstack-reuse=@var{reuse-level}
@opindex fstack_reuse
This option controls stack space reuse for user declared local/auto variables
and compiler generated temporaries. @var{reuse_level} can be @samp{all},
@samp{named_vars}, or @samp{none}. @samp{all} enables stack reuse for all
local variables and temporaries, @samp{named_vars} enables the reuse only for
user defined local variables with names, and @samp{none} disables stack reuse
completely. The default value is @samp{all}. The option is needed when the
program extends the lifetime of a scoped local variable or a compiler generated
temporary beyond the end point defined by the language. When a lifetime of
a variable ends, and if the variable lives in memory, the optimizing compiler
has the freedom to reuse its stack space with other temporaries or scoped
local variables whose live range does not overlap with it. Legacy code extending
local lifetime will likely to break with the stack reuse optimization.
For example,
@smallexample
int *p;
@{
int local1;
p = &local1;
local1 = 10;
....
@}
@{
int local2;
local2 = 20;
...
@}
if (*p == 10) // out of scope use of local1
@{
@}
@end smallexample
Another example:
@smallexample
struct A
@{
A(int k) : i(k), j(k) @{ @}
int i;
int j;
@};
A *ap;
void foo(const A& ar)
@{
ap = &ar;
@}
void bar()
@{
foo(A(10)); // temp object's lifetime ends when foo returns
@{
A a(20);
....
@}
ap->i+= 10; // ap references out of scope temp whose space
// is reused with a. What is the value of ap->i?
@}
@end smallexample
The lifetime of a compiler generated temporary is well defined by the C++
standard. When a lifetime of a temporary ends, and if the temporary lives
in memory, the optimizing compiler has the freedom to reuse its stack
space with other temporaries or scoped local variables whose live range
does not overlap with it. However some of the legacy code relies on
the behavior of older compilers in which temporaries' stack space is
not reused, the aggressive stack reuse can lead to runtime errors. This
option is used to control the temporary stack reuse optimization.
@item -ftrapv @item -ftrapv
@opindex ftrapv @opindex ftrapv
This option generates traps for signed overflow on addition, subtraction, This option generates traps for signed overflow on addition, subtraction,
......
...@@ -106,6 +106,14 @@ enum symbol_visibility ...@@ -106,6 +106,14 @@ enum symbol_visibility
}; };
#endif #endif
/* The stack reuse level. */
enum stack_reuse_level
{
SR_NONE,
SR_NAMED_VARS,
SR_ALL
};
/* The algorithm used for the integrated register allocator (IRA). */ /* The algorithm used for the integrated register allocator (IRA). */
enum ira_algorithm enum ira_algorithm
{ {
......
...@@ -1247,7 +1247,8 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) ...@@ -1247,7 +1247,8 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
&& !DECL_HAS_VALUE_EXPR_P (t) && !DECL_HAS_VALUE_EXPR_P (t)
/* Only care for variables that have to be in memory. Others /* Only care for variables that have to be in memory. Others
will be rewritten into SSA names, hence moved to the top-level. */ will be rewritten into SSA names, hence moved to the top-level. */
&& !is_gimple_reg (t)) && !is_gimple_reg (t)
&& flag_stack_reuse != SR_NONE)
{ {
tree clobber = build_constructor (TREE_TYPE (t), NULL); tree clobber = build_constructor (TREE_TYPE (t), NULL);
TREE_THIS_VOLATILE (clobber) = 1; TREE_THIS_VOLATILE (clobber) = 1;
...@@ -5634,7 +5635,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) ...@@ -5634,7 +5635,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
/* Add a clobber for the temporary going out of scope, like /* Add a clobber for the temporary going out of scope, like
gimplify_bind_expr. */ gimplify_bind_expr. */
if (gimplify_ctxp->in_cleanup_point_expr if (gimplify_ctxp->in_cleanup_point_expr
&& needs_to_live_in_memory (temp)) && needs_to_live_in_memory (temp)
&& flag_stack_reuse == SR_ALL)
{ {
tree clobber = build_constructor (TREE_TYPE (temp), NULL); tree clobber = build_constructor (TREE_TYPE (temp), NULL);
TREE_THIS_VOLATILE (clobber) = true; TREE_THIS_VOLATILE (clobber) = true;
......
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