summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/global.c
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1999-08-26 09:30:50 +0000
committerobrien <obrien@FreeBSD.org>1999-08-26 09:30:50 +0000
commit0bedf4fb30066e5e1d4342a1d3914dae7d37cba7 (patch)
tree68d8110b41afd0ebbf39167b1a4918eea667a7c5 /contrib/gcc/global.c
parentd4db5fb866b7ad5216abd5047774a3973b9901a9 (diff)
downloadFreeBSD-src-0bedf4fb30066e5e1d4342a1d3914dae7d37cba7.zip
FreeBSD-src-0bedf4fb30066e5e1d4342a1d3914dae7d37cba7.tar.gz
Virgin import of gcc from EGCS 1.1.2
Diffstat (limited to 'contrib/gcc/global.c')
-rw-r--r--contrib/gcc/global.c146
1 files changed, 79 insertions, 67 deletions
diff --git a/contrib/gcc/global.c b/contrib/gcc/global.c
index e9941e6..d382537 100644
--- a/contrib/gcc/global.c
+++ b/contrib/gcc/global.c
@@ -1,5 +1,5 @@
/* Allocate registers for pseudo-registers that span basic blocks.
- Copyright (C) 1987, 1988, 1991, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 94, 96, 1997 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -19,15 +19,18 @@ the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include <stdio.h>
#include "config.h"
+#include "system.h"
+
+#include "machmode.h"
+#include "hard-reg-set.h"
#include "rtl.h"
#include "flags.h"
#include "basic-block.h"
-#include "hard-reg-set.h"
#include "regs.h"
#include "insn-config.h"
#include "output.h"
+#include "toplev.h"
/* This pass of the compiler performs global register allocation.
It assigns hard register numbers to all the pseudo registers
@@ -75,7 +78,7 @@ static int max_allocno;
/* Indexed by (pseudo) reg number, gives the allocno, or -1
for pseudo registers already allocated by local_allocate. */
-static int *reg_allocno;
+int *reg_allocno;
/* Indexed by allocno, gives the reg number. */
@@ -251,7 +254,7 @@ static int n_regs_set;
static HARD_REG_SET eliminable_regset;
-static int allocno_compare PROTO((int *, int *));
+static int allocno_compare PROTO((const GENERIC_PTR, const GENERIC_PTR));
static void global_conflicts PROTO((void));
static void expand_preferences PROTO((void));
static void prune_preferences PROTO((void));
@@ -277,6 +280,7 @@ int
global_alloc (file)
FILE *file;
{
+ int retval;
#ifdef ELIMINABLE_REGS
static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
#endif
@@ -287,7 +291,7 @@ global_alloc (file)
#endif
|| FRAME_POINTER_REQUIRED);
- register int i;
+ register size_t i;
rtx x;
max_allocno = 0;
@@ -385,17 +389,17 @@ global_alloc (file)
/* Note that reg_live_length[i] < 0 indicates a "constant" reg
that we are supposed to refrain from putting in a hard reg.
-2 means do make an allocno but don't allocate it. */
- if (reg_n_refs[i] != 0 && reg_renumber[i] < 0 && reg_live_length[i] != -1
+ if (REG_N_REFS (i) != 0 && reg_renumber[i] < 0 && REG_LIVE_LENGTH (i) != -1
/* Don't allocate pseudos that cross calls,
if this function receives a nonlocal goto. */
&& (! current_function_has_nonlocal_label
- || reg_n_calls_crossed[i] == 0))
+ || REG_N_CALLS_CROSSED (i) == 0))
{
if (reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
reg_allocno[i] = reg_allocno[reg_may_share[i]];
else
reg_allocno[i] = max_allocno++;
- if (reg_live_length[i] == 0)
+ if (REG_LIVE_LENGTH (i) == 0)
abort ();
}
else
@@ -417,10 +421,10 @@ global_alloc (file)
int allocno = reg_allocno[i];
allocno_reg[allocno] = i;
allocno_size[allocno] = PSEUDO_REGNO_SIZE (i);
- allocno_calls_crossed[allocno] += reg_n_calls_crossed[i];
- allocno_n_refs[allocno] += reg_n_refs[i];
- if (allocno_live_length[allocno] < reg_live_length[i])
- allocno_live_length[allocno] = reg_live_length[i];
+ allocno_calls_crossed[allocno] += REG_N_CALLS_CROSSED (i);
+ allocno_n_refs[allocno] += REG_N_REFS (i);
+ if (allocno_live_length[allocno] < REG_LIVE_LENGTH (i))
+ allocno_live_length[allocno] = REG_LIVE_LENGTH (i);
}
/* Calculate amount of usage of each hard reg by pseudos
@@ -437,8 +441,8 @@ global_alloc (file)
for (j = regno; j < endregno; j++)
{
- local_reg_n_refs[j] += reg_n_refs[i];
- local_reg_live_length[j] += reg_live_length[i];
+ local_reg_n_refs[j] += REG_N_REFS (i);
+ local_reg_live_length[j] += REG_LIVE_LENGTH (i);
}
}
@@ -486,8 +490,11 @@ global_alloc (file)
allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
- conflicts = (INT_TYPE *) alloca (max_allocno * allocno_row_words
- * sizeof (INT_TYPE));
+ /* We used to use alloca here, but the size of what it would try to
+ allocate would occasionally cause it to exceed the stack limit and
+ cause unpredictable core dumps. Some examples were > 2Mb in size. */
+ conflicts = (INT_TYPE *) xmalloc (max_allocno * allocno_row_words
+ * sizeof (INT_TYPE));
bzero ((char *) conflicts,
max_allocno * allocno_row_words * sizeof (INT_TYPE));
@@ -554,19 +561,19 @@ global_alloc (file)
except for parameters marked with reg_live_length[regno] == -2. */
for (i = 0; i < max_allocno; i++)
- if (reg_live_length[allocno_reg[allocno_order[i]]] >= 0)
+ if (REG_LIVE_LENGTH (allocno_reg[allocno_order[i]]) >= 0)
{
/* If we have more than one register class,
first try allocating in the class that is cheapest
for this pseudo-reg. If that fails, try any reg. */
if (N_REG_CLASSES > 1)
{
- find_reg (allocno_order[i], HARD_CONST (0), 0, 0, 0);
+ find_reg (allocno_order[i], 0, 0, 0, 0);
if (reg_renumber[allocno_reg[allocno_order[i]]] >= 0)
continue;
}
if (reg_alternate_class (allocno_reg[allocno_order[i]]) != NO_REGS)
- find_reg (allocno_order[i], HARD_CONST (0), 1, 0, 0);
+ find_reg (allocno_order[i], 0, 1, 0, 0);
}
}
@@ -577,34 +584,39 @@ global_alloc (file)
for the sake of debugging information. */
if (n_basic_blocks > 0)
#endif
- return reload (get_insns (), 1, file);
+ retval = reload (get_insns (), 1, file);
+
+ free (conflicts);
+ return retval;
}
/* Sort predicate for ordering the allocnos.
Returns -1 (1) if *v1 should be allocated before (after) *v2. */
static int
-allocno_compare (v1, v2)
- int *v1, *v2;
+allocno_compare (v1p, v2p)
+ const GENERIC_PTR v1p;
+ const GENERIC_PTR v2p;
{
+ int v1 = *(int *)v1p, v2 = *(int *)v2p;
/* 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 (allocno_n_refs[*v1]) * allocno_n_refs[*v1])
- / allocno_live_length[*v1])
- * 10000 * allocno_size[*v1]);
+ = (((double) (floor_log2 (allocno_n_refs[v1]) * allocno_n_refs[v1])
+ / allocno_live_length[v1])
+ * 10000 * allocno_size[v1]);
register int pri2
- = (((double) (floor_log2 (allocno_n_refs[*v2]) * allocno_n_refs[*v2])
- / allocno_live_length[*v2])
- * 10000 * allocno_size[*v2]);
+ = (((double) (floor_log2 (allocno_n_refs[v2]) * allocno_n_refs[v2])
+ / allocno_live_length[v2])
+ * 10000 * allocno_size[v2]);
if (pri2 - pri1)
return pri2 - pri1;
/* If regs are equally good, sort by allocno,
so that the results of qsort leave nothing to chance. */
- return *v1 - *v2;
+ return v1 - v2;
}
/* Scan the rtl code and record all conflicts and register preferences in the
@@ -640,41 +652,36 @@ global_conflicts ()
are explicitly marked in basic_block_live_at_start. */
{
- register int offset;
- REGSET_ELT_TYPE bit;
register regset old = basic_block_live_at_start[b];
int ax = 0;
-#ifdef HARD_REG_SET
- hard_regs_live = old[0];
-#else
- COPY_HARD_REG_SET (hard_regs_live, old);
-#endif
- for (offset = 0, i = 0; offset < regset_size; offset++)
- if (old[offset] == 0)
- i += REGSET_ELT_BITS;
- else
- for (bit = 1; bit; bit <<= 1, i++)
- {
- if (i >= max_regno)
- break;
- if (old[offset] & bit)
- {
- register int a = reg_allocno[i];
- if (a >= 0)
- {
- SET_ALLOCNO_LIVE (a);
- block_start_allocnos[ax++] = a;
- }
- else if ((a = reg_renumber[i]) >= 0)
- mark_reg_live_nc (a, PSEUDO_REGNO_MODE (i));
- }
- }
+ REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
+ EXECUTE_IF_SET_IN_REG_SET (old, FIRST_PSEUDO_REGISTER, i,
+ {
+ register int a = reg_allocno[i];
+ if (a >= 0)
+ {
+ SET_ALLOCNO_LIVE (a);
+ block_start_allocnos[ax++] = a;
+ }
+ else if ((a = reg_renumber[i]) >= 0)
+ mark_reg_live_nc
+ (a, PSEUDO_REGNO_MODE (i));
+ });
/* Record that each allocno now live conflicts with each other
allocno now live, and with each hard reg now live. */
record_conflicts (block_start_allocnos, ax);
+
+#ifdef STACK_REGS
+ /* Pseudos can't go in stack regs at the start of a basic block
+ that can be reached through a computed goto, since reg-stack
+ can't handle computed gotos. */
+ if (basic_block_computed_jump_target[b])
+ for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
+ record_one_conflict (ax);
+#endif
}
insn = basic_block_head[b];
@@ -869,7 +876,8 @@ prune_preferences ()
we want to give the lower-priority allocno the first chance for
these registers). */
for (j = i + 1; j < max_allocno; j++)
- if (CONFLICTP (allocno, allocno_order[j]))
+ if (CONFLICTP (allocno, allocno_order[j])
+ || CONFLICTP (allocno_order[j], allocno))
{
COPY_HARD_REG_SET (temp,
hard_reg_full_preferences[allocno_order[j]]);
@@ -937,7 +945,7 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
IOR_HARD_REG_SET (used1, hard_reg_conflicts[allocno]);
#ifdef CLASS_CANNOT_CHANGE_SIZE
- if (reg_changes_size[allocno_reg[allocno]])
+ if (REG_CHANGES_SIZE (allocno_reg[allocno]))
IOR_HARD_REG_SET (used1,
reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]);
#endif
@@ -1085,7 +1093,14 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
&& CALLER_SAVE_PROFITABLE (allocno_n_refs[allocno],
allocno_calls_crossed[allocno]))
{
- find_reg (allocno, losers, alt_regs_p, 1, retrying);
+ HARD_REG_SET new_losers;
+ if (! losers)
+ CLEAR_HARD_REG_SET (new_losers);
+ else
+ COPY_HARD_REG_SET (new_losers, losers);
+
+ IOR_HARD_REG_SET(new_losers, losing_caller_save_reg_set);
+ find_reg (allocno, new_losers, alt_regs_p, 1, retrying);
if (reg_renumber[allocno_reg[allocno]] >= 0)
{
caller_save_needed = 1;
@@ -1117,7 +1132,7 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying)
&& ! TEST_HARD_REG_BIT (used2, regno)
&& HARD_REGNO_MODE_OK (regno, mode)
#ifdef CLASS_CANNOT_CHANGE_SIZE
- && ! (reg_changes_size[allocno_reg[allocno]]
+ && ! (REG_CHANGES_SIZE (allocno_reg[allocno])
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE],
regno)))
@@ -1630,13 +1645,10 @@ mark_elimination (from, to)
int i;
for (i = 0; i < n_basic_blocks; i++)
- if ((basic_block_live_at_start[i][from / REGSET_ELT_BITS]
- & ((REGSET_ELT_TYPE) 1 << (from % REGSET_ELT_BITS))) != 0)
+ if (REGNO_REG_SET_P (basic_block_live_at_start[i], from))
{
- basic_block_live_at_start[i][from / REGSET_ELT_BITS]
- &= ~ ((REGSET_ELT_TYPE) 1 << (from % REGSET_ELT_BITS));
- basic_block_live_at_start[i][to / REGSET_ELT_BITS]
- |= ((REGSET_ELT_TYPE) 1 << (to % REGSET_ELT_BITS));
+ CLEAR_REGNO_REG_SET (basic_block_live_at_start[i], from);
+ SET_REGNO_REG_SET (basic_block_live_at_start[i], to);
}
}
OpenPOWER on IntegriCloud