]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Implement -freuse-stack= option
authorXinliang David Li <davidxl@google.com>
Tue, 10 Jul 2012 20:26:38 +0000 (20:26 +0000)
committerXinliang David Li <davidxl@gcc.gnu.org>
Tue, 10 Jul 2012 20:26:38 +0000 (20:26 +0000)
From-SVN: r189413

gcc/ChangeLog
gcc/common.opt
gcc/doc/invoke.texi
gcc/flag-types.h
gcc/gimplify.c

index ddf70e1be30329118f003d719ea6beb876d2cccc..f49066cbc05a488b88e50df230d860a17b9094f4 100644 (file)
@@ -1,3 +1,12 @@
+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>
 
        * config/arm/arm.md (movsi): Don't split symbol refs here.
index 12f557acb4f7ff5e501c475697c647d758f6534f..4761d51e8d84ed624d8304f6a40168efa9db4cad 100644 (file)
@@ -1247,6 +1247,22 @@ fif-conversion2
 Common Report Var(flag_if_conversion2) Optimization
 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
 Common Report Var(flag_tree_loop_if_convert) Init(-1) Optimization
 Convert conditional jumps in innermost loops to branchless equivalents
index c8bfa3cb0bdb4c5b5b6e8f519a8e164f61a0f91a..ca313bea9f198606a8ed4b62c9a7e7ce02304c24 100644 (file)
@@ -990,6 +990,7 @@ See S/390 and zSeries Options.
 -fstack-limit-register=@var{reg}  -fstack-limit-symbol=@var{sym} @gol
 -fno-stack-limit -fsplit-stack @gol
 -fleading-underscore  -ftls-model=@var{model} @gol
+-fstack-reuse=@var{reuse_level} @gol
 -ftrapv  -fwrapv  -fbounds-check @gol
 -fvisibility -fstrict-volatile-bitfields -fsync-libcalls}
 @end table
@@ -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
 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
 @opindex ftrapv
 This option generates traps for signed overflow on addition, subtraction,
index f757423e56a57df51507beabcbfcd07ddf059d48..b503c9f4f198672ab5e06e761f3b8c49c82412a9 100644 (file)
@@ -106,6 +106,14 @@ enum symbol_visibility
 };
 #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).  */
 enum ira_algorithm
 {
index 9bf4ead84ed202d2a84b0fa870b38822ed3c0ba9..bd3642c8c41f37483053427ac4a80e1a0a92e622 100644 (file)
@@ -1247,7 +1247,8 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
          && !DECL_HAS_VALUE_EXPR_P (t)
          /* Only care for variables that have to be in memory.  Others
             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_THIS_VOLATILE (clobber) = 1;
@@ -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
         gimplify_bind_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_THIS_VOLATILE (clobber) = true;