aboutsummaryrefslogtreecommitdiff
path: root/gcc/reg-stack.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r--gcc/reg-stack.c505
1 files changed, 261 insertions, 244 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index a49d9e9a108..5e5fcc74744 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -224,6 +224,11 @@ enum emit_where
/* The block we're currently working on. */
static basic_block current_block;
+/* In the current_block, whether we're processing the first register
+ stack or call instruction, i.e. the the regstack is currently the
+ same as BLOCK_INFO(current_block)->stack_in. */
+static bool starting_stack_p;
+
/* This is the register file for all register after conversion. */
static rtx
FP_mode_reg[LAST_STACK_REG+1-FIRST_STACK_REG][(int) MAX_MACHINE_MODE];
@@ -237,7 +242,6 @@ static rtx not_a_num;
/* Forward declarations */
static int stack_regs_mentioned_p (rtx pat);
-static void straighten_stack (rtx, stack);
static void pop_stack (stack, int);
static rtx *get_true_reg (rtx *);
@@ -248,7 +252,6 @@ static void replace_reg (rtx *, int);
static void remove_regno_note (rtx, enum reg_note, unsigned int);
static int get_hard_regnum (stack, rtx);
static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where);
-static void emit_swap_insn (rtx, stack, rtx);
static void swap_to_top(rtx, stack, rtx, rtx);
static bool move_for_stack_reg (rtx, stack, rtx);
static bool move_nan_for_stack_reg (rtx, stack, rtx);
@@ -259,14 +262,8 @@ static bool subst_stack_regs_pat (rtx, stack, rtx);
static void subst_asm_stack_regs (rtx, stack);
static bool subst_stack_regs (rtx, stack);
static void change_stack (rtx, stack, stack, enum emit_where);
-static int convert_regs_entry (void);
-static void convert_regs_exit (void);
-static int convert_regs_1 (FILE *, basic_block);
-static int convert_regs_2 (FILE *, basic_block);
-static int convert_regs (FILE *);
static void print_stack (FILE *, stack);
static rtx next_flags_user (rtx);
-static bool compensate_edge (edge, FILE *);
/* Return nonzero if any stack register is mentioned somewhere within PAT. */
@@ -350,8 +347,7 @@ next_flags_user (rtx insn)
return NULL_RTX;
}
-/* Reorganize the stack into ascending numbers,
- after this insn. */
+/* Reorganize the stack into ascending numbers, before this insn. */
static void
straighten_stack (rtx insn, stack regstack)
@@ -371,7 +367,7 @@ straighten_stack (rtx insn, stack regstack)
for (top = temp_stack.top = regstack->top; top >= 0; top--)
temp_stack.reg[top] = FIRST_STACK_REG + temp_stack.top - top;
- change_stack (insn, regstack, &temp_stack, EMIT_AFTER);
+ change_stack (insn, regstack, &temp_stack, EMIT_BEFORE);
}
/* Pop a register from the stack. */
@@ -398,101 +394,6 @@ pop_stack (stack regstack, int regno)
}
}
-/* Convert register usage from "flat" register file usage to a "stack
- register file. FILE is the dump file, if used.
-
- Construct a CFG and run life analysis. Then convert each insn one
- by one. Run a last cleanup_cfg pass, if optimizing, to eliminate
- code duplication created when the converter inserts pop insns on
- the edges. */
-
-bool
-reg_to_stack (FILE *file)
-{
- basic_block bb;
- int i;
- int max_uid;
-
- /* Clean up previous run. */
- stack_regs_mentioned_data = 0;
-
- /* See if there is something to do. Flow analysis is quite
- expensive so we might save some compilation time. */
- for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
- if (regs_ever_live[i])
- break;
- if (i > LAST_STACK_REG)
- return false;
-
- /* Ok, floating point instructions exist. If not optimizing,
- build the CFG and run life analysis.
- Also need to rebuild life when superblock scheduling is done
- as it don't update liveness yet. */
- if (!optimize
- || (flag_sched2_use_superblocks
- && flag_schedule_insns_after_reload))
- {
- count_or_remove_death_notes (NULL, 1);
- life_analysis (file, PROP_DEATH_NOTES);
- }
- mark_dfs_back_edges ();
-
- /* Set up block info for each basic block. */
- alloc_aux_for_blocks (sizeof (struct block_info_def));
- FOR_EACH_BB_REVERSE (bb)
- {
- edge e;
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, bb->preds)
- if (!(e->flags & EDGE_DFS_BACK)
- && e->src != ENTRY_BLOCK_PTR)
- BLOCK_INFO (bb)->predecessors++;
- }
-
- /* Create the replacement registers up front. */
- for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
- {
- enum machine_mode mode;
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
- }
-
- ix86_flags_rtx = gen_rtx_REG (CCmode, FLAGS_REG);
-
- /* A QNaN for initializing uninitialized variables.
-
- ??? We can't load from constant memory in PIC mode, because
- we're inserting these instructions before the prologue and
- the PIC register hasn't been set up. In that case, fall back
- on zero, which we can get from `ldz'. */
-
- if (flag_pic)
- not_a_num = CONST0_RTX (SFmode);
- else
- {
- not_a_num = gen_lowpart (SFmode, GEN_INT (0x7fc00000));
- not_a_num = force_const_mem (SFmode, not_a_num);
- }
-
- /* Allocate a cache for stack_regs_mentioned. */
- max_uid = get_max_uid ();
- VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1,
- "stack_regs_mentioned cache");
-
- convert_regs (file);
-
- free_aux_for_blocks ();
- return true;
-}
-
-
/* Return a pointer to the REG expression within PAT. If PAT is not a
REG, possible enclosed by a conversion rtx, return the inner part of
PAT that stopped the search. */
@@ -965,6 +866,16 @@ emit_swap_insn (rtx insn, stack regstack, rtx reg)
return;
}
+ /* Avoid emitting the swap if this is the first register stack insn
+ of the current_block. Instead update the current_block's stack_in
+ and let compensate edges take care of this for us. */
+ if (current_block && starting_stack_p)
+ {
+ BLOCK_INFO (current_block)->stack_in = *regstack;
+ starting_stack_p = false;
+ return;
+ }
+
swap_rtx = gen_swapxf (FP_MODE_REG (hard_regno, XFmode),
FP_MODE_REG (FIRST_STACK_REG, XFmode));
@@ -1231,9 +1142,9 @@ swap_rtx_condition (rtx insn)
pat = PATTERN (insn);
}
- /* See if this is, or ends in, a fnstsw, aka unspec 9. If so, we're
- not doing anything with the cc value right now. We may be able to
- search for one though. */
+ /* See if this is, or ends in, a fnstsw. If so, we're not doing anything
+ with the cc value right now. We may be able to search for one
+ though. */
if (GET_CODE (pat) == SET
&& GET_CODE (SET_SRC (pat)) == UNSPEC
@@ -1252,9 +1163,13 @@ swap_rtx_condition (rtx insn)
return 0;
}
+ /* We haven't found it. */
+ if (insn == BB_END (current_block))
+ return 0;
+
/* So we've found the insn using this value. If it is anything
- other than sahf, aka unspec 10, or the value does not die
- (meaning we'd have to search further), then we must give up. */
+ other than sahf or the value does not die (meaning we'd have
+ to search further), then we must give up. */
pat = PATTERN (insn);
if (GET_CODE (pat) != SET
|| GET_CODE (SET_SRC (pat)) != UNSPEC
@@ -2302,7 +2217,7 @@ subst_stack_regs (rtx insn, stack regstack)
if (top >= 0)
{
- straighten_stack (PREV_INSN (insn), regstack);
+ straighten_stack (insn, regstack);
/* Now mark the arguments as dead after the call. */
@@ -2393,6 +2308,19 @@ change_stack (rtx insn, stack old, stack new, enum emit_where where)
int reg;
int update_end = 0;
+ /* Stack adjustments for the first insn in a block update the
+ current_block's stack_in instead of inserting insns directly.
+ compensate_edges will add the necessary code later. */
+ if (current_block
+ && starting_stack_p
+ && where == EMIT_BEFORE)
+ {
+ BLOCK_INFO (current_block)->stack_in = *new;
+ starting_stack_p = false;
+ *old = *new;
+ return;
+ }
+
/* We will be inserting new insns "backwards". If we are to insert
after INSN, find the next insn, and insert before it. */
@@ -2604,25 +2532,6 @@ convert_regs_entry (void)
int inserted = 0;
edge e;
edge_iterator ei;
- basic_block block;
-
- FOR_EACH_BB_REVERSE (block)
- {
- block_info bi = BLOCK_INFO (block);
- int reg;
-
- /* Set current register status at last instruction `uninitialized'. */
- bi->stack_in.top = -2;
-
- /* Copy live_at_end and live_at_start into temporaries. */
- for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
- {
- if (REGNO_REG_SET_P (block->global_live_at_end, reg))
- SET_HARD_REG_BIT (bi->out_reg_set, reg);
- if (REGNO_REG_SET_P (block->global_live_at_start, reg))
- SET_HARD_REG_BIT (bi->stack_in.reg_set, reg);
- }
- }
/* Load something into each stack register live at function entry.
Such live registers can be caused by uninitialized variables or
@@ -2694,9 +2603,29 @@ convert_regs_exit (void)
}
}
-/* Adjust the stack of this block on exit to match the stack of the
- target block, or copy stack info into the stack of the successor
- of the successor hasn't been processed yet. */
+/* Copy the stack info from the end of edge E's source block to the
+ start of E's destination block. */
+
+static void
+propagate_stack (edge e)
+{
+ stack src_stack = &BLOCK_INFO (e->src)->stack_out;
+ stack dest_stack = &BLOCK_INFO (e->dest)->stack_in;
+ int reg;
+
+ /* Preserve the order of the original stack, but check whether
+ any pops are needed. */
+ dest_stack->top = -1;
+ for (reg = 0; reg <= src_stack->top; ++reg)
+ if (TEST_HARD_REG_BIT (dest_stack->reg_set, src_stack->reg[reg]))
+ dest_stack->reg[++dest_stack->top] = src_stack->reg[reg];
+}
+
+
+/* Adjust the stack of edge E's source block on exit to match the stack
+ of it's target block upon input. The stack layouts of both blocks
+ should have been defined by now. */
+
static bool
compensate_edge (edge e, FILE *file)
{
@@ -2711,50 +2640,27 @@ compensate_edge (edge e, FILE *file)
if (file)
fprintf (file, "Edge %d->%d: ", block->index, target->index);
- if (target_stack->top == -2)
+ gcc_assert (target_stack->top != -2);
+
+ /* Check whether stacks are identical. */
+ if (target_stack->top == regstack.top)
{
- /* The target block hasn't had a stack order selected.
- We need merely ensure that no pops are needed. */
- for (reg = regstack.top; reg >= 0; --reg)
- if (!TEST_HARD_REG_BIT (target_stack->reg_set, regstack.reg[reg]))
+ for (reg = target_stack->top; reg >= 0; --reg)
+ if (target_stack->reg[reg] != regstack.reg[reg])
break;
if (reg == -1)
{
if (file)
- fprintf (file, "new block; copying stack position\n");
-
- /* change_stack kills values in regstack. */
- tmpstack = regstack;
-
- change_stack (BB_END (block), &tmpstack, target_stack, EMIT_AFTER);
+ fprintf (file, "no changes needed\n");
return false;
}
-
- if (file)
- fprintf (file, "new block; pops needed\n");
}
- else
- {
- if (target_stack->top == regstack.top)
- {
- for (reg = target_stack->top; reg >= 0; --reg)
- if (target_stack->reg[reg] != regstack.reg[reg])
- break;
- if (reg == -1)
- {
- if (file)
- fprintf (file, "no changes needed\n");
- return false;
- }
- }
-
- if (file)
- {
- fprintf (file, "correcting stack to ");
- print_stack (file, target_stack);
- }
+ if (file)
+ {
+ fprintf (file, "correcting stack to ");
+ print_stack (file, target_stack);
}
/* Care for non-call EH edges specially. The normal return path have
@@ -2829,72 +2735,97 @@ compensate_edge (edge e, FILE *file)
return false;
}
+/* Traverse all non-entry edges in the CFG, and emit the necessary
+ edge compensation code to change the stack from stack_out of the
+ source block to the stack_in of the destination block. */
+
+static bool
+compensate_edges (FILE *file)
+{
+ bool inserted = false;
+ basic_block bb;
+
+ starting_stack_p = false;
+
+ FOR_EACH_BB (bb)
+ if (bb != ENTRY_BLOCK_PTR)
+ {
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ inserted |= compensate_edge (e, file);
+ }
+ return inserted;
+}
+
+/* Select the better of two edges E1 and E2 to use to determine the
+ stack layout for their shared destination basic block. This is
+ typically the more frequently executed. The edge E1 may be NULL
+ (in which case E2 is returned), but E2 is always non-NULL. */
+
+static edge
+better_edge (edge e1, edge e2)
+{
+ if (!e1)
+ return e2;
+
+ if (EDGE_FREQUENCY (e1) > EDGE_FREQUENCY (e2))
+ return e1;
+ if (EDGE_FREQUENCY (e1) < EDGE_FREQUENCY (e2))
+ return e2;
+
+ if (e1->count > e2->count)
+ return e1;
+ if (e1->count < e2->count)
+ return e2;
+
+ /* Prefer critical edges to minimize inserting compensation code on
+ critical edges. */
+
+ if (EDGE_CRITICAL_P (e1) != EDGE_CRITICAL_P (e2))
+ return EDGE_CRITICAL_P (e1) ? e1 : e2;
+
+ /* Avoid non-deterministic behaviour. */
+ return (e1->src->index < e2->src->index) ? e1 : e2;
+}
+
/* Convert stack register references in one block. */
-static int
+static void
convert_regs_1 (FILE *file, basic_block block)
{
struct stack_def regstack;
block_info bi = BLOCK_INFO (block);
- int inserted, reg;
+ int reg;
rtx insn, next;
- edge e, beste = NULL;
bool control_flow_insn_deleted = false;
- edge_iterator ei;
- inserted = 0;
any_malformed_asm = false;
- /* Find the edge we will copy stack from. It should be the most frequent
- one as it will get cheapest after compensation code is generated,
- if multiple such exists, take one with largest count, prefer critical
- one (as splitting critical edges is more expensive), or one with lowest
- index, to avoid random changes with different orders of the edges. */
- FOR_EACH_EDGE (e, ei, block->preds)
- {
- if (e->flags & EDGE_DFS_BACK)
- ;
- else if (! beste)
- beste = e;
- else if (EDGE_FREQUENCY (beste) < EDGE_FREQUENCY (e))
- beste = e;
- else if (EDGE_FREQUENCY (beste) > EDGE_FREQUENCY (e))
- ;
- else if (beste->count < e->count)
- beste = e;
- else if (beste->count > e->count)
- ;
- else if ((EDGE_CRITICAL_P (e) != 0)
- != (EDGE_CRITICAL_P (beste) != 0))
- {
- if (EDGE_CRITICAL_P (e))
- beste = e;
- }
- else if (e->src->index < beste->src->index)
- beste = e;
- }
-
- /* Initialize stack at block entry. */
+ /* Choose an initial stack layout, if one hasn't already been chosen. */
if (bi->stack_in.top == -2)
{
+ edge e, beste = NULL;
+ edge_iterator ei;
+
+ /* Select the best incoming edge (typically the most frequent) to
+ use as a template for this basic block. */
+ FOR_EACH_EDGE (e, ei, block->preds)
+ if (BLOCK_INFO (e->src)->done)
+ beste = better_edge (beste, e);
+
if (beste)
- inserted |= compensate_edge (beste, file);
+ propagate_stack (beste);
else
{
/* No predecessors. Create an arbitrary input stack. */
- int reg;
-
bi->stack_in.top = -1;
for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg)
if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg))
bi->stack_in.reg[++bi->stack_in.top] = reg;
}
}
- else
- /* Entry blocks do have stack already initialized. */
- beste = NULL;
-
- current_block = block;
if (file)
{
@@ -2904,8 +2835,11 @@ convert_regs_1 (FILE *file, basic_block block)
/* Process all insns in this block. Keep track of NEXT so that we
don't process insns emitted while substituting in INSN. */
+ current_block = block;
next = BB_HEAD (block);
regstack = bi->stack_in;
+ starting_stack_p = true;
+
do
{
insn = next;
@@ -2928,6 +2862,7 @@ convert_regs_1 (FILE *file, basic_block block)
print_stack (file, &regstack);
}
control_flow_insn_deleted |= subst_stack_regs (insn, &regstack);
+ starting_stack_p = false;
}
}
while (next);
@@ -2993,38 +2928,14 @@ convert_regs_1 (FILE *file, basic_block block)
gcc_assert (any_malformed_asm);
win:
bi->stack_out = regstack;
-
- /* Compensate the back edges, as those wasn't visited yet. */
- FOR_EACH_EDGE (e, ei, block->succs)
- {
- if (e->flags & EDGE_DFS_BACK
- || (e->dest == EXIT_BLOCK_PTR))
- {
- gcc_assert (BLOCK_INFO (e->dest)->done
- || e->dest == block);
- inserted |= compensate_edge (e, file);
- }
- }
- FOR_EACH_EDGE (e, ei, block->preds)
- {
- if (e != beste && !(e->flags & EDGE_DFS_BACK)
- && e->src != ENTRY_BLOCK_PTR)
- {
- gcc_assert (BLOCK_INFO (e->src)->done);
- inserted |= compensate_edge (e, file);
- }
- }
-
- return inserted;
}
/* Convert registers in all blocks reachable from BLOCK. */
-static int
+static void
convert_regs_2 (FILE *file, basic_block block)
{
basic_block *stack, *sp;
- int inserted;
/* We process the blocks in a top-down manner, in a way such that one block
is only processed after all its predecessors. The number of predecessors
@@ -3035,7 +2946,6 @@ convert_regs_2 (FILE *file, basic_block block)
*sp++ = block;
- inserted = 0;
do
{
edge e;
@@ -3064,21 +2974,19 @@ convert_regs_2 (FILE *file, basic_block block)
*sp++ = e->dest;
}
- inserted |= convert_regs_1 (file, block);
+ convert_regs_1 (file, block);
BLOCK_INFO (block)->done = 1;
}
while (sp != stack);
free (stack);
-
- return inserted;
}
/* Traverse all basic blocks in a function, converting the register
references in each insn from the "flat" register file that gcc uses,
to the stack-like registers the 387 uses. */
-static int
+static void
convert_regs (FILE *file)
{
int inserted;
@@ -3099,7 +3007,7 @@ convert_regs (FILE *file)
/* Process all blocks reachable from all entry points. */
FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
- inserted |= convert_regs_2 (file, e->dest);
+ convert_regs_2 (file, e->dest);
/* ??? Process all unreachable blocks. Though there's no excuse
for keeping these even when not optimizing. */
@@ -3108,8 +3016,11 @@ convert_regs (FILE *file)
block_info bi = BLOCK_INFO (b);
if (! bi->done)
- inserted |= convert_regs_2 (file, b);
+ convert_regs_2 (file, b);
}
+
+ inserted |= compensate_edges (file);
+
clear_aux_for_blocks ();
fixup_abnormal_edges ();
@@ -3118,8 +3029,114 @@ convert_regs (FILE *file)
if (file)
fputc ('\n', file);
+}
+
+/* Convert register usage from "flat" register file usage to a "stack
+ register file. FILE is the dump file, if used.
- return inserted;
+ Construct a CFG and run life analysis. Then convert each insn one
+ by one. Run a last cleanup_cfg pass, if optimizing, to eliminate
+ code duplication created when the converter inserts pop insns on
+ the edges. */
+
+bool
+reg_to_stack (FILE *file)
+{
+ basic_block bb;
+ int i;
+ int max_uid;
+
+ /* Clean up previous run. */
+ stack_regs_mentioned_data = 0;
+
+ /* See if there is something to do. Flow analysis is quite
+ expensive so we might save some compilation time. */
+ for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
+ if (regs_ever_live[i])
+ break;
+ if (i > LAST_STACK_REG)
+ return false;
+
+ /* Ok, floating point instructions exist. If not optimizing,
+ build the CFG and run life analysis.
+ Also need to rebuild life when superblock scheduling is done
+ as it don't update liveness yet. */
+ if (!optimize
+ || (flag_sched2_use_superblocks
+ && flag_schedule_insns_after_reload))
+ {
+ count_or_remove_death_notes (NULL, 1);
+ life_analysis (file, PROP_DEATH_NOTES);
+ }
+ mark_dfs_back_edges ();
+
+ /* Set up block info for each basic block. */
+ alloc_aux_for_blocks (sizeof (struct block_info_def));
+ FOR_EACH_BB (bb)
+ {
+ block_info bi = BLOCK_INFO (bb);
+ edge_iterator ei;
+ edge e;
+ int reg;
+
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ if (!(e->flags & EDGE_DFS_BACK)
+ && e->src != ENTRY_BLOCK_PTR)
+ bi->predecessors++;
+
+ /* Set current register status at last instruction `uninitialized'. */
+ bi->stack_in.top = -2;
+
+ /* Copy live_at_end and live_at_start into temporaries. */
+ for (reg = FIRST_STACK_REG; reg <= LAST_STACK_REG; reg++)
+ {
+ if (REGNO_REG_SET_P (bb->global_live_at_end, reg))
+ SET_HARD_REG_BIT (bi->out_reg_set, reg);
+ if (REGNO_REG_SET_P (bb->global_live_at_start, reg))
+ SET_HARD_REG_BIT (bi->stack_in.reg_set, reg);
+ }
+ }
+
+ /* Create the replacement registers up front. */
+ for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
+ {
+ enum machine_mode mode;
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ FP_MODE_REG (i, mode) = gen_rtx_REG (mode, i);
+ }
+
+ ix86_flags_rtx = gen_rtx_REG (CCmode, FLAGS_REG);
+
+ /* A QNaN for initializing uninitialized variables.
+
+ ??? We can't load from constant memory in PIC mode, because
+ we're inserting these instructions before the prologue and
+ the PIC register hasn't been set up. In that case, fall back
+ on zero, which we can get from `ldz'. */
+
+ if (flag_pic)
+ not_a_num = CONST0_RTX (SFmode);
+ else
+ {
+ not_a_num = gen_lowpart (SFmode, GEN_INT (0x7fc00000));
+ not_a_num = force_const_mem (SFmode, not_a_num);
+ }
+
+ /* Allocate a cache for stack_regs_mentioned. */
+ max_uid = get_max_uid ();
+ VARRAY_CHAR_INIT (stack_regs_mentioned_data, max_uid + 1,
+ "stack_regs_mentioned cache");
+
+ convert_regs (file);
+
+ free_aux_for_blocks ();
+ return true;
}
#endif /* STACK_REGS */