summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1992-01-15 21:58:02 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>1992-01-15 21:58:02 +0000
commitca9902fc32856cc08accfbaf01047dcadb4f8b9f (patch)
treed6512fbd06ee1244603b7c69b713c38dbe35bd4c
parent9f25e1a4c4713f696faf251ce55cfd06dc5aa84d (diff)
downloadgcc-ca9902fc32856cc08accfbaf01047dcadb4f8b9f.tar.gz
*** empty log message ***
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@192 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/machmode.h2
-rw-r--r--gcc/output.h2
-rw-r--r--gcc/print-rtl.c2
-rw-r--r--gcc/recog.c2
-rw-r--r--gcc/regclass.c4
-rw-r--r--gcc/reload1.c184
-rw-r--r--gcc/rtl.c2
-rw-r--r--gcc/rtl.h29
8 files changed, 152 insertions, 75 deletions
diff --git a/gcc/machmode.h b/gcc/machmode.h
index 4f88de0f859..67bcb355fd3 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -1,5 +1,5 @@
/* Machine mode definitions for GNU C-Compiler; included by rtl.h and tree.h.
- Copyright (C) 1990-1991 Free Software Foundation, Inc.
+ Copyright (C) 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/gcc/output.h b/gcc/output.h
index 27a9d532740..edf68ffed34 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -1,6 +1,6 @@
/* Declarations for insn-output.c. These functions are defined in recog.c,
final.c, and varasm.c.
- Copyright (C) 1987-1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 75d0c0afa4b..ca048d66a2e 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -1,5 +1,5 @@
/* Print RTL for GNU C Compiler.
- Copyright (C) 1987-1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/gcc/recog.c b/gcc/recog.c
index 5828f759c48..c347bdf1924 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -1,5 +1,5 @@
/* Subroutines used by or related to instruction recognition.
- Copyright (C) 1987-1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/gcc/regclass.c b/gcc/regclass.c
index 8416a7cf6df..76df1e486ef 100644
--- a/gcc/regclass.c
+++ b/gcc/regclass.c
@@ -1,5 +1,5 @@
/* Compute register class preferences for pseudo-registers.
- Copyright (C) 1987-1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -327,7 +327,7 @@ fix_register (name, fixed, call_used)
the register info. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (!strcmp (reg_names[i], name))
+ if (reg_names[i][0] && ! strcmp (reg_names[i], name))
{
fixed_regs[i] = fixed;
call_used_regs[i] = call_used;
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 8af7b0caa58..b4f6fa3ac75 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -1,5 +1,5 @@
/* Reload pseudo regs into hard regs for insns that require hard regs.
- Copyright (C) 1987-1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -266,6 +266,7 @@ static struct elim_table
int can_eliminate_previous; /* Value of CAN_ELIMINATE in previous scan over
insns made by reload. */
int offset; /* Current offset between the two regs. */
+ int max_offset; /* Maximum offset between the two regs. */
int previous_offset; /* Offset at end of previous insn. */
int ref_outside_mem; /* "to" has been referenced outside a MEM. */
rtx from_rtx; /* REG rtx for the register to be eliminated.
@@ -493,7 +494,8 @@ reload (first, global, dumpfile)
int something_needs_reloads;
int something_needs_elimination;
int new_basic_block_needs;
- int caller_save_needs_spill;
+ enum reg_class caller_save_spill_class = NO_REGS;
+ int caller_save_group_size = 1;
/* The basic block number currently being processed for INSN. */
int this_block;
@@ -516,9 +518,9 @@ reload (first, global, dumpfile)
bzero (spill_stack_slot, sizeof spill_stack_slot);
bzero (spill_stack_slot_width, sizeof spill_stack_slot_width);
- /* If caller-saves are requested, initialize the required save areas. */
- if (flag_caller_saves)
- init_save_areas ();
+ /* Initialize the save area information for caller-save, in case some
+ are needed. */
+ init_save_areas ();
/* Compute which hard registers are now in use
as homes for pseudo registers.
@@ -566,7 +568,12 @@ reload (first, global, dumpfile)
if (set != 0 && GET_CODE (SET_DEST (set)) == REG)
{
rtx note = find_reg_note (insn, REG_EQUIV, 0);
- if (note)
+ if (note
+#ifdef LEGITIMATE_PIC_OPERAND_P
+ && (! CONSTANT_P (XEXP (note, 0)) || ! flag_pic
+ || LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0)))
+#endif
+ )
{
rtx x = XEXP (note, 0);
i = REGNO (SET_DEST (set));
@@ -792,7 +799,8 @@ reload (first, global, dumpfile)
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
{
INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset);
- ep->previous_offset = ep->offset = ep->initial_offset;
+ ep->previous_offset = ep->offset
+ = ep->max_offset = ep->initial_offset;
}
#else
#ifdef INITIAL_FRAME_POINTER_OFFSET
@@ -802,7 +810,7 @@ reload (first, global, dumpfile)
abort ();
reg_eliminate[0].initial_offset = 0;
#endif
- reg_eliminate[0].previous_offset
+ reg_eliminate[0].previous_offset = reg_eliminate[0].max_offset
= reg_eliminate[0].offset = reg_eliminate[0].initial_offset;
#endif
@@ -877,6 +885,15 @@ reload (first, global, dumpfile)
if (something_changed)
continue;
+ /* If caller-saves needs a group, initialize the group to include
+ the size and mode required for caller-saves. */
+
+ if (caller_save_group_size > 1)
+ {
+ group_mode[(int) caller_save_spill_class] = Pmode;
+ group_size[(int) caller_save_spill_class] = caller_save_group_size;
+ }
+
/* Compute the most additional registers needed by any instruction.
Collect information separately for each class of regs. */
@@ -927,14 +944,6 @@ reload (first, global, dumpfile)
int insn_groups_for_operands[N_REG_CLASSES];
int insn_total_groups_for_operands = 0;
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- insn_needs[i] = 0, insn_groups[i] = 0;
- insn_needs_for_inputs[i] = 0, insn_groups_for_inputs[i] = 0;
- insn_needs_for_outputs[i] = 0, insn_groups_for_outputs[i] = 0;
- insn_needs_for_operands[i] = 0, insn_groups_for_operands[i] = 0;
- }
-
#if 0 /* This wouldn't work nowadays, since optimize_bit_field
looks for non-strict memory addresses. */
/* Optimization: a bit-field instruction whose field
@@ -1014,11 +1023,25 @@ reload (first, global, dumpfile)
something_needs_elimination = 1;
}
- if (n_reloads == 0)
+ /* If this insn has no reloads, we need not do anything except
+ in the case of a CALL_INSN when we have caller-saves and
+ caller-save needs reloads. */
+
+ if (n_reloads == 0
+ && ! (GET_CODE (insn) == CALL_INSN
+ && caller_save_spill_class != NO_REGS))
continue;
something_needs_reloads = 1;
+ for (i = 0; i < N_REG_CLASSES; i++)
+ {
+ insn_needs[i] = 0, insn_groups[i] = 0;
+ insn_needs_for_inputs[i] = 0, insn_groups_for_inputs[i] = 0;
+ insn_needs_for_outputs[i] = 0, insn_groups_for_outputs[i] = 0;
+ insn_needs_for_operands[i] = 0, insn_groups_for_operands[i] = 0;
+ }
+
/* Count each reload once in every class
containing the reload's own class. */
@@ -1145,18 +1168,59 @@ reload (first, global, dumpfile)
if (insn_groups_for_operands[i] > this_max)
this_max = insn_groups_for_operands[i];
insn_groups[i] += this_max;
-
- if (global && (insn_needs[i] || insn_groups[i])
- && ! basic_block_needs[i][this_block])
- {
- new_basic_block_needs = 1;
- basic_block_needs[i][this_block] = 1;
- }
}
+
insn_total_groups += MAX (insn_total_groups_for_inputs,
MAX (insn_total_groups_for_outputs,
insn_total_groups_for_operands));
+ /* If this is a CALL_INSN and caller-saves will need
+ a spill register, act as if the spill register is
+ needed for this insn. However, the spill register
+ can be used by any reload of this insn, so we only
+ need do something if no need for that class has
+ been recorded.
+
+ The assumption that every CALL_INSN will trigger a
+ caller-save is highly conservative, however, the number
+ of cases where caller-saves will need a spill register but
+ a block containing a CALL_INSN won't need a spill register
+ of that class should be quite rare.
+
+ If a group is needed, the size and mode of the group will
+ have been set up at the begining of this loop. */
+
+ if (GET_CODE (insn) == CALL_INSN
+ && caller_save_spill_class != NO_REGS)
+ {
+ int *caller_save_needs
+ = (caller_save_group_size > 1 ? insn_groups : insn_needs);
+
+ if (caller_save_needs[(int) caller_save_spill_class] == 0)
+ {
+ register enum reg_class *p
+ = reg_class_superclasses[(int) caller_save_spill_class];
+
+ caller_save_needs[(int) caller_save_spill_class]++;
+
+ while (*p != LIM_REG_CLASSES)
+ caller_save_needs[*p++] += 1;
+ }
+
+ if (caller_save_group_size > 1)
+ insn_total_groups = MAX (insn_total_groups, 1);
+ }
+
+ /* Update the basic block needs. */
+
+ for (i = 0; i < N_REG_CLASSES; i++)
+ if (global && (insn_needs[i] || insn_groups[i])
+ && ! basic_block_needs[i][this_block])
+ {
+ new_basic_block_needs = 1;
+ basic_block_needs[i][this_block] = 1;
+ }
+
#ifdef SMALL_REGISTER_CLASSES
/* If this insn stores the value of a function call,
and that value is in a register that has been spilled,
@@ -1205,20 +1269,21 @@ reload (first, global, dumpfile)
}
/* If we have caller-saves, set up the save areas and see if caller-save
- will need a spill register. If it will and we don't already have a
- need of class BASE_REG_CLASS, create such a need. */
+ will need a spill register. */
if (caller_save_needed
- && 0 != (caller_save_needs_spill
- = ! setup_save_areas (&something_changed))
- && max_needs[(int) BASE_REG_CLASS] == 0)
+ && ! setup_save_areas (&something_changed)
+ && caller_save_spill_class == NO_REGS)
{
- register enum reg_class *p
- = reg_class_superclasses[(int) BASE_REG_CLASS];
-
- max_needs[(int) BASE_REG_CLASS] = 1;
- while (*p != LIM_REG_CLASSES)
- max_needs[(int) *p++] += 1;
+ /* The class we will need depends on whether the machine
+ supports the sum of two registers for an address; see
+ find_address_reloads for details. */
+
+ caller_save_spill_class
+ = double_reg_address_ok ? INDEX_REG_CLASS : BASE_REG_CLASS;
+ caller_save_group_size
+ = CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
+ something_changed = 1;
}
/* Now deduct from the needs for the registers already
@@ -1569,22 +1634,13 @@ reload (first, global, dumpfile)
reload_in_progress = 1;
/* Insert code to save and restore call-clobbered hard regs
- around calls. If caller-save needs a spill register, find one
- for it to use. */
+ around calls. Tell if what mode to use so that we will process
+ those insns in reload_as_needed if we have to. */
if (caller_save_needed)
- {
- register int regno = -1;
-
- if (caller_save_needs_spill)
- for (i = 0; i < n_spills; i++)
- if (TEST_HARD_REG_BIT (reg_class_contents[(int) BASE_REG_CLASS],
- spill_regs[i])
- && HARD_REGNO_MODE_OK (spill_regs[i], Pmode))
- regno = spill_regs[i];
-
- save_call_clobbered_regs (regno);
- }
+ save_call_clobbered_regs (num_eliminable ? QImode
+ : caller_save_spill_class != NO_REGS ? HImode
+ : VOIDmode);
/* If a pseudo has no hard reg, delete the insns that made the equivalence.
If that insn didn't set the register (i.e., it copied the register to
@@ -1611,7 +1667,9 @@ reload (first, global, dumpfile)
by generating move instructions to move the must-be-register
values into or out of the reload registers. */
- if (something_needs_reloads || something_needs_elimination)
+ if (something_needs_reloads || something_needs_elimination
+ || (caller_save_needed && num_eliminable)
+ || caller_save_spill_class != NO_REGS)
reload_as_needed (first, global);
reload_in_progress = 0;
@@ -2765,6 +2823,9 @@ eliminate_regs_in_insn (insn, replace)
/* Loop through all elimination pairs. See if any have changed and
recalculate the number not at initial offset.
+ Compute the maximum offset (minimum offset if the stack does not
+ grow downward) for each elimination pair.
+
We also detect a cases where register elimination cannot be done,
namely, if a register would be both changed and referenced outside a MEM
in the resulting insn since such an insn is often undefined and, even if
@@ -2788,6 +2849,12 @@ eliminate_regs_in_insn (insn, replace)
ep->previous_offset = ep->offset;
if (ep->can_eliminate && ep->offset != ep->initial_offset)
num_not_at_initial_offset++;
+
+#ifdef STACK_GROWS_DOWNWARD
+ ep->max_offset = MAX (ep->max_offset, ep->offset);
+#else
+ ep->max_offset = MIN (ep->max_offset, ep->offset);
+#endif
}
done:
@@ -4362,6 +4429,7 @@ emit_reload_insns (insn)
{
register int j;
rtx following_insn = NEXT_INSN (insn);
+ rtx before_insn = insn;
rtx first_output_reload_insn = NEXT_INSN (insn);
rtx first_other_reload_insn = insn;
rtx first_operand_address_reload_insn = insn;
@@ -4369,6 +4437,16 @@ emit_reload_insns (insn)
/* Values to be put in spill_reg_store are put here first. */
rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
+ /* If this is a CALL_INSN preceeded by USE insns, any reload insns
+ must go in front of the first USE insn, not in front of INSN. */
+
+ if (GET_CODE (insn) == CALL_INSN && GET_CODE (PREV_INSN (insn)) == INSN
+ && GET_CODE (PATTERN (PREV_INSN (insn))) == USE)
+ while (GET_CODE (PREV_INSN (before_insn)) == INSN
+ && GET_CODE (PATTERN (PREV_INSN (before_insn))) == USE)
+ first_other_reload_insn = first_operand_address_reload_insn
+ = before_insn = PREV_INSN (before_insn);
+
/* Now output the instructions to copy the data into and out of the
reload registers. Do these in the order that the reloads were reported,
since reloads of base and index registers precede reloads of operands
@@ -4520,7 +4598,7 @@ emit_reload_insns (insn)
where = first_output_reload_insn;
break;
case RELOAD_FOR_OPERAND_ADDRESS:
- where = insn;
+ where = before_insn;
}
special = 0;
@@ -4761,9 +4839,9 @@ emit_reload_insns (insn)
first_other_reload_insn = this_reload_insn;
break;
case RELOAD_FOR_OPERAND_ADDRESS:
- if (first_operand_address_reload_insn == insn)
+ if (first_operand_address_reload_insn == before_insn)
first_operand_address_reload_insn = this_reload_insn;
- if (first_other_reload_insn == insn)
+ if (first_other_reload_insn == before_insn)
first_other_reload_insn = this_reload_insn;
}
diff --git a/gcc/rtl.c b/gcc/rtl.c
index 8b8a1372994..b82e5f13968 100644
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -1,5 +1,5 @@
/* Allocate and read RTL for GNU C Compiler.
- Copyright (C) 1987-1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 62a7811d07a..814068d7e0d 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1,5 +1,5 @@
/* Register Transfer Language (RTL) definitions for GNU C-Compiler
- Copyright (C) 1987-1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1991 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -649,22 +649,21 @@ extern rtx pc_rtx;
extern rtx cc0_rtx;
extern rtx const0_rtx;
extern rtx const1_rtx;
+extern rtx const2_rtx;
extern rtx constm1_rtx;
extern rtx const_true_rtx;
-extern rtx fconst0_rtx;
-extern rtx fconst1_rtx;
-extern rtx fconst2_rtx;
-extern rtx dconst0_rtx;
-extern rtx dconst1_rtx;
-extern rtx dconst2_rtx;
-
-/* Returns a constant 0 rtx in mode MODE. */
-
-#define CONST0_RTX(MODE) \
- ((MODE == SFmode) ? fconst0_rtx \
- : ((MODE == DFmode) ? dconst0_rtx \
- : ((GET_MODE_CLASS (MODE) == MODE_INT) ? const0_rtx \
- : (abort (), NULL_RTX))))
+
+extern rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE];
+
+/* Returns a constant 0 rtx in mode MODE. Integer modes are treated the
+ same as VOIDmode. */
+
+#define CONST0_RTX(MODE) (const_tiny_rtx[0][(int) (MODE)])
+
+/* Likewise, for the constants 1 and 2. */
+
+#define CONST1_RTX(MODE) (const_tiny_rtx[1][(int) (MODE)])
+#define CONST2_RTX(MODE) (const_tiny_rtx[2][(int) (MODE)])
/* All references to certain hard regs, except those created
by allocating pseudo regs into them (when that's possible),