summaryrefslogtreecommitdiff
path: root/gnu/usr.bin/gcc/local-alloc.c
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1998-03-03 21:37:38 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1998-03-03 21:37:38 +0000
commitc826e751760901de543f4640467e3a08df7f49bf (patch)
tree6a2323a78664ba45b78df1709ff3cc077db63ccd /gnu/usr.bin/gcc/local-alloc.c
parenta4511fe6a5dc69a771b5ffdf64ba574c959cf37d (diff)
GCC 2.8.0 merge
Diffstat (limited to 'gnu/usr.bin/gcc/local-alloc.c')
-rw-r--r--gnu/usr.bin/gcc/local-alloc.c532
1 files changed, 321 insertions, 211 deletions
diff --git a/gnu/usr.bin/gcc/local-alloc.c b/gnu/usr.bin/gcc/local-alloc.c
index 647b2d53304..080afe2f7b1 100644
--- a/gnu/usr.bin/gcc/local-alloc.c
+++ b/gnu/usr.bin/gcc/local-alloc.c
@@ -1,5 +1,5 @@
/* Allocate registers within a basic block, for GNU compiler.
- Copyright (C) 1987, 88, 91, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 93-6, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -55,8 +55,12 @@ Boston, MA 02111-1307, USA. */
But this is currently disabled since tying in global_alloc is not
yet implemented. */
-#include <stdio.h>
+/* Pseudos allocated here cannot be reallocated by global.c if the hard
+ register is used as a spill register. So we don't allocate such pseudos
+ here if their preferred class is likely to be used by spills. */
+
#include "config.h"
+#include <stdio.h>
#include "rtl.h"
#include "flags.h"
#include "basic-block.h"
@@ -66,17 +70,6 @@ Boston, MA 02111-1307, USA. */
#include "recog.h"
#include "output.h"
-/* Pseudos allocated here cannot be reallocated by global.c if the hard
- register is used as a spill register. So we don't allocate such pseudos
- here if their preferred class is likely to be used by spills.
-
- On most machines, the appropriate test is if the class has one
- register, so we default to that. */
-
-#ifndef CLASS_LIKELY_SPILLED_P
-#define CLASS_LIKELY_SPILLED_P(CLASS) (reg_class_size[(int) (CLASS)] == 1)
-#endif
-
/* Next quantity number available for allocation. */
static int next_qty;
@@ -110,7 +103,7 @@ static HARD_REG_SET *qty_phys_sugg;
static short *qty_phys_num_copy_sugg;
-/* Element Q is the number of suggested registers in qty_phys_sugg. */
+/* Element Q is the number of suggested registers in qty_phys_sugg. */
static short *qty_phys_num_sugg;
@@ -242,10 +235,18 @@ static int scratch_index;
static int this_insn_number;
static rtx this_insn;
+/* Used to communicate changes made by update_equiv_regs to
+ memref_referenced_p. reg_equiv_replacement is set for any REG_EQUIV note
+ found or created, so that we can keep track of what memory accesses might
+ be created later, e.g. by reload. */
+
+static rtx *reg_equiv_replacement;
+
static void alloc_qty PROTO((int, enum machine_mode, int, int));
static void alloc_qty_for_scratch PROTO((rtx, int, rtx, int, int));
static void validate_equiv_mem_from_store PROTO((rtx, rtx));
static int validate_equiv_mem PROTO((rtx, rtx, rtx));
+static int contains_replace_regs PROTO((rtx, char *));
static int memref_referenced_p PROTO((rtx, rtx));
static int memref_used_between_p PROTO((rtx, rtx, rtx));
static void optimize_reg_copy_1 PROTO((rtx, rtx, rtx));
@@ -253,9 +254,9 @@ static void optimize_reg_copy_2 PROTO((rtx, rtx, rtx));
static void update_equiv_regs PROTO((void));
static void block_alloc PROTO((int));
static int qty_sugg_compare PROTO((int, int));
-static int qty_sugg_compare_1 PROTO((int *, int *));
+static int qty_sugg_compare_1 PROTO((const GENERIC_PTR, const GENERIC_PTR));
static int qty_compare PROTO((int, int));
-static int qty_compare_1 PROTO((int *, int *));
+static int qty_compare_1 PROTO((const GENERIC_PTR, const GENERIC_PTR));
static int combine_regs PROTO((rtx, rtx, int, int, rtx, int));
static int reg_meets_class_p PROTO((int, enum reg_class));
static int reg_classes_overlap_p PROTO((enum reg_class, enum reg_class,
@@ -291,11 +292,11 @@ alloc_qty (regno, mode, size, birth)
qty_size[qty] = size;
qty_mode[qty] = mode;
qty_birth[qty] = birth;
- qty_n_calls_crossed[qty] = reg_n_calls_crossed[regno];
+ qty_n_calls_crossed[qty] = REG_N_CALLS_CROSSED (regno);
qty_min_class[qty] = reg_preferred_class (regno);
qty_alternate_class[qty] = reg_alternate_class (regno);
- qty_n_refs[qty] = reg_n_refs[regno];
- qty_changes_size[qty] = reg_changes_size[regno];
+ qty_n_refs[qty] = REG_N_REFS (regno);
+ qty_changes_size[qty] = REG_CHANGES_SIZE (regno);
}
/* Similar to `alloc_qty', but allocates a quantity for a SCRATCH rtx
@@ -453,9 +454,8 @@ local_alloc ()
reg_offset = (char *) alloca (max_regno * sizeof (char));
reg_next_in_qty = (int *) alloca (max_regno * sizeof (int));
- reg_renumber = (short *) oballoc (max_regno * sizeof (short));
- for (i = 0; i < max_regno; i++)
- reg_renumber[i] = -1;
+ /* Allocate the reg_renumber array */
+ allocate_reg_info (max_regno, FALSE, TRUE);
/* Determine which pseudo-registers can be allocated by local-alloc.
In general, these are the registers used only in a single block and
@@ -469,7 +469,7 @@ local_alloc ()
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
{
- if (reg_basic_block[i] >= 0 && reg_n_deaths[i] == 1
+ if (REG_BASIC_BLOCK (i) >= 0 && REG_N_DEATHS (i) == 1
&& (reg_alternate_class (i) == NO_REGS
|| ! CLASS_LIKELY_SPILLED_P (reg_preferred_class (i))))
reg_qty[i] = -2;
@@ -601,6 +601,52 @@ validate_equiv_mem (start, reg, memref)
return 0;
}
+
+/* TRUE if X uses any registers for which reg_equiv_replace is true. */
+
+static int
+contains_replace_regs (x, reg_equiv_replace)
+ rtx x;
+ char *reg_equiv_replace;
+{
+ int i, j;
+ char *fmt;
+ enum rtx_code code = GET_CODE (x);
+
+ switch (code)
+ {
+ case CONST_INT:
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST_DOUBLE:
+ case PC:
+ case CC0:
+ case HIGH:
+ case LO_SUM:
+ return 0;
+
+ case REG:
+ return reg_equiv_replace[REGNO (x)];
+ }
+
+ fmt = GET_RTX_FORMAT (code);
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+ switch (fmt[i])
+ {
+ case 'e':
+ if (contains_replace_regs (XEXP (x, i), reg_equiv_replace))
+ return 1;
+ break;
+ case 'E':
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+ if (contains_replace_regs (XVECEXP (x, i, j), reg_equiv_replace))
+ return 1;
+ break;
+ }
+
+ return 0;
+}
/* TRUE if X references a memory location that would be affected by a store
to MEMREF. */
@@ -616,7 +662,6 @@ memref_referenced_p (memref, x)
switch (code)
{
- case REG:
case CONST_INT:
case CONST:
case LABEL_REF:
@@ -628,6 +673,11 @@ memref_referenced_p (memref, x)
case LO_SUM:
return 0;
+ case REG:
+ return (reg_equiv_replacement[REGNO (x)]
+ && memref_referenced_p (memref,
+ reg_equiv_replacement[REGNO (x)]));
+
case MEM:
if (true_dependence (memref, x))
return 1;
@@ -645,6 +695,9 @@ memref_referenced_p (memref, x)
return 1;
return memref_referenced_p (memref, SET_SRC (x));
+
+ default:
+ break;
}
fmt = GET_RTX_FORMAT (code);
@@ -708,11 +761,11 @@ optimize_reg_copy_1 (insn, dest, src)
int sregno = REGNO (src);
int dregno = REGNO (dest);
+ /* We don't want to mess with hard regs if register classes are small. */
if (sregno == dregno
-#ifdef SMALL_REGISTER_CLASSES
- /* We don't want to mess with hard regs if register classes are small. */
- || sregno < FIRST_PSEUDO_REGISTER || dregno < FIRST_PSEUDO_REGISTER
-#endif
+ || (SMALL_REGISTER_CLASSES
+ && (sregno < FIRST_PSEUDO_REGISTER
+ || dregno < FIRST_PSEUDO_REGISTER))
/* We don't see all updates to SP if they are in an auto-inc memory
reference, so we must disallow this optimization on them. */
|| sregno == STACK_POINTER_REGNUM || dregno == STACK_POINTER_REGNUM)
@@ -736,7 +789,7 @@ optimize_reg_copy_1 (insn, dest, src)
break;
/* See if all of SRC dies in P. This test is slightly more
- conservative than it needs to be. */
+ conservative than it needs to be. */
if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0
&& GET_MODE (XEXP (note, 0)) == GET_MODE (src))
{
@@ -778,9 +831,9 @@ optimize_reg_copy_1 (insn, dest, src)
insn in the updates below. If this is not correct,
no great harm is done. */
if (sregno >= FIRST_PSEUDO_REGISTER)
- reg_n_refs[sregno] -= loop_depth;
+ REG_N_REFS (sregno) -= loop_depth;
if (dregno >= FIRST_PSEUDO_REGISTER)
- reg_n_refs[dregno] += loop_depth;
+ REG_N_REFS (dregno) += loop_depth;
}
else
{
@@ -817,19 +870,25 @@ optimize_reg_copy_1 (insn, dest, src)
{
if (sregno >= FIRST_PSEUDO_REGISTER)
{
- reg_live_length[sregno] -= length;
- /* reg_live_length is only an approximation after combine
- if sched is not run, so make sure that we still have
- a reasonable value. */
- if (reg_live_length[sregno] < 2)
- reg_live_length[sregno] = 2;
- reg_n_calls_crossed[sregno] -= n_calls;
+ if (REG_LIVE_LENGTH (sregno) >= 0)
+ {
+ REG_LIVE_LENGTH (sregno) -= length;
+ /* reg_live_length is only an approximation after
+ combine if sched is not run, so make sure that we
+ still have a reasonable value. */
+ if (REG_LIVE_LENGTH (sregno) < 2)
+ REG_LIVE_LENGTH (sregno) = 2;
+ }
+
+ REG_N_CALLS_CROSSED (sregno) -= n_calls;
}
if (dregno >= FIRST_PSEUDO_REGISTER)
{
- reg_live_length[dregno] += d_length;
- reg_n_calls_crossed[dregno] += d_n_calls;
+ if (REG_LIVE_LENGTH (dregno) >= 0)
+ REG_LIVE_LENGTH (dregno) += d_length;
+
+ REG_N_CALLS_CROSSED (dregno) += d_n_calls;
}
/* Move death note of SRC from P to INSN. */
@@ -865,7 +924,7 @@ optimize_reg_copy_1 (insn, dest, src)
In that case, we can replace all uses of DEST, starting with INSN and
ending with the set of SRC to DEST, with SRC. We do not do this
optimization if a CALL_INSN is crossed unless SRC already crosses a
- call.
+ call or if DEST dies before the copy back to SRC.
It is assumed that DEST and SRC are pseudos; it is too complicated to do
this for hard registers since the substitutions we may make might fail. */
@@ -910,27 +969,28 @@ optimize_reg_copy_2 (insn, dest, src)
/* We assume that a register is used exactly once per
insn in the updates below. If this is not correct,
no great harm is done. */
- reg_n_refs[dregno] -= loop_depth;
- reg_n_refs[sregno] += loop_depth;
+ REG_N_REFS (dregno) -= loop_depth;
+ REG_N_REFS (sregno) += loop_depth;
}
if (GET_CODE (q) == CALL_INSN)
{
- reg_n_calls_crossed[dregno]--;
- reg_n_calls_crossed[sregno]++;
+ REG_N_CALLS_CROSSED (dregno)--;
+ REG_N_CALLS_CROSSED (sregno)++;
}
}
remove_note (p, find_reg_note (p, REG_DEAD, dest));
- reg_n_deaths[dregno]--;
+ REG_N_DEATHS (dregno)--;
remove_note (insn, find_reg_note (insn, REG_DEAD, src));
- reg_n_deaths[sregno]--;
+ REG_N_DEATHS (sregno)--;
return;
}
if (reg_set_p (src, p)
- || (GET_CODE (p) == CALL_INSN && reg_n_calls_crossed[sregno] == 0))
+ || find_reg_note (p, REG_DEAD, dest)
+ || (GET_CODE (p) == CALL_INSN && REG_N_CALLS_CROSSED (sregno) == 0))
break;
}
}
@@ -947,11 +1007,18 @@ static void
update_equiv_regs ()
{
rtx *reg_equiv_init_insn = (rtx *) alloca (max_regno * sizeof (rtx *));
- rtx *reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *));
+ /* Set when an attempt should be made to replace a register with the
+ associated reg_equiv_replacement entry at the end of this function. */
+ char *reg_equiv_replace
+ = (char *) alloca (max_regno * sizeof *reg_equiv_replace);
rtx insn;
+ int block, depth;
+
+ reg_equiv_replacement = (rtx *) alloca (max_regno * sizeof (rtx *));
bzero ((char *) reg_equiv_init_insn, max_regno * sizeof (rtx *));
bzero ((char *) reg_equiv_replacement, max_regno * sizeof (rtx *));
+ bzero ((char *) reg_equiv_replace, max_regno * sizeof *reg_equiv_replace);
init_alias_analysis ();
@@ -964,7 +1031,7 @@ update_equiv_regs ()
{
rtx note;
rtx set = single_set (insn);
- rtx dest;
+ rtx dest, src;
int regno;
if (GET_CODE (insn) == NOTE)
@@ -980,17 +1047,30 @@ update_equiv_regs ()
continue;
dest = SET_DEST (set);
+ src = SET_SRC (set);
/* If this sets a MEM to the contents of a REG that is only used
in a single basic block, see if the register is always equivalent
to that memory location and if moving the store from INSN to the
insn that set REG is safe. If so, put a REG_EQUIV note on the
- initializing insn. */
+ initializing insn.
+
+ Don't add a REG_EQUIV note if the insn already has one. The existing
+ REG_EQUIV is likely more useful than the one we are adding.
+
+ If one of the regs in the address is marked as reg_equiv_replace,
+ then we can't add this REG_EQUIV note. The reg_equiv_replace
+ optimization may move the set of this register immediately before
+ insn, which puts it after reg_equiv_init_insn[regno], and hence
+ the mention in the REG_EQUIV note would be to an uninitialized
+ pseudo. */
if (GET_CODE (dest) == MEM && GET_CODE (SET_SRC (set)) == REG
&& (regno = REGNO (SET_SRC (set))) >= FIRST_PSEUDO_REGISTER
- && reg_basic_block[regno] >= 0
+ && REG_BASIC_BLOCK (regno) >= 0
&& reg_equiv_init_insn[regno] != 0
+ && ! find_reg_note (insn, REG_EQUIV, NULL_RTX)
+ && ! contains_replace_regs (XEXP (dest, 0), reg_equiv_replace)
&& validate_equiv_mem (reg_equiv_init_insn[regno], SET_SRC (set),
dest)
&& ! memref_used_between_p (SET_DEST (set),
@@ -1015,10 +1095,15 @@ update_equiv_regs ()
optimize_reg_copy_2 (insn, dest, SET_SRC (set));
/* Otherwise, we only handle the case of a pseudo register being set
- once. */
+ once and only if neither the source nor the destination are
+ in a register class that's likely to be spilled. */
if (GET_CODE (dest) != REG
|| (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
- || reg_n_sets[regno] != 1)
+ || REG_N_SETS (regno) != 1
+ || CLASS_LIKELY_SPILLED_P (reg_preferred_class (REGNO (dest)))
+ || (GET_CODE (src) == REG
+ && REGNO (src) >= FIRST_PSEUDO_REGISTER
+ && CLASS_LIKELY_SPILLED_P (reg_preferred_class (REGNO (src)))))
continue;
note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
@@ -1048,71 +1133,139 @@ update_equiv_regs ()
note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
- if (note == 0 && reg_basic_block[regno] >= 0
+ if (note == 0 && REG_BASIC_BLOCK (regno) >= 0
&& GET_CODE (SET_SRC (set)) == MEM
&& validate_equiv_mem (insn, dest, SET_SRC (set)))
REG_NOTES (insn) = note = gen_rtx (EXPR_LIST, REG_EQUIV, SET_SRC (set),
REG_NOTES (insn));
- /* Don't mess with things live during setjmp. */
- if (note && reg_live_length[regno] >= 0)
+ if (note)
{
int regno = REGNO (dest);
- /* Note that the statement below does not affect the priority
- in local-alloc! */
- reg_live_length[regno] *= 2;
+ reg_equiv_replacement[regno] = XEXP (note, 0);
+
+ /* Don't mess with things live during setjmp. */
+ if (REG_LIVE_LENGTH (regno) >= 0)
+ {
+ /* Note that the statement below does not affect the priority
+ in local-alloc! */
+ REG_LIVE_LENGTH (regno) *= 2;
- /* If the register is referenced exactly twice, meaning it is set
- once and used once, indicate that the reference may be replaced
- by the equivalence we computed above. If the register is only
- used in one basic block, this can't succeed or combine would
- have done it.
- It would be nice to use "loop_depth * 2" in the compare
- below. Unfortunately, LOOP_DEPTH need not be constant within
- a basic block so this would be too complicated.
+ /* If the register is referenced exactly twice, meaning it is
+ set once and used once, indicate that the reference may be
+ replaced by the equivalence we computed above. If the
+ register is only used in one basic block, this can't succeed
+ or combine would have done it.
- This case normally occurs when a parameter is read from memory
- and then used exactly once, not in a loop. */
+ It would be nice to use "loop_depth * 2" in the compare
+ below. Unfortunately, LOOP_DEPTH need not be constant within
+ a basic block so this would be too complicated.
- if (reg_n_refs[regno] == 2
- && reg_basic_block[regno] < 0
- && rtx_equal_p (XEXP (note, 0), SET_SRC (set)))
- reg_equiv_replacement[regno] = SET_SRC (set);
+ This case normally occurs when a parameter is read from
+ memory and then used exactly once, not in a loop. */
+
+ if (REG_N_REFS (regno) == 2
+ && REG_BASIC_BLOCK (regno) < 0
+ && rtx_equal_p (XEXP (note, 0), SET_SRC (set)))
+ reg_equiv_replace[regno] = 1;
+ }
}
}
- /* Now scan all regs killed in an insn to see if any of them are registers
- only used that once. If so, see if we can replace the reference with
- the equivalent from. If we can, delete the initializing reference
- and this register will go away. */
- for (insn = next_active_insn (get_insns ());
- insn;
- insn = next_active_insn (insn))
+ /* Now scan all regs killed in an insn to see if any of them are
+ registers only used that once. If so, see if we can replace the
+ reference with the equivalent from. If we can, delete the
+ initializing reference and this register will go away. If we
+ can't replace the reference, and the instruction is not in a
+ loop, then move the register initialization just before the use,
+ so that they are in the same basic block. */
+ block = -1;
+ depth = 0;
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
rtx link;
+ /* Keep track of which basic block we are in. */
+ if (block + 1 < n_basic_blocks
+ && basic_block_head[block + 1] == insn)
+ ++block;
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+ {
+ if (GET_CODE (insn) == NOTE)
+ {
+ if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+ ++depth;
+ else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+ {
+ --depth;
+ if (depth < 0)
+ abort ();
+ }
+ }
+
+ continue;
+ }
+
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
- if (REG_NOTE_KIND (link) == REG_DEAD
- /* Make sure this insn still refers to the register. */
- && reg_mentioned_p (XEXP (link, 0), PATTERN (insn)))
- {
- int regno = REGNO (XEXP (link, 0));
+ {
+ if (REG_NOTE_KIND (link) == REG_DEAD
+ /* Make sure this insn still refers to the register. */
+ && reg_mentioned_p (XEXP (link, 0), PATTERN (insn)))
+ {
+ int regno = REGNO (XEXP (link, 0));
+ rtx equiv_insn;
- if (reg_equiv_replacement[regno]
- && validate_replace_rtx (regno_reg_rtx[regno],
- reg_equiv_replacement[regno], insn))
- {
- rtx equiv_insn = reg_equiv_init_insn[regno];
+ if (! reg_equiv_replace[regno])
+ continue;
- remove_death (regno, insn);
- reg_n_refs[regno] = 0;
- PUT_CODE (equiv_insn, NOTE);
- NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (equiv_insn) = 0;
- }
- }
+ equiv_insn = reg_equiv_init_insn[regno];
+
+ if (validate_replace_rtx (regno_reg_rtx[regno],
+ reg_equiv_replacement[regno], insn))
+ {
+ remove_death (regno, insn);
+ REG_N_REFS (regno) = 0;
+ PUT_CODE (equiv_insn, NOTE);
+ NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (equiv_insn) = 0;
+ }
+ /* If we aren't in a loop, and there are no calls in
+ INSN or in the initialization of the register, then
+ move the initialization of the register to just
+ before INSN. Update the flow information. */
+ else if (depth == 0
+ && GET_CODE (equiv_insn) == INSN
+ && GET_CODE (insn) == INSN
+ && REG_BASIC_BLOCK (regno) < 0)
+ {
+ int l;
+
+ emit_insn_before (copy_rtx (PATTERN (equiv_insn)), insn);
+ REG_NOTES (PREV_INSN (insn)) = REG_NOTES (equiv_insn);
+
+ PUT_CODE (equiv_insn, NOTE);
+ NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (equiv_insn) = 0;
+ REG_NOTES (equiv_insn) = 0;
+
+ if (block < 0)
+ REG_BASIC_BLOCK (regno) = 0;
+ else
+ REG_BASIC_BLOCK (regno) = block;
+ REG_N_CALLS_CROSSED (regno) = 0;
+ REG_LIVE_LENGTH (regno) = 2;
+
+ if (block >= 0 && insn == basic_block_head[block])
+ basic_block_head[block] = PREV_INSN (insn);
+
+ for (l = 0; l < n_basic_blocks; l++)
+ CLEAR_REGNO_REG_SET (basic_block_live_at_start[l], regno);
+ }
+ }
+ }
}
}
@@ -1156,11 +1309,7 @@ block_alloc (b)
/* Initialize table of hardware registers currently live. */
-#ifdef HARD_REG_SET
- regs_live = *basic_block_live_at_start[b];
-#else
- COPY_HARD_REG_SET (regs_live, basic_block_live_at_start[b]);
-#endif
+ REG_SET_TO_HARD_REG_SET (regs_live, basic_block_live_at_start[b]);
/* This loop scans the instructions of the basic block
and assigns quantities to registers.
@@ -1446,13 +1595,13 @@ block_alloc (b)
if (qty_sugg_compare (1, 2) > 0)
EXCHANGE (2, 1);
- /* ... Fall through ... */
+ /* ... Fall through ... */
case 2:
/* Put the best one to allocate in qty_order[0]. */
if (qty_sugg_compare (0, 1) > 0)
EXCHANGE (0, 1);
- /* ... Fall through ... */
+ /* ... Fall through ... */
case 1:
case 0:
@@ -1495,13 +1644,13 @@ block_alloc (b)
if (qty_compare (1, 2) > 0)
EXCHANGE (2, 1);
- /* ... Fall through ... */
+ /* ... Fall through ... */
case 2:
/* Put the best one to allocate in qty_order[0]. */
if (qty_compare (0, 1) > 0)
EXCHANGE (0, 1);
- /* ... Fall through ... */
+ /* ... Fall through ... */
case 1:
case 0:
@@ -1550,17 +1699,11 @@ block_alloc (b)
{
if (GET_CODE (qty_scratch_rtx[q]) == REG)
abort ();
- PUT_CODE (qty_scratch_rtx[q], REG);
- REGNO (qty_scratch_rtx[q]) = qty_phys_reg[q];
-
+ qty_scratch_rtx[q] = gen_rtx (REG, GET_MODE (qty_scratch_rtx[q]),
+ qty_phys_reg[q]);
scratch_block[scratch_index] = b;
scratch_list[scratch_index++] = qty_scratch_rtx[q];
- /* Must clear the USED field, because it will have been set by
- copy_rtx_if_shared, but the leaf_register code expects that
- it is zero in all REG rtx. copy_rtx_if_shared does not set the
- used bit for REGs, but does for SCRATCHes. */
- qty_scratch_rtx[q]->used = 0;
}
}
}
@@ -1575,51 +1718,37 @@ block_alloc (b)
the same algorithm in both local- and global-alloc can speed up execution
of some programs by as much as a factor of three! */
+/* Note that the quotient will never be bigger than
+ the value of floor_log2 times the maximum number of
+ times a register can occur in one insn (surely less than 100).
+ Multiplying this by 10000 can't overflow.
+ QTY_CMP_PRI is also used by qty_sugg_compare. */
+
+#define QTY_CMP_PRI(q) \
+ ((int) (((double) (floor_log2 (qty_n_refs[q]) * qty_n_refs[q] * qty_size[q]) \
+ / (qty_death[q] - qty_birth[q])) * 10000))
+
static int
qty_compare (q1, q2)
int q1, q2;
{
- /* Note that the quotient will never be bigger than
- the value of floor_log2 times the maximum number of
- times a register can occur in one insn (surely less than 100).
- Multiplying this by 10000 can't overflow. */
- register int pri1
- = (((double) (floor_log2 (qty_n_refs[q1]) * qty_n_refs[q1] * qty_size[q1])
- / (qty_death[q1] - qty_birth[q1]))
- * 10000);
- register int pri2
- = (((double) (floor_log2 (qty_n_refs[q2]) * qty_n_refs[q2] * qty_size[q2])
- / (qty_death[q2] - qty_birth[q2]))
- * 10000);
- return pri2 - pri1;
+ return QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
}
static int
-qty_compare_1 (q1, q2)
- int *q1, *q2;
+qty_compare_1 (q1p, q2p)
+ const GENERIC_PTR q1p;
+ const GENERIC_PTR q2p;
{
- register int tem;
-
- /* Note that the quotient will never be bigger than
- the value of floor_log2 times the maximum number of
- times a register can occur in one insn (surely less than 100).
- Multiplying this by 10000 can't overflow. */
- register int pri1
- = (((double) (floor_log2 (qty_n_refs[*q1]) * qty_n_refs[*q1]
- * qty_size[*q1])
- / (qty_death[*q1] - qty_birth[*q1]))
- * 10000);
- register int pri2
- = (((double) (floor_log2 (qty_n_refs[*q2]) * qty_n_refs[*q2]
- * qty_size[*q2])
- / (qty_death[*q2] - qty_birth[*q2]))
- * 10000);
-
- tem = pri2 - pri1;
- if (tem != 0) return tem;
+ register int q1 = *(int *)q1p, q2 = *(int *)q2p;
+ register int tem = QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
+
+ if (tem != 0)
+ return tem;
+
/* If qtys are equally good, sort by qty number,
so that the results of qsort leave nothing to chance. */
- return *q1 - *q2;
+ return q1 - q2;
}
/* Compare two quantities' priority for getting real registers. This version
@@ -1629,71 +1758,45 @@ qty_compare_1 (q1, q2)
number of preferences have the highest priority. Of those, we use the same
algorithm as above. */
+#define QTY_CMP_SUGG(q) \
+ (qty_phys_num_copy_sugg[q] \
+ ? qty_phys_num_copy_sugg[q] \
+ : qty_phys_num_sugg[q] * FIRST_PSEUDO_REGISTER)
+
static int
qty_sugg_compare (q1, q2)
int q1, q2;
{
- register int sugg1 = (qty_phys_num_copy_sugg[q1]
- ? qty_phys_num_copy_sugg[q1]
- : qty_phys_num_sugg[q1] * FIRST_PSEUDO_REGISTER);
- register int sugg2 = (qty_phys_num_copy_sugg[q2]
- ? qty_phys_num_copy_sugg[q2]
- : qty_phys_num_sugg[q2] * FIRST_PSEUDO_REGISTER);
- /* Note that the quotient will never be bigger than
- the value of floor_log2 times the maximum number of
- times a register can occur in one insn (surely less than 100).
- Multiplying this by 10000 can't overflow. */
- register int pri1
- = (((double) (floor_log2 (qty_n_refs[q1]) * qty_n_refs[q1] * qty_size[q1])
- / (qty_death[q1] - qty_birth[q1]))
- * 10000);
- register int pri2
- = (((double) (floor_log2 (qty_n_refs[q2]) * qty_n_refs[q2] * qty_size[q2])
- / (qty_death[q2] - qty_birth[q2]))
- * 10000);
-
- if (sugg1 != sugg2)
- return sugg1 - sugg2;
+ register int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
+
+ if (tem != 0)
+ return tem;
- return pri2 - pri1;
+ return QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
}
static int
-qty_sugg_compare_1 (q1, q2)
- int *q1, *q2;
+qty_sugg_compare_1 (q1p, q2p)
+ const GENERIC_PTR q1p;
+ const GENERIC_PTR q2p;
{
- register int sugg1 = (qty_phys_num_copy_sugg[*q1]
- ? qty_phys_num_copy_sugg[*q1]
- : qty_phys_num_sugg[*q1] * FIRST_PSEUDO_REGISTER);
- register int sugg2 = (qty_phys_num_copy_sugg[*q2]
- ? qty_phys_num_copy_sugg[*q2]
- : qty_phys_num_sugg[*q2] * FIRST_PSEUDO_REGISTER);
-
- /* Note that the quotient will never be bigger than
- the value of floor_log2 times the maximum number of
- times a register can occur in one insn (surely less than 100).
- Multiplying this by 10000 can't overflow. */
- register int pri1
- = (((double) (floor_log2 (qty_n_refs[*q1]) * qty_n_refs[*q1]
- * qty_size[*q1])
- / (qty_death[*q1] - qty_birth[*q1]))
- * 10000);
- register int pri2
- = (((double) (floor_log2 (qty_n_refs[*q2]) * qty_n_refs[*q2]
- * qty_size[*q2])
- / (qty_death[*q2] - qty_birth[*q2]))
- * 10000);
-
- if (sugg1 != sugg2)
- return sugg1 - sugg2;
-
- if (pri1 != pri2)
- return pri2 - pri1;
+ register int q1 = *(int *)q1p, q2 = *(int *)q2p;
+ register int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
+
+ if (tem != 0)
+ return tem;
+
+ tem = QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
+ if (tem != 0)
+ return tem;
/* If qtys are equally good, sort by qty number,
so that the results of qsort leave nothing to chance. */
- return *q1 - *q2;
+ return q1 - q2;
}
+
+#undef QTY_CMP_SUGG
+#undef QTY_CMP_PRI
/* Attempt to combine the two registers (rtx's) USEDREG and SETREG.
Returns 1 if have done so, or 0 if cannot.
@@ -1767,7 +1870,7 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
|| (offset > 0 && usize + offset > ssize)
|| (offset < 0 && usize + offset < ssize)
/* Do not combine with a smaller already-assigned object
- if that smaller object is already combined with something bigger. */
+ if that smaller object is already combined with something bigger. */
|| (ssize > usize && ureg >= FIRST_PSEUDO_REGISTER
&& usize < qty_size[reg_qty[ureg]])
/* Can't combine if SREG is not a register we can allocate. */
@@ -1844,8 +1947,8 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
/* If we are not going to let any regs live across calls,
don't tie a call-crossing reg to a non-call-crossing reg. */
|| (current_function_has_nonlocal_label
- && ((reg_n_calls_crossed[ureg] > 0)
- != (reg_n_calls_crossed[sreg] > 0))))
+ && ((REG_N_CALLS_CROSSED (ureg) > 0)
+ != (REG_N_CALLS_CROSSED (sreg) > 0))))
return 0;
/* We don't already know about SREG, so tie it to UREG
@@ -1866,8 +1969,8 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
update_qty_class (sqty, sreg);
/* Update info about quantity SQTY. */
- qty_n_calls_crossed[sqty] += reg_n_calls_crossed[sreg];
- qty_n_refs[sqty] += reg_n_refs[sreg];
+ qty_n_calls_crossed[sqty] += REG_N_CALLS_CROSSED (sreg);
+ qty_n_refs[sqty] += REG_N_REFS (sreg);
if (usize < ssize)
{
register int i;
@@ -1937,7 +2040,7 @@ update_qty_class (qty, reg)
if (reg_class_subset_p (rclass, qty_alternate_class[qty]))
qty_alternate_class[qty] = rclass;
- if (reg_changes_size[reg])
+ if (REG_CHANGES_SIZE (reg))
qty_changes_size[qty] = 1;
}
@@ -2105,6 +2208,9 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
else
COPY_HARD_REG_SET (used, call_used_reg_set);
+ if (accept_call_clobbered)
+ IOR_HARD_REG_SET (used, losing_caller_save_reg_set);
+
for (ins = born_index; ins < dead_index; ins++)
IOR_HARD_REG_SET (used, regs_live_at[ins]);
@@ -2121,7 +2227,7 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
SET_HARD_REG_BIT (used, eliminables[i].from);
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
/* If FRAME_POINTER_REGNUM is not a real register, then protect the one
- that it might be eliminated into. */
+ that it might be eliminated into. */
SET_HARD_REG_BIT (used, HARD_FRAME_POINTER_REGNUM);
#endif
#else
@@ -2303,8 +2409,12 @@ no_conflict_p (insn, r0, r1)
if (find_reg_note (p, REG_DEAD, r1))
ok = 1;
- if (reg_mentioned_p (r1, PATTERN (p))
- && ! find_reg_note (p, REG_NO_CONFLICT, r1))
+ /* There must be a REG_NO_CONFLICT note on every insn, otherwise
+ some earlier optimization pass has inserted instructions into
+ the sequence, and it is not safe to perform this optimization.
+ Note that emit_no_conflict_block always ensures that this is
+ true when these sequences are created. */
+ if (! find_reg_note (p, REG_NO_CONFLICT, r1))
return 0;
}