summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/reload1.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/reload1.c')
-rw-r--r--contrib/gcc/reload1.c356
1 files changed, 183 insertions, 173 deletions
diff --git a/contrib/gcc/reload1.c b/contrib/gcc/reload1.c
index 5928a68..3000f61 100644
--- a/contrib/gcc/reload1.c
+++ b/contrib/gcc/reload1.c
@@ -1,6 +1,6 @@
/* Reload pseudo regs into hard regs for insns that require hard regs.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
@@ -139,7 +139,7 @@ static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];
when reg_reloaded_valid is set for this register. */
static rtx reg_reloaded_insn[FIRST_PSEUDO_REGISTER];
-/* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid */
+/* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid. */
static HARD_REG_SET reg_reloaded_valid;
/* Indicate if the register was dead at the end of the reload.
This is only valid if reg_reloaded_contents is set and valid. */
@@ -280,9 +280,6 @@ char *reload_firstobj;
Used to quickly free all memory after processing one insn. */
static char *reload_insn_firstobj;
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-
/* List of insn_chain instructions, one for every insn that reload needs to
examine. */
struct insn_chain *reload_insn_chain;
@@ -343,7 +340,7 @@ static const struct elim_table_1
#define NUM_ELIMINABLE_REGS ARRAY_SIZE (reg_eliminate_1)
/* Record the number of pending eliminations that have an offset not equal
- to their initial offset. If non-zero, we use a new copy of each
+ to their initial offset. If nonzero, we use a new copy of each
replacement result in any insns encountered. */
int num_not_at_initial_offset;
@@ -355,11 +352,14 @@ static int num_eliminable_invariants;
/* For each label, we record the offset of each elimination. If we reach
a label by more than one path and an offset differs, we cannot do the
- elimination. This information is indexed by the number of the label.
- The first table is an array of flags that records whether we have yet
- encountered a label and the second table is an array of arrays, one
- entry in the latter array for each elimination. */
-
+ elimination. This information is indexed by the difference of the
+ number of the label and the first label number. We can't offset the
+ pointer itself as this can cause problems on machines with segmented
+ memory. The first table is an array of flags that records whether we
+ have yet encountered a label and the second table is an array of arrays,
+ one entry in the latter array for each elimination. */
+
+static int first_label_num;
static char *offsets_known_at;
static int (*offsets_at)[NUM_ELIMINABLE_REGS];
@@ -443,7 +443,7 @@ static rtx inc_for_reload PARAMS ((rtx, rtx, rtx, int));
static void reload_cse_regs_1 PARAMS ((rtx));
static int reload_cse_noop_set_p PARAMS ((rtx));
static int reload_cse_simplify_set PARAMS ((rtx, rtx));
-static int reload_cse_simplify_operands PARAMS ((rtx));
+static int reload_cse_simplify_operands PARAMS ((rtx, rtx));
static void reload_combine PARAMS ((void));
static void reload_combine_note_use PARAMS ((rtx *, rtx));
static void reload_combine_note_store PARAMS ((rtx, rtx, void *));
@@ -457,8 +457,7 @@ static HOST_WIDE_INT sext_for_mode PARAMS ((enum machine_mode,
HOST_WIDE_INT));
static void failed_reload PARAMS ((rtx, int));
static int set_reload_reg PARAMS ((int, int));
-static void reload_cse_delete_noop_set PARAMS ((rtx, rtx));
-static void reload_cse_simplify PARAMS ((rtx));
+static void reload_cse_simplify PARAMS ((rtx, rtx));
void fixup_abnormal_edges PARAMS ((void));
extern void dump_needs PARAMS ((struct insn_chain *));
@@ -675,11 +674,7 @@ reload (first, global)
int i;
rtx insn;
struct elim_table *ep;
-
- /* The two pointers used to track the true location of the memory used
- for label offsets. */
- char *real_known_ptr = NULL;
- int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
+ basic_block bb;
/* Make sure even insns with volatile mem refs are recognizable. */
init_recog ();
@@ -820,8 +815,12 @@ reload (first, global)
else if (LEGITIMATE_CONSTANT_P (x))
reg_equiv_constant[i] = x;
else
- reg_equiv_memory_loc[i]
- = force_const_mem (GET_MODE (SET_DEST (set)), x);
+ {
+ reg_equiv_memory_loc[i]
+ = force_const_mem (GET_MODE (SET_DEST (set)), x);
+ if (!reg_equiv_memory_loc[i])
+ continue;
+ }
}
else
continue;
@@ -855,21 +854,18 @@ reload (first, global)
init_elim_table ();
- num_labels = max_label_num () - get_first_label_num ();
+ first_label_num = get_first_label_num ();
+ num_labels = max_label_num () - first_label_num;
/* Allocate the tables used to store offset information at labels. */
/* 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 a core dump. */
- real_known_ptr = xmalloc (num_labels);
- real_at_ptr
+ offsets_known_at = xmalloc (num_labels);
+ offsets_at
= (int (*)[NUM_ELIMINABLE_REGS])
xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (int));
- offsets_known_at = real_known_ptr - get_first_label_num ();
- offsets_at
- = (int (*)[NUM_ELIMINABLE_REGS]) (real_at_ptr - get_first_label_num ());
-
/* Alter each pseudo-reg rtx to contain its hard reg number.
Assign stack slots to the pseudos that lack hard regs or equivalents.
Do not touch virtual registers. */
@@ -1026,7 +1022,7 @@ reload (first, global)
did_spill = 1;
/* Regardless of the state of spills, if we previously had
- a register that we thought we could eliminate, but no can
+ a register that we thought we could eliminate, but now can
not eliminate, we must run another pass.
Consider pseudos which have an entry in reg_equiv_* which
@@ -1122,8 +1118,8 @@ reload (first, global)
pseudo. */
if (! frame_pointer_needed)
- for (i = 0; i < n_basic_blocks; i++)
- CLEAR_REGNO_REG_SET (BASIC_BLOCK (i)->global_live_at_start,
+ FOR_EACH_BB (bb)
+ CLEAR_REGNO_REG_SET (bb->global_live_at_start,
HARD_FRAME_POINTER_REGNUM);
/* Come here (with failure set nonzero) if we can't get enough spill regs
@@ -1159,9 +1155,9 @@ reload (first, global)
{
rtx reg = regno_reg_rtx[i];
+ REG_USERVAR_P (reg) = 0;
PUT_CODE (reg, MEM);
XEXP (reg, 0) = addr;
- REG_USERVAR_P (reg) = 0;
if (reg_equiv_memory_loc[i])
MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
else
@@ -1183,10 +1179,12 @@ reload (first, global)
/* Make a pass over all the insns and delete all USEs which we inserted
only to tag a REG_EQUAL note on them. Remove all REG_DEAD and REG_UNUSED
- notes. Delete all CLOBBER insns that don't refer to the return value
- and simplify (subreg (reg)) operands. Also remove all REG_RETVAL and
- REG_LIBCALL notes since they are no longer useful or accurate. Strip
- and regenerate REG_INC notes that may have been moved around. */
+ notes. Delete all CLOBBER insns, except those that refer to the return
+ value and the special mem:BLK CLOBBERs added to prevent the scheduler
+ from misarranging variable-array code, and simplify (subreg (reg))
+ operands. Also remove all REG_RETVAL and REG_LIBCALL notes since they
+ are no longer useful or accurate. Strip and regenerate REG_INC notes
+ that may have been moved around. */
for (insn = first; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
@@ -1203,6 +1201,11 @@ reload (first, global)
&& (GET_MODE (insn) == QImode
|| find_reg_note (insn, REG_EQUAL, NULL_RTX)))
|| (GET_CODE (PATTERN (insn)) == CLOBBER
+ && (GET_CODE (XEXP (PATTERN (insn), 0)) != MEM
+ || GET_MODE (XEXP (PATTERN (insn), 0)) != BLKmode
+ || (GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) != SCRATCH
+ && XEXP (XEXP (PATTERN (insn), 0), 0)
+ != stack_pointer_rtx))
&& (GET_CODE (XEXP (PATTERN (insn), 0)) != REG
|| ! REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))))
{
@@ -1261,10 +1264,10 @@ reload (first, global)
free (reg_equiv_memory_loc);
reg_equiv_memory_loc = 0;
- if (real_known_ptr)
- free (real_known_ptr);
- if (real_at_ptr)
- free (real_at_ptr);
+ if (offsets_known_at)
+ free (offsets_known_at);
+ if (offsets_at)
+ free (offsets_at);
free (reg_equiv_mem);
free (reg_equiv_init);
@@ -1383,8 +1386,12 @@ maybe_fix_stack_asms ()
break;
default:
- cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
-
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
+ cls = (int) reg_class_subunion[cls]
+ [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+ else
+ cls = (int) reg_class_subunion[cls]
+ [(int) REG_CLASS_FROM_LETTER (c)];
}
}
}
@@ -1489,7 +1496,7 @@ calculate_needs_all_insns (global)
&& REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
{
delete_insn (insn);
- /* Delete it from the reload chain */
+ /* Delete it from the reload chain. */
if (chain->prev)
chain->prev->next = next;
else
@@ -2110,7 +2117,7 @@ mark_home_live (regno)
INSN is the insn that it came from, if any.
- INITIAL_P is non-zero if we are to set the offset to be the initial
+ INITIAL_P is nonzero if we are to set the offset to be the initial
offset and zero if we are setting the offset of the label to be the
current offset. */
@@ -2143,13 +2150,13 @@ set_label_offsets (x, insn, initial_p)
we guessed wrong, we will suppress an elimination that might have
been possible had we been able to guess correctly. */
- if (! offsets_known_at[CODE_LABEL_NUMBER (x)])
+ if (! offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num])
{
for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
- offsets_at[CODE_LABEL_NUMBER (x)][i]
+ offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
= (initial_p ? reg_eliminate[i].initial_offset
: reg_eliminate[i].offset);
- offsets_known_at[CODE_LABEL_NUMBER (x)] = 1;
+ offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num] = 1;
}
/* Otherwise, if this is the definition of a label and it is
@@ -2166,7 +2173,7 @@ set_label_offsets (x, insn, initial_p)
where the offsets disagree. */
for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
- if (offsets_at[CODE_LABEL_NUMBER (x)][i]
+ if (offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
!= (initial_p ? reg_eliminate[i].initial_offset
: reg_eliminate[i].offset))
reg_eliminate[i].can_eliminate = 0;
@@ -2265,7 +2272,7 @@ set_label_offsets (x, insn, initial_p)
to record the fact that a register is referenced outside a MEM.
If INSN is an insn, it is the insn containing X. If we replace a REG
- in a SET_DEST with an equivalent MEM and INSN is non-zero, write a
+ in a SET_DEST with an equivalent MEM and INSN is nonzero, write a
CLOBBER of the pseudo after INSN so find_equiv_regs will know that
the REG is being modified.
@@ -3221,7 +3228,7 @@ eliminate_regs_in_insn (insn, replace)
insn. The changes we make were determined by the earlier call to
elimination_effects.
- We also detect a cases where register elimination cannot be done,
+ We also detect 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
not, we cannot know what meaning will be given to it. Note that it is
@@ -3375,7 +3382,7 @@ static void
set_initial_label_offsets ()
{
rtx x;
- memset ((char *) &offsets_known_at[get_first_label_num ()], 0, num_labels);
+ memset (offsets_known_at, 0, num_labels);
for (x = forced_labels; x; x = XEXP (x, 1))
if (XEXP (x, 0))
@@ -3396,14 +3403,15 @@ set_offsets_for_label (insn)
num_not_at_initial_offset = 0;
for (i = 0, ep = reg_eliminate; i < NUM_ELIMINABLE_REGS; ep++, i++)
{
- ep->offset = ep->previous_offset = offsets_at[label_nr][i];
+ ep->offset = ep->previous_offset
+ = offsets_at[label_nr - first_label_num][i];
if (ep->can_eliminate && ep->offset != ep->initial_offset)
num_not_at_initial_offset++;
}
}
/* See if anything that happened changes which eliminations are valid.
- For example, on the Sparc, whether or not the frame pointer can
+ For example, on the SPARC, whether or not the frame pointer can
be eliminated can depend on what registers have been used. We need
not check some conditions again (such as flag_omit_frame_pointer)
since they can't have changed. */
@@ -3412,9 +3420,7 @@ static void
update_eliminables (pset)
HARD_REG_SET *pset;
{
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
int previous_frame_pointer_needed = frame_pointer_needed;
-#endif
struct elim_table *ep;
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
@@ -3479,12 +3485,10 @@ update_eliminables (pset)
}
}
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
/* If we didn't need a frame pointer last time, but we do now, spill
the hard frame pointer. */
if (frame_pointer_needed && ! previous_frame_pointer_needed)
SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
-#endif
}
/* Initialize the table of registers to eliminate. */
@@ -3842,7 +3846,7 @@ reload_as_needed (live_known)
else if (INSN_P (insn))
{
- rtx oldpat = PATTERN (insn);
+ rtx oldpat = copy_rtx (PATTERN (insn));
/* If this is a USE and CLOBBER of a MEM, ensure that any
references to eliminable registers have been removed. */
@@ -3926,6 +3930,7 @@ reload_as_needed (live_known)
if (asm_noperands (PATTERN (insn)) >= 0)
for (p = NEXT_INSN (prev); p != next; p = NEXT_INSN (p))
if (p != insn && INSN_P (p)
+ && GET_CODE (PATTERN (p)) != USE
&& (recog_memoized (p) < 0
|| (extract_insn (p), ! constrain_operands (1))))
{
@@ -4097,23 +4102,21 @@ forget_old_reloads_1 (x, ignored, data)
{
unsigned int regno;
unsigned int nr;
- int offset = 0;
/* note_stores does give us subregs of hard regs,
subreg_regno_offset will abort if it is not a hard reg. */
while (GET_CODE (x) == SUBREG)
{
- offset += subreg_regno_offset (REGNO (SUBREG_REG (x)),
- GET_MODE (SUBREG_REG (x)),
- SUBREG_BYTE (x),
- GET_MODE (x));
+ /* We ignore the subreg offset when calculating the regno,
+ because we are using the entire underlying hard register
+ below. */
x = SUBREG_REG (x);
}
if (GET_CODE (x) != REG)
return;
- regno = REGNO (x) + offset;
+ regno = REGNO (x);
if (regno >= FIRST_PSEUDO_REGISTER)
nr = 1;
@@ -4326,7 +4329,7 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
abort ();
}
/* We resolve conflicts with remaining reloads of the same type by
- excluding the intervals of of reload registers by them from the
+ excluding the intervals of reload registers by them from the
interval of freed reload registers. Since we only keep track of
one set of interval bounds, we might have to exclude somewhat
more than what would be necessary if we used a HARD_REG_SET here.
@@ -4746,7 +4749,7 @@ char reload_inherited[MAX_RELOADS];
if we know it. Otherwise, this is 0. */
rtx reload_inheritance_insn[MAX_RELOADS];
-/* If non-zero, this is a place to get the value of the reload,
+/* If nonzero, this is a place to get the value of the reload,
rather than using reload_in. */
rtx reload_override_in[MAX_RELOADS];
@@ -4987,7 +4990,7 @@ reload_reg_free_for_value_p (start_regno, regno, opnum, type, value, out,
determine how many hard regs to test.
Other read-only reloads with the same value do not conflict
- unless OUT is non-zero and these other reloads have to live while
+ unless OUT is nonzero and these other reloads have to live while
output reloads live.
If OUT is CONST0_RTX, this is a special case: it means that the
test should not be for using register REGNO as reload register, but
@@ -5110,7 +5113,7 @@ set_reload_reg (i, r)
}
/* Find a spill register to use as a reload register for reload R.
- LAST_RELOAD is non-zero if this is the last reload for the insn being
+ LAST_RELOAD is nonzero if this is the last reload for the insn being
processed.
Set rld[R].reg_rtx to the register allocated.
@@ -5488,16 +5491,15 @@ choose_reload_regs (chain)
GET_MODE_CLASS (mode));
if (
-#ifdef CLASS_CANNOT_CHANGE_MODE
- (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], i)
- ? ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (last_reg),
- need_mode)
- : (GET_MODE_SIZE (GET_MODE (last_reg))
- >= GET_MODE_SIZE (need_mode)))
-#else
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ (!REG_CANNOT_CHANGE_MODE_P (i, GET_MODE (last_reg),
+ need_mode)
+ &&
+#endif
(GET_MODE_SIZE (GET_MODE (last_reg))
>= GET_MODE_SIZE (need_mode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ )
#endif
&& reg_reloaded_contents[i] == regno
&& TEST_HARD_REG_BIT (reg_reloaded_valid, i)
@@ -5745,8 +5747,8 @@ choose_reload_regs (chain)
/* If we found an equivalent reg, say no code need be generated
to load it, and use it as our reload reg. */
- if (equiv != 0
- && (regno != HARD_FRAME_POINTER_REGNUM
+ if (equiv != 0
+ && (regno != HARD_FRAME_POINTER_REGNUM
|| !frame_pointer_needed))
{
int nr = HARD_REGNO_NREGS (regno, rld[r].mode);
@@ -6003,7 +6005,7 @@ deallocate_reload_reg (r)
reload_spill_index[r] = -1;
}
-/* If SMALL_REGISTER_CLASSES is non-zero, we may not have merged two
+/* If SMALL_REGISTER_CLASSES is nonzero, we may not have merged two
reloads of the same item for fear that we might not have enough reload
registers. However, normally they will get the same reload register
and hence actually need not be loaded twice.
@@ -6098,17 +6100,41 @@ merge_assigned_reloads (insn)
if they were for inputs, RELOAD_OTHER for outputs. Note that
this test is equivalent to looking for reloads for this operand
number. */
+ /* We must take special care when there are two or more reloads to
+ be merged and a RELOAD_FOR_OUTPUT_ADDRESS reload that loads the
+ same value or a part of it; we must not change its type if there
+ is a conflicting input. */
if (rld[i].when_needed == RELOAD_OTHER)
for (j = 0; j < n_reloads; j++)
if (rld[j].in != 0
&& rld[j].when_needed != RELOAD_OTHER
+ && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS
+ && (! conflicting_input
+ || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+ || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
&& reg_overlap_mentioned_for_reload_p (rld[j].in,
rld[i].in))
- rld[j].when_needed
- = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
- || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
- ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
+ {
+ int k;
+
+ rld[j].when_needed
+ = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+ || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
+ ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
+
+ /* Check to see if we accidentally converted two reloads
+ that use the same reload register with different inputs
+ to the same type. If so, the resulting code won't work,
+ so abort. */
+ if (rld[j].reg_rtx)
+ for (k = 0; k < j; k++)
+ if (rld[k].in != 0 && rld[k].reg_rtx != 0
+ && rld[k].when_needed == rld[j].when_needed
+ && rtx_equal_p (rld[k].reg_rtx, rld[j].reg_rtx)
+ && ! rtx_equal_p (rld[k].in, rld[j].in))
+ abort ();
+ }
}
}
}
@@ -6615,7 +6641,7 @@ emit_input_reload_insns (chain, rl, old, j)
/* End this sequence. */
*where = get_insns ();
end_sequence ();
-
+
/* Update reload_override_in so that delete_address_reloads_1
can see the actual register usage. */
if (oldequiv_reg)
@@ -6824,7 +6850,7 @@ emit_output_reload_insns (chain, rl, j)
if (rl->when_needed == RELOAD_OTHER)
{
- emit_insns (other_output_reload_insns[rl->opnum]);
+ emit_insn (other_output_reload_insns[rl->opnum]);
other_output_reload_insns[rl->opnum] = get_insns ();
}
else
@@ -7040,25 +7066,25 @@ emit_reload_insns (chain)
reloads for the operand. The RELOAD_OTHER output reloads are
output in descending order by reload number. */
- emit_insns_before (other_input_address_reload_insns, insn);
- emit_insns_before (other_input_reload_insns, insn);
+ emit_insn_before (other_input_address_reload_insns, insn);
+ emit_insn_before (other_input_reload_insns, insn);
for (j = 0; j < reload_n_operands; j++)
{
- emit_insns_before (inpaddr_address_reload_insns[j], insn);
- emit_insns_before (input_address_reload_insns[j], insn);
- emit_insns_before (input_reload_insns[j], insn);
+ emit_insn_before (inpaddr_address_reload_insns[j], insn);
+ emit_insn_before (input_address_reload_insns[j], insn);
+ emit_insn_before (input_reload_insns[j], insn);
}
- emit_insns_before (other_operand_reload_insns, insn);
- emit_insns_before (operand_reload_insns, insn);
+ emit_insn_before (other_operand_reload_insns, insn);
+ emit_insn_before (operand_reload_insns, insn);
for (j = 0; j < reload_n_operands; j++)
{
- rtx x = emit_insns_after (outaddr_address_reload_insns[j], insn);
- x = emit_insns_after (output_address_reload_insns[j], x);
- x = emit_insns_after (output_reload_insns[j], x);
- emit_insns_after (other_output_reload_insns[j], x);
+ rtx x = emit_insn_after (outaddr_address_reload_insns[j], insn);
+ x = emit_insn_after (output_address_reload_insns[j], x);
+ x = emit_insn_after (output_reload_insns[j], x);
+ emit_insn_after (other_output_reload_insns[j], x);
}
/* For all the spill regs newly reloaded in this instruction,
@@ -7165,8 +7191,7 @@ emit_reload_insns (chain)
for (k = 1; k < nnr; k++)
reg_last_reload_reg[nregno + k]
= (nr == nnr
- ? gen_rtx_REG (reg_raw_mode[REGNO (rld[r].reg_rtx) + k],
- REGNO (rld[r].reg_rtx) + k)
+ ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
: 0);
/* Now do the inverse operation. */
@@ -7215,8 +7240,7 @@ emit_reload_insns (chain)
for (k = 1; k < nnr; k++)
reg_last_reload_reg[nregno + k]
= (nr == nnr
- ? gen_rtx_REG (reg_raw_mode[REGNO (rld[r].reg_rtx) + k],
- REGNO (rld[r].reg_rtx) + k)
+ ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
: 0);
/* Unless we inherited this reload, show we haven't
@@ -7358,9 +7382,6 @@ gen_reload (out, in, opnum, type)
{
rtx last = get_last_insn ();
rtx tem;
-#ifdef SECONDARY_MEMORY_NEEDED
- int in_regnum, out_regnum;
-#endif
/* If IN is a paradoxical SUBREG, remove it and try to put the
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
@@ -7523,22 +7544,22 @@ gen_reload (out, in, opnum, type)
#ifdef SECONDARY_MEMORY_NEEDED
/* If we need a memory location to do the move, do it that way. */
- else if ((in_regnum = true_regnum (in)) >= 0
- && in_regnum < FIRST_PSEUDO_REGISTER
- && (out_regnum = true_regnum (out)) >= 0
- && out_regnum < FIRST_PSEUDO_REGISTER
- && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (in_regnum),
- REGNO_REG_CLASS (out_regnum),
+ else if ((GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
+ && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
+ && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG)
+ && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
+ && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
+ REGNO_REG_CLASS (reg_or_subregno (out)),
GET_MODE (out)))
{
/* Get the memory to use and rewrite both registers to its mode. */
rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
if (GET_MODE (loc) != GET_MODE (out))
- out = gen_rtx_REG (GET_MODE (loc), out_regnum);
+ out = gen_rtx_REG (GET_MODE (loc), REGNO (out));
if (GET_MODE (loc) != GET_MODE (in))
- in = gen_rtx_REG (GET_MODE (loc), in_regnum);
+ in = gen_rtx_REG (GET_MODE (loc), REGNO (in));
gen_reload (loc, in, opnum, type);
gen_reload (out, loc, opnum, type);
@@ -7920,7 +7941,7 @@ inc_for_reload (reloadreg, in, value, inc_amount)
rtx real_in = in == value ? XEXP (in, 0) : in;
/* No hard register is equivalent to this register after
- inc/dec operation. If REG_LAST_RELOAD_REG were non-zero,
+ inc/dec operation. If REG_LAST_RELOAD_REG were nonzero,
we could inc/dec that register as well (maybe even using it for
the source), but I'm not sure it's worth worrying about. */
if (GET_CODE (incloc) == REG)
@@ -7995,30 +8016,6 @@ inc_for_reload (reloadreg, in, value, inc_amount)
return store;
}
-/* INSN is a no-op; delete it.
- If this sets the return value of the function, we must keep a USE around,
- in case this is in a different basic block than the final USE. Otherwise,
- we could loose important register lifeness information on
- SMALL_REGISTER_CLASSES machines, where return registers might be used as
- spills: subsequent passes assume that spill registers are dead at the end
- of a basic block.
- VALUE must be the return value in such a case, NULL otherwise. */
-static void
-reload_cse_delete_noop_set (insn, value)
- rtx insn, value;
-{
- bool purge = BLOCK_FOR_INSN (insn)->end == insn;
- if (value)
- {
- PATTERN (insn) = gen_rtx_USE (VOIDmode, value);
- INSN_CODE (insn) = -1;
- REG_NOTES (insn) = NULL_RTX;
- }
- else
- delete_insn (insn);
- if (purge)
- purge_dead_edges (BLOCK_FOR_INSN (insn));
-}
/* See whether a single set SET is a noop. */
static int
@@ -8030,8 +8027,9 @@ reload_cse_noop_set_p (set)
/* Try to simplify INSN. */
static void
-reload_cse_simplify (insn)
+reload_cse_simplify (insn, testreg)
rtx insn;
+ rtx testreg;
{
rtx body = PATTERN (insn);
@@ -8049,16 +8047,17 @@ reload_cse_simplify (insn)
if (!count && reload_cse_noop_set_p (body))
{
rtx value = SET_DEST (body);
- if (! REG_FUNCTION_VALUE_P (SET_DEST (body)))
+ if (REG_P (value)
+ && ! REG_FUNCTION_VALUE_P (value))
value = 0;
- reload_cse_delete_noop_set (insn, value);
+ delete_insn_and_edges (insn);
return;
}
if (count > 0)
apply_change_group ();
else
- reload_cse_simplify_operands (insn);
+ reload_cse_simplify_operands (insn, testreg);
}
else if (GET_CODE (body) == PARALLEL)
{
@@ -8075,7 +8074,8 @@ reload_cse_simplify (insn)
{
if (! reload_cse_noop_set_p (part))
break;
- if (REG_FUNCTION_VALUE_P (SET_DEST (part)))
+ if (REG_P (SET_DEST (part))
+ && REG_FUNCTION_VALUE_P (SET_DEST (part)))
{
if (value)
break;
@@ -8088,7 +8088,7 @@ reload_cse_simplify (insn)
if (i < 0)
{
- reload_cse_delete_noop_set (insn, value);
+ delete_insn_and_edges (insn);
/* We're done with this insn. */
return;
}
@@ -8101,7 +8101,7 @@ reload_cse_simplify (insn)
if (count > 0)
apply_change_group ();
else
- reload_cse_simplify_operands (insn);
+ reload_cse_simplify_operands (insn, testreg);
}
}
@@ -8127,6 +8127,7 @@ reload_cse_regs_1 (first)
rtx first;
{
rtx insn;
+ rtx testreg = gen_rtx_REG (VOIDmode, -1);
cselib_init ();
init_alias_analysis ();
@@ -8134,7 +8135,7 @@ reload_cse_regs_1 (first)
for (insn = first; insn; insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
- reload_cse_simplify (insn);
+ reload_cse_simplify (insn, testreg);
cselib_process_insn (insn);
}
@@ -8192,7 +8193,7 @@ reload_cse_simplify_set (set, insn)
#ifdef LOAD_EXTEND_OP
/* When replacing a memory with a register, we need to honor assumptions
that combine made wrt the contents of sign bits. We'll do this by
- generating an extend instruction instead of a reg->reg copy. Thus
+ generating an extend instruction instead of a reg->reg copy. Thus
the destination must be a register that we can widen. */
if (GET_CODE (src) == MEM
&& GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
@@ -8277,7 +8278,13 @@ reload_cse_simplify_set (set, insn)
{
#ifdef LOAD_EXTEND_OP
if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
- && extend_op != NIL)
+ && extend_op != NIL
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SET_DEST (set)),
+ word_mode,
+ REGNO_REG_CLASS (REGNO (SET_DEST (set))))
+#endif
+ )
{
rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
@@ -8305,8 +8312,9 @@ reload_cse_simplify_set (set, insn)
hard registers. */
static int
-reload_cse_simplify_operands (insn)
+reload_cse_simplify_operands (insn, testreg)
rtx insn;
+ rtx testreg;
{
int i, j;
@@ -8326,7 +8334,6 @@ reload_cse_simplify_operands (insn)
int *op_alt_regno[MAX_RECOG_OPERANDS];
/* Array of alternatives, sorted in order of decreasing desirability. */
int *alternative_order;
- rtx reg = gen_rtx_REG (VOIDmode, -1);
extract_insn (insn);
@@ -8410,8 +8417,8 @@ reload_cse_simplify_operands (insn)
if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
continue;
- REGNO (reg) = regno;
- PUT_MODE (reg, mode);
+ REGNO (testreg) = regno;
+ PUT_MODE (testreg, mode);
/* We found a register equal to this operand. Now look for all
alternatives that can accept this register and have not been
@@ -8453,10 +8460,10 @@ reload_cse_simplify_operands (insn)
alternative yet and the operand being replaced is not
a cheap CONST_INT. */
if (op_alt_regno[i][j] == -1
- && reg_fits_class_p (reg, class, 0, mode)
+ && reg_fits_class_p (testreg, class, 0, mode)
&& (GET_CODE (recog_data.operand[i]) != CONST_INT
|| (rtx_cost (recog_data.operand[i], SET)
- > rtx_cost (reg, SET))))
+ > rtx_cost (testreg, SET))))
{
alternative_nregs[j]++;
op_alt_regno[i][j] = regno;
@@ -8583,6 +8590,7 @@ reload_combine ()
int first_index_reg = -1;
int last_index_reg = 0;
int i;
+ basic_block bb;
unsigned int r;
int last_label_ruid;
int min_labelno, n_labels;
@@ -8618,17 +8626,17 @@ reload_combine ()
label_live = (HARD_REG_SET *) xmalloc (n_labels * sizeof (HARD_REG_SET));
CLEAR_HARD_REG_SET (ever_live_at_start);
- for (i = n_basic_blocks - 1; i >= 0; i--)
+ FOR_EACH_BB_REVERSE (bb)
{
- insn = BLOCK_HEAD (i);
+ insn = bb->head;
if (GET_CODE (insn) == CODE_LABEL)
{
HARD_REG_SET live;
REG_SET_TO_HARD_REG_SET (live,
- BASIC_BLOCK (i)->global_live_at_start);
+ bb->global_live_at_start);
compute_use_by_pseudos (&live,
- BASIC_BLOCK (i)->global_live_at_start);
+ bb->global_live_at_start);
COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
IOR_HARD_REG_SET (ever_live_at_start, live);
}
@@ -9357,7 +9365,7 @@ move2add_note_store (dst, set, data)
reg_set_luid[regno] = move2add_last_label_luid + 1;
reg_mode[regno] = mode;
return;
-
+
default:
invalidate:
/* Invalidate the contents of the register. */
@@ -9443,7 +9451,7 @@ copy_eh_notes (insn, x)
for (; x != 0; x = NEXT_INSN (x))
{
if (may_trap_p (PATTERN (x)))
- REG_NOTES (x)
+ REG_NOTES (x)
= gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0),
REG_NOTES (x));
}
@@ -9454,20 +9462,19 @@ copy_eh_notes (insn, x)
abnormal calls moving basic block end, but in fact it wants to emit
them on the edge. Looks for abnormal call edges, find backward the
proper call and fix the damage.
-
+
Similar handle instructions throwing exceptions internally. */
void
fixup_abnormal_edges ()
{
- int i;
bool inserted = false;
+ basic_block bb;
- for (i = 0; i < n_basic_blocks; i++)
+ FOR_EACH_BB (bb)
{
- basic_block bb = BASIC_BLOCK (i);
edge e;
- /* Look for cases we are interested in - an calls or instructions causing
+ /* Look for cases we are interested in - calls or instructions causing
exceptions. */
for (e = bb->succ; e; e = e->succ_next)
{
@@ -9500,19 +9507,22 @@ fixup_abnormal_edges ()
next = NEXT_INSN (insn);
if (INSN_P (insn))
{
- rtx seq;
-
delete_insn (insn);
- /* We're not deleting it, we're moving it. */
- INSN_DELETED_P (insn) = 0;
+ /* Sometimes there's still the return value USE.
+ If it's placed after a trapping call (i.e. that
+ call is the last insn anyway), we have no fallthru
+ edge. Simply delete this use and don't try to insert
+ on the non-existant edge. */
+ if (GET_CODE (PATTERN (insn)) != USE)
+ {
+ /* We're not deleting it, we're moving it. */
+ INSN_DELETED_P (insn) = 0;
+ PREV_INSN (insn) = NULL_RTX;
+ NEXT_INSN (insn) = NULL_RTX;
- /* Emit a sequence, rather than scarfing the pattern, so
- that we don't lose REG_NOTES etc. */
- /* ??? Could copy the test from gen_sequence, but don't
- think it's worth the bother. */
- seq = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (1, insn));
- insert_insn_on_edge (seq, e);
+ insert_insn_on_edge (insn, e);
+ }
}
insn = next;
}
OpenPOWER on IntegriCloud