/* Expands front end tree to back end RTL for GNU C-Compiler
- Copyright (C) 1987, 1988, 1989, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1991, 1992 Free Software Foundation, Inc.
This file is part of GNU CC.
static void optimize_bit_field ();
static void instantiate_decls ();
static void instantiate_decls_1 ();
+static void instantiate_decl ();
static int instantiate_virtual_regs_1 ();
static rtx fixup_memory_subreg ();
static rtx walk_fixup_memory_subreg ();
/* Process all parameters of the function. */
for (decl = DECL_ARGUMENTS (fndecl); decl; decl = TREE_CHAIN (decl))
{
- if (DECL_RTL (decl) && GET_CODE (DECL_RTL (decl)) == MEM)
- instantiate_virtual_regs_1 (&XEXP (DECL_RTL (decl), 0),
- (valid_only ? DECL_RTL (decl) : NULL_RTX),
- 0);
- if (DECL_INCOMING_RTL (decl)
- && GET_CODE (DECL_INCOMING_RTL (decl)) == MEM)
- instantiate_virtual_regs_1 (&XEXP (DECL_INCOMING_RTL (decl), 0),
- (valid_only ? DECL_INCOMING_RTL (decl)
- : NULL_RTX),
- 0);
+ instantiate_decl (DECL_RTL (decl), int_size_in_bytes (TREE_TYPE (decl)),
+ valid_only);
+ instantiate_decl (DECL_INCOMING_RTL (decl),
+ int_size_in_bytes (TREE_TYPE (decl)), valid_only);
}
/* Now process all variables defined in the function or its subblocks. */
tree t;
for (t = BLOCK_VARS (let); t; t = TREE_CHAIN (t))
- if (DECL_RTL (t) && GET_CODE (DECL_RTL (t)) == MEM)
- instantiate_virtual_regs_1 (& XEXP (DECL_RTL (t), 0),
- valid_only ? DECL_RTL (t) : NULL_RTX, 0);
+ instantiate_decl (DECL_RTL (t), int_size_in_bytes (TREE_TYPE (t)),
+ valid_only);
/* Process all subblocks. */
for (t = BLOCK_SUBBLOCKS (let); t; t = TREE_CHAIN (t))
instantiate_decls_1 (t, valid_only);
}
+
+/* Subroutine of the preceeding procedures: Given RTL representing a
+ decl and the size of the object, do any instantiation required.
+
+ If VALID_ONLY is non-zero, it means that the RTL should only be
+ changed if the new address is valid. */
+
+static void
+instantiate_decl (x, size, valid_only)
+ rtx x;
+ int size;
+ int valid_only;
+{
+ enum machine_mode mode;
+ rtx addr;
+
+ /* If this is not a MEM, no need to do anything. Similarly if the
+ address is a constant or a register that is not a virtual register. */
+
+ if (x == 0 || GET_CODE (x) != MEM)
+ return;
+
+ addr = XEXP (x, 0);
+ if (CONSTANT_P (addr)
+ || (GET_CODE (addr) == REG
+ && (REGNO (addr) < FIRST_VIRTUAL_REGISTER
+ || REGNO (addr) > LAST_VIRTUAL_REGISTER)))
+ return;
+
+ /* If we should only do this if the address is valid, copy the address.
+ We need to do this so we can undo any changes that might make the
+ address invalid. This copy is unfortunate, but probably can't be
+ avoided. */
+
+ if (valid_only)
+ addr = copy_rtx (addr);
+
+ instantiate_virtual_regs_1 (&addr, NULL_RTX, 0);
+
+ if (! valid_only)
+ return;
+
+ /* Now verify that the resulting address is valid for every integer or
+ floating-point mode up to and including SIZE bytes long. We do this
+ since the object might be accessed in any mode and frame addresses
+ are shared. */
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
+ mode = GET_MODE_WIDER_MODE (mode))
+ if (! memory_address_p (mode, addr))
+ return;
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+ mode != VOIDmode && GET_MODE_SIZE (mode) <= size;
+ mode = GET_MODE_WIDER_MODE (mode))
+ if (! memory_address_p (mode, addr))
+ return;
+
+ /* Otherwise, put back the address, now that we have updated it and we
+ know it is valid. */
+
+ XEXP (x, 0) = addr;
+}
\f
/* Given a pointer to a piece of rtx and an optional pointer to the
containing object, instantiate any virtual registers present in it.
passed_mode = TYPE_MODE (passed_type);
nominal_mode = TYPE_MODE (TREE_TYPE (parm));
+ /* If the parm's mode is VOID, its value doesn't matter,
+ and avoid the usual things like emit_move_insn that could crash. */
+ if (nominal_mode == VOIDmode)
+ {
+ DECL_INCOMING_RTL (parm) = DECL_RTL (parm) = const0_rtx;
+ continue;
+ }
+
#ifdef FUNCTION_ARG_PASS_BY_REFERENCE
/* See if this arg was passed by invisible reference. */
if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, passed_mode,
}
DECL_RTL (parm) = stack_parm;
}
- else if (! (
-#if 0 /* This change was turned off because it makes compilation bigger. */
- !optimize
-#else /* It's not clear why the following was replaced. */
- /* Obsoleted by preceding line. */
- (obey_regdecls && ! DECL_REGISTER (parm)
+ else if (! ((obey_regdecls && ! DECL_REGISTER (parm)
&& ! DECL_INLINE (fndecl))
-#endif
/* layout_decl may set this. */
|| TREE_ADDRESSABLE (parm)
|| TREE_SIDE_EFFECTS (parm)
else
emit_move_insn (parmreg, validize_mem (entry_parm));
+ /* If we were passed a pointer but the actual value
+ can safely live in a register, put it in one. */
+ if (passed_pointer && TYPE_MODE (TREE_TYPE (parm)) != BLKmode
+ && ! ((obey_regdecls && ! DECL_REGISTER (parm)
+ && ! DECL_INLINE (fndecl))
+ /* layout_decl may set this. */
+ || TREE_ADDRESSABLE (parm)
+ || TREE_SIDE_EFFECTS (parm)
+ /* If -ffloat-store specified, don't put explicit
+ float variables into registers. */
+ || (flag_float_store
+ && TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE)))
+ {
+ /* We can't use nominal_mode, because it will have been set to
+ Pmode above. We must use the actual mode of the parm. */
+ parmreg = gen_reg_rtx (TYPE_MODE (TREE_TYPE (parm)));
+ emit_move_insn (parmreg, DECL_RTL (parm));
+ DECL_RTL (parm) = parmreg;
+ }
+
/* In any case, record the parm's desired stack location
in case we later discover it must live in the stack. */
if (REGNO (parmreg) >= nparmregs)
tree top_block;
rtx insns;
{
- int n_blocks = all_blocks (top_block, 0);
- tree *block_vector = (tree *) alloca (n_blocks * sizeof (tree));
- int *block_stack = (int *) alloca (n_blocks * sizeof (int));
+ int n_blocks;
+ tree *block_vector;
+ int *block_stack;
int depth = 0;
int next_block_number = 0;
int current_block_number = 0;
rtx insn;
+ if (top_block == 0)
+ return 0;
+
+ n_blocks = all_blocks (top_block, 0);
+ block_vector = (tree *) xmalloc (n_blocks * sizeof (tree));
+ block_stack = (int *) alloca (n_blocks * sizeof (int));
+
all_blocks (top_block, block_vector);
for (insn = insns; insn; insn = NEXT_INSN (insn))
{
block_stack[depth++] = current_block_number;
current_block_number = next_block_number;
- SET_NOTE_BLOCK_NUMBER (insn, next_block_number++);
+ NOTE_BLOCK_NUMBER (insn) = next_block_number++;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
{
current_block_number = block_stack[--depth];
- SET_NOTE_BLOCK_NUMBER (insn, current_block_number);
+ NOTE_BLOCK_NUMBER (insn) = current_block_number;
}
}
/* Given BLOCK_VECTOR which was returned by identify_blocks,
and a revised instruction chain, rebuild the tree structure
of BLOCK nodes to correspond to the new order of RTL.
+ The new block tree is inserted below TOP_BLOCK.
Returns the current top-level block. */
tree
-reorder_blocks (block_vector, insns)
+reorder_blocks (block_vector, top_block, insns)
tree *block_vector;
+ tree top_block;
rtx insns;
{
- tree current_block = block_vector[0];
+ tree current_block = top_block;
rtx insn;
+ if (block_vector == 0)
+ return top_block;
+
+ /* Prune the old tree away, so that it doesn't get in the way. */
+ BLOCK_SUBBLOCKS (current_block) = 0;
+
for (insn = insns; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE)
{
/* If we have seen this block before, copy it. */
if (TREE_ASM_WRITTEN (block))
block = copy_node (block);
- else
- BLOCK_SUBBLOCKS (block) = 0;
+ BLOCK_SUBBLOCKS (block) = 0;
TREE_ASM_WRITTEN (block) = 1;
BLOCK_SUPERCONTEXT (block) = current_block;
BLOCK_CHAIN (block) = BLOCK_SUBBLOCKS (current_block);
BLOCK_SUBBLOCKS (current_block) = block;
current_block = block;
- SET_NOTE_BLOCK_NUMBER (insn, 0);
+ NOTE_SOURCE_FILE (insn) = 0;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
{
BLOCK_SUBBLOCKS (current_block)
= blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
current_block = BLOCK_SUPERCONTEXT (current_block);
- SET_NOTE_BLOCK_NUMBER (insn, 0);
+ NOTE_SOURCE_FILE (insn) = 0;
}
}
TREE_ASM_WRITTEN (block) = 0;
/* Record this block. */
- vector[n_blocks++] = block;
+ if (vector)
+ vector[0] = block;
/* Record the subblocks, and their subblocks. */
for (subblocks = BLOCK_SUBBLOCKS (block);
subblocks; subblocks = BLOCK_CHAIN (subblocks))
- n_blocks += all_blocks (subblocks, vector + n_blocks);
+ n_blocks += all_blocks (subblocks, vector ? vector + n_blocks : 0);
return n_blocks;
}
return vec;
}
-/* Determine whether INSN is in the array of INSN_UIDs VEC. */
+/* Determine how many INSN_UIDs in VEC are part of INSN. */
-static rtx
+static int
contains (insn, vec)
rtx insn;
int *vec;
if (GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == SEQUENCE)
{
+ int count = 0;
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
for (j = 0; vec[j]; j++)
if (INSN_UID (XVECEXP (PATTERN (insn), 0, i)) == vec[j])
- return XVECEXP (PATTERN (insn), 0, i);
+ count++;
+ return count;
}
else
{
for (j = 0; vec[j]; j++)
if (INSN_UID (insn) == vec[j])
- return insn;
+ return 1;
}
return 0;
}
if (n_basic_blocks)
{
rtx next, prev;
+ int len;
if (prologue)
{
- register rtx insn, end_prologue;
-
- /* From the end of the first basic block, search backward for a
- prologue insn. */
- for (insn = NEXT_INSN (PREV_INSN (basic_block_end[0]));
- insn; insn = prev_nonnote_insn (insn))
- if (contains (insn, prologue))
+ register rtx insn, note = 0;
+
+ /* Scan from the beginning until we reach the last prologue insn.
+ We apparently can't depend on basic_block_{head,end} after
+ reorg has run. */
+ for (len = 0; prologue[len]; len++)
+ ;
+ for (insn = f; insn; insn = NEXT_INSN (insn))
+ if (GET_CODE (insn) == NOTE)
+ {
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
+ note = insn;
+ }
+ else if ((len -= contains (insn, prologue)) == 0)
{
- end_prologue = insn;
- /* Find the prologue-end note and move it to just after the
- last prologue insn. */
- for (insn = f; insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END)
- break;
- next = NEXT_INSN (insn);
- prev = PREV_INSN (insn);
+ /* Find the prologue-end note if we haven't already, and
+ move it to just after the last prologue insn. */
+ if (note == 0)
+ for (note = insn; note = NEXT_INSN (note);)
+ if (GET_CODE (note) == NOTE
+ && NOTE_LINE_NUMBER (note) == NOTE_INSN_PROLOGUE_END)
+ break;
+ next = NEXT_INSN (note);
+ prev = PREV_INSN (note);
if (prev)
NEXT_INSN (prev) = next;
if (next)
PREV_INSN (next) = prev;
- add_insn_after (insn, end_prologue);
+ add_insn_after (note, insn);
break;
}
}
if (epilogue)
{
- register rtx insn, beg_epilogue;
-
- /* From the start of the last basic block, search forward for an
- epilogue insn. */
- for (insn = PREV_INSN (NEXT_INSN (basic_block_head[n_basic_blocks - 1]));
- insn; insn = next_nonnote_insn (insn))
- if (beg_epilogue = contains (insn, epilogue))
+ register rtx insn, note = 0;
+
+ /* Scan from the end until we reach the first epilogue insn.
+ We apparently can't depend on basic_block_{head,end} after
+ reorg has run. */
+ for (len = 0; epilogue[len]; len++)
+ ;
+ for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+ if (GET_CODE (insn) == NOTE)
+ {
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
+ note = insn;
+ }
+ else if ((len -= contains (insn, epilogue)) == 0)
{
- /* Find the epilogue-begin note and move it to just before
- the first epilogue insn. */
- for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
- if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EPILOGUE_BEG)
- break;
- next = NEXT_INSN (insn);
- prev = PREV_INSN (insn);
+ /* Find the epilogue-begin note if we haven't already, and
+ move it to just before the first epilogue insn. */
+ if (note == 0)
+ for (note = insn; note = PREV_INSN (note);)
+ if (GET_CODE (note) == NOTE
+ && NOTE_LINE_NUMBER (note) == NOTE_INSN_EPILOGUE_BEG)
+ break;
+ next = NEXT_INSN (note);
+ prev = PREV_INSN (note);
if (prev)
NEXT_INSN (prev) = next;
if (next)
PREV_INSN (next) = prev;
- add_insn_after (insn, PREV_INSN (beg_epilogue));
+ add_insn_after (note, PREV_INSN (insn));
break;
}
}