aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.4.3/gcc/cfgexpand.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.4.3/gcc/cfgexpand.c')
-rw-r--r--gcc-4.4.3/gcc/cfgexpand.c171
1 files changed, 118 insertions, 53 deletions
diff --git a/gcc-4.4.3/gcc/cfgexpand.c b/gcc-4.4.3/gcc/cfgexpand.c
index d63701a7d..66acd3c75 100644
--- a/gcc-4.4.3/gcc/cfgexpand.c
+++ b/gcc-4.4.3/gcc/cfgexpand.c
@@ -42,7 +42,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "value-prof.h"
#include "target.h"
-
+#include "tree-stack-overlay.h"
/* Return an expression tree corresponding to the RHS of GIMPLE
statement STMT. */
@@ -871,6 +871,21 @@ dump_stack_var_partition (void)
}
}
+static void
+sort_stack_vars (void)
+{
+ size_t si, n = stack_vars_num;
+
+ stack_vars_sorted = XNEWVEC (size_t, stack_vars_num);
+ for (si = 0; si < n; ++si)
+ stack_vars_sorted[si] = si;
+
+ if (n == 1)
+ return;
+
+ qsort (stack_vars_sorted, n, sizeof (size_t), stack_var_size_cmp);
+}
+
/* Assign rtl to DECL at frame offset OFFSET. */
static void
@@ -896,6 +911,34 @@ expand_one_stack_var_at (tree decl, HOST_WIDE_INT offset)
set_mem_attributes (x, decl, true);
SET_DECL_RTL (decl, x);
+ if (flag_early_stack_alloc)
+ {
+ /* If this decl is synthesized by stack_overlay pass, copy the RTL
+ to the original DECLs and remove this decl from BLOCK_VARS to
+ generate proper debug info. */
+ VEC(tree,gc) *orig_vars = get_original_stack_vars (decl);
+ if (VEC_length(tree,orig_vars))
+ {
+ tree t, outer_block = DECL_INITIAL (current_function_decl);
+ int ix=0;
+ /* Set RTL to original variables. */
+ for (ix = 0; VEC_iterate(tree,orig_vars,ix,t); ix++)
+ SET_DECL_RTL (t, x);
+ /* Remove decl from BLOCK_VARS. */
+ t = BLOCK_VARS (outer_block);
+ if (t == decl)
+ BLOCK_VARS (outer_block) = TREE_CHAIN (t);
+ else
+ {
+ for (; t ; t = TREE_CHAIN (t))
+ if (TREE_CHAIN (t) == decl)
+ {
+ TREE_CHAIN (t) = TREE_CHAIN (decl);
+ break;
+ }
+ }
+ }
+ }
}
/* A subroutine of expand_used_vars. Give each partition representative
@@ -1045,6 +1088,11 @@ defer_stack_allocation (tree var, bool toplevel)
if (flag_stack_protect)
return true;
+ /* If stack protection is not required and variable coalescing happens
+ in an earlier pass, no need to defer allocation. */
+ if (flag_early_stack_alloc)
+ return false;
+
/* Variables in the outermost scope automatically conflict with
every other variable. The only reason to want to defer them
at all is that, after sorting, we can more efficiently pack
@@ -1064,6 +1112,7 @@ defer_stack_allocation (tree var, bool toplevel)
return true;
}
+
/* A subroutine of expand_used_vars. Expand one variable according to
its flavor. Variables to be placed on the stack are not actually
expanded yet, merely recorded.
@@ -1282,12 +1331,25 @@ stack_protect_decl_phase (tree decl)
else
ret = (bits & SPCT_HAS_LARGE_CHAR_ARRAY) != 0;
- if (ret)
+ if (!flag_early_stack_alloc && ret)
has_protected_decls = true;
return ret;
}
+static bool
+need_stack_protection (void)
+{
+ size_t i, n = stack_vars_num;
+
+ if (!flag_stack_protect)
+ return false;
+ for (i = 0; i < n; ++i)
+ if (stack_protect_decl_phase (stack_vars[i].decl))
+ return true;
+ return false;
+}
+
/* Two helper routines that check for phase 1 and phase 2. These are used
as callbacks for expand_stack_vars. */
@@ -1475,35 +1537,37 @@ expand_used_vars (void)
for (; t; t = next)
{
tree var = TREE_VALUE (t);
- bool expand_now = false;
+ bool expand_now = flag_early_stack_alloc;
next = TREE_CHAIN (t);
-
- /* We didn't set a block for static or extern because it's hard
- to tell the difference between a global variable (re)declared
- in a local scope, and one that's really declared there to
- begin with. And it doesn't really matter much, since we're
- not giving them stack space. Expand them now. */
- if (TREE_STATIC (var) || DECL_EXTERNAL (var))
- expand_now = true;
-
- /* Any variable that could have been hoisted into an SSA_NAME
- will have been propagated anywhere the optimizers chose,
- i.e. not confined to their original block. Allocate them
- as if they were defined in the outermost scope. */
- else if (is_gimple_reg (var))
- expand_now = true;
-
- /* If the variable is not associated with any block, then it
- was created by the optimizers, and could be live anywhere
- in the function. */
- else if (TREE_USED (var))
- expand_now = true;
-
- /* Finally, mark all variables on the list as used. We'll use
- this in a moment when we expand those associated with scopes. */
- TREE_USED (var) = 1;
-
+ if (!flag_early_stack_alloc)
+ {
+ /* We didn't set a block for static or extern because it's hard
+ to tell the difference between a global variable (re)declared
+ in a local scope, and one that's really declared there to
+ begin with. And it doesn't really matter much, since we're
+ not giving them stack space. Expand them now. */
+ if (TREE_STATIC (var) || DECL_EXTERNAL (var))
+ expand_now = true;
+
+ /* Any variable that could have been hoisted into an SSA_NAME
+ will have been propagated anywhere the optimizers chose,
+ i.e. not confined to their original block. Allocate them
+ as if they were defined in the outermost scope. */
+ else if (is_gimple_reg (var))
+ expand_now = true;
+
+ /* If the variable is not associated with any block, then it
+ was created by the optimizers, and could be live anywhere
+ in the function. */
+ else if (TREE_USED (var))
+ expand_now = true;
+
+ /* Finally, mark all variables on the list as used. We'll use
+ this in a moment when we expand those associated with scopes. */
+ TREE_USED (var) = 1;
+
+ }
if (expand_now)
{
expand_one_var (var, true, true);
@@ -1525,11 +1589,14 @@ expand_used_vars (void)
ggc_free (t);
}
- /* At this point, all variables within the block tree with TREE_USED
- set are actually used by the optimized function. Lay them out. */
- expand_used_vars_for_block (outer_block, true);
+ if (flag_early_stack_alloc)
+ has_protected_decls = need_stack_protection ();
+ else
+ /* At this point, all variables within the block tree with TREE_USED
+ set are actually used by the optimized function. Lay them out. */
+ expand_used_vars_for_block (outer_block, true);
- if (stack_vars_num > 0)
+ if (!flag_early_stack_alloc && stack_vars_num > 0)
{
/* Due to the way alias sets work, no variables with non-conflicting
alias sets may be assigned the same address. Add conflicts to
@@ -1558,6 +1625,8 @@ expand_used_vars (void)
/* Assign rtl to each variable based on these partitions. */
if (stack_vars_num > 0)
{
+ if (flag_early_stack_alloc)
+ sort_stack_vars ();
/* Reorder decls to be protected by iterating over the variables
array multiple times, and allocating out of each phase in turn. */
/* ??? We could probably integrate this into the qsort we did
@@ -2245,8 +2314,18 @@ expand_stack_alignment (void)
|| crtl->has_nonlocal_goto)
crtl->need_drap = true;
- gcc_assert (crtl->stack_alignment_needed
- <= crtl->stack_alignment_estimated);
+ /* Call update_stack_boundary here again to update incoming stack
+ boundary. It may set incoming stack alignment to a different
+ value after RTL expansion. TARGET_FUNCTION_OK_FOR_SIBCALL may
+ use the minimum incoming stack alignment to check if it is OK
+ to perform sibcall optimization since sibcall optimization will
+ only align the outgoing stack to incoming stack boundary. */
+ if (targetm.calls.update_stack_boundary)
+ targetm.calls.update_stack_boundary ();
+
+ /* The incoming stack frame has to be aligned at least at
+ parm_stack_boundary. */
+ gcc_assert (crtl->parm_stack_boundary <= INCOMING_STACK_BOUNDARY);
/* Update crtl->stack_alignment_estimated and use it later to align
stack. We check PREFERRED_STACK_BOUNDARY if there may be non-call
@@ -2262,6 +2341,9 @@ expand_stack_alignment (void)
if (preferred_stack_boundary > crtl->stack_alignment_needed)
crtl->stack_alignment_needed = preferred_stack_boundary;
+ gcc_assert (crtl->stack_alignment_needed
+ <= crtl->stack_alignment_estimated);
+
crtl->stack_realign_needed
= INCOMING_STACK_BOUNDARY < crtl->stack_alignment_estimated;
crtl->stack_realign_tried = crtl->stack_realign_needed;
@@ -2333,7 +2415,7 @@ gimple_expand_cfg (void)
targetm.expand_to_rtl_hook ();
crtl->stack_alignment_needed = STACK_BOUNDARY;
crtl->max_used_stack_slot_alignment = STACK_BOUNDARY;
- crtl->stack_alignment_estimated = STACK_BOUNDARY;
+ crtl->stack_alignment_estimated = 0;
crtl->preferred_stack_boundary = STACK_BOUNDARY;
cfun->cfg->max_jumptable_ents = 0;
@@ -2368,23 +2450,6 @@ gimple_expand_cfg (void)
if (crtl->stack_protect_guard)
stack_protect_prologue ();
- /* Update stack boundary if needed. */
- if (SUPPORTS_STACK_ALIGNMENT)
- {
- /* Call update_stack_boundary here to update incoming stack
- boundary before TARGET_FUNCTION_OK_FOR_SIBCALL is called.
- TARGET_FUNCTION_OK_FOR_SIBCALL needs to know the accurate
- incoming stack alignment to check if it is OK to perform
- sibcall optimization since sibcall optimization will only
- align the outgoing stack to incoming stack boundary. */
- if (targetm.calls.update_stack_boundary)
- targetm.calls.update_stack_boundary ();
-
- /* The incoming stack frame has to be aligned at least at
- parm_stack_boundary. */
- gcc_assert (crtl->parm_stack_boundary <= INCOMING_STACK_BOUNDARY);
- }
-
/* Register rtl specific functions for cfg. */
rtl_register_cfg_hooks ();