summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cc/cc_int/reload1.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cc/cc_int/reload1.c')
-rw-r--r--gnu/usr.bin/cc/cc_int/reload1.c312
1 files changed, 142 insertions, 170 deletions
diff --git a/gnu/usr.bin/cc/cc_int/reload1.c b/gnu/usr.bin/cc/cc_int/reload1.c
index e46d764..d6dadf2 100644
--- a/gnu/usr.bin/cc/cc_int/reload1.c
+++ b/gnu/usr.bin/cc/cc_int/reload1.c
@@ -327,7 +327,7 @@ struct hard_reg_n_uses { int regno; int uses; };
static int possible_group_p PROTO((int, int *));
static void count_possible_groups PROTO((int *, enum machine_mode *,
- int *));
+ int *, int));
static int modes_equiv_for_class_p PROTO((enum machine_mode,
enum machine_mode,
enum reg_class));
@@ -1153,7 +1153,8 @@ reload (first, global, dumpfile)
if (other_mode != VOIDmode && other_mode != allocate_mode
&& ! modes_equiv_for_class_p (allocate_mode,
other_mode, class))
- abort ();
+ fatal_insn ("Two dissimilar machine modes both need groups of consecutive regs of the same class",
+ insn);
}
else if (size == 1)
{
@@ -1349,19 +1350,14 @@ reload (first, global, dumpfile)
}
/* Now count extra regs if there might be a conflict with
- the return value register.
+ the return value register. */
- ??? This is not quite correct because we don't properly
- handle the case of groups, but if we end up doing
- something wrong, it either will end up not mattering or
- we will abort elsewhere. */
-
for (r = regno; r < regno + nregs; r++)
if (spill_reg_order[r] >= 0)
for (i = 0; i < N_REG_CLASSES; i++)
if (TEST_HARD_REG_BIT (reg_class_contents[i], r))
{
- if (basic_needs[i] > 0 || basic_groups[i] > 0)
+ if (basic_needs[i] > 0)
{
enum reg_class *p;
@@ -1370,6 +1366,15 @@ reload (first, global, dumpfile)
while (*p != LIM_REG_CLASSES)
insn_needs.other.regs[0][(int) *p++]++;
}
+ if (basic_groups[i] > 0)
+ {
+ enum reg_class *p;
+
+ insn_needs.other.groups[i]++;
+ p = reg_class_superclasses[i];
+ while (*p != LIM_REG_CLASSES)
+ insn_needs.other.groups[(int) *p++]++;
+ }
}
}
#endif /* SMALL_REGISTER_CLASSES */
@@ -1603,7 +1608,8 @@ reload (first, global, dumpfile)
/* If any single spilled regs happen to form groups,
count them now. Maybe we don't really need
to spill another group. */
- count_possible_groups (group_size, group_mode, max_groups);
+ count_possible_groups (group_size, group_mode, max_groups,
+ class);
if (max_groups[class] <= 0)
break;
@@ -2063,68 +2069,65 @@ possible_group_p (regno, max_groups)
return 0;
}
-/* Count any groups that can be formed from the registers recently spilled.
- This is done class by class, in order of ascending class number. */
+/* Count any groups of CLASS that can be formed from the registers recently
+ spilled. */
static void
-count_possible_groups (group_size, group_mode, max_groups)
+count_possible_groups (group_size, group_mode, max_groups, class)
int *group_size;
enum machine_mode *group_mode;
int *max_groups;
+ int class;
{
- int i;
+ HARD_REG_SET new;
+ int i, j;
+
/* Now find all consecutive groups of spilled registers
and mark each group off against the need for such groups.
But don't count them against ordinary need, yet. */
- for (i = 0; i < N_REG_CLASSES; i++)
- if (group_size[i] > 1)
+ if (group_size[class] == 0)
+ return;
+
+ CLEAR_HARD_REG_SET (new);
+
+ /* Make a mask of all the regs that are spill regs in class I. */
+ for (i = 0; i < n_spills; i++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[class], spill_regs[i])
+ && ! TEST_HARD_REG_BIT (counted_for_groups, spill_regs[i])
+ && ! TEST_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]))
+ SET_HARD_REG_BIT (new, spill_regs[i]);
+
+ /* Find each consecutive group of them. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER && max_groups[class] > 0; i++)
+ if (TEST_HARD_REG_BIT (new, i)
+ && i + group_size[class] <= FIRST_PSEUDO_REGISTER
+ && HARD_REGNO_MODE_OK (i, group_mode[class]))
{
- HARD_REG_SET new;
- int j;
-
- CLEAR_HARD_REG_SET (new);
-
- /* Make a mask of all the regs that are spill regs in class I. */
- for (j = 0; j < n_spills; j++)
- if (TEST_HARD_REG_BIT (reg_class_contents[i], spill_regs[j])
- && ! TEST_HARD_REG_BIT (counted_for_groups, spill_regs[j])
- && ! TEST_HARD_REG_BIT (counted_for_nongroups,
- spill_regs[j]))
- SET_HARD_REG_BIT (new, spill_regs[j]);
-
- /* Find each consecutive group of them. */
- for (j = 0; j < FIRST_PSEUDO_REGISTER && max_groups[i] > 0; j++)
- if (TEST_HARD_REG_BIT (new, j)
- && j + group_size[i] <= FIRST_PSEUDO_REGISTER
- /* Next line in case group-mode for this class
- demands an even-odd pair. */
- && HARD_REGNO_MODE_OK (j, group_mode[i]))
- {
- int k;
- for (k = 1; k < group_size[i]; k++)
- if (! TEST_HARD_REG_BIT (new, j + k))
- break;
- if (k == group_size[i])
- {
- /* We found a group. Mark it off against this class's
- need for groups, and against each superclass too. */
- register enum reg_class *p;
- max_groups[i]--;
- p = reg_class_superclasses[i];
- while (*p != LIM_REG_CLASSES)
- max_groups[(int) *p++]--;
- /* Don't count these registers again. */
- for (k = 0; k < group_size[i]; k++)
- SET_HARD_REG_BIT (counted_for_groups, j + k);
- }
- /* Skip to the last reg in this group. When j is incremented
- above, it will then point to the first reg of the next
- possible group. */
- j += k - 1;
- }
- }
+ for (j = 1; j < group_size[class]; j++)
+ if (! TEST_HARD_REG_BIT (new, i + j))
+ break;
+
+ if (j == group_size[class])
+ {
+ /* We found a group. Mark it off against this class's need for
+ groups, and against each superclass too. */
+ register enum reg_class *p;
+
+ max_groups[class]--;
+ p = reg_class_superclasses[class];
+ while (*p != LIM_REG_CLASSES)
+ max_groups[(int) *p++]--;
+
+ /* Don't count these registers again. */
+ for (j = 0; j < group_size[class]; j++)
+ SET_HARD_REG_BIT (counted_for_groups, i + j);
+ }
+ /* Skip to the last reg in this group. When i is incremented above,
+ it will then point to the first reg of the next possible group. */
+ i += j - 1;
+ }
}
/* ALLOCATE_MODE is a register mode that needs to be reloaded. OTHER_MODE is
@@ -2165,7 +2168,7 @@ spill_failure (insn)
if (asm_noperands (PATTERN (insn)) >= 0)
error_for_asm (insn, "`asm' needs too many reloads");
else
- abort ();
+ fatal_insn ("Unable to find a register to spill.", insn);
}
/* Add a new register to the tables of available spill-registers
@@ -2886,11 +2889,20 @@ eliminate_regs (x, mem_mode, insn)
/* If we didn't change anything, we must retain the pseudo. */
if (new == reg_equiv_memory_loc[REGNO (SUBREG_REG (x))])
- new = XEXP (x, 0);
+ new = SUBREG_REG (x);
else
- /* Otherwise, ensure NEW isn't shared in case we have to reload
- it. */
- new = copy_rtx (new);
+ {
+ /* Otherwise, ensure NEW isn't shared in case we have to reload
+ it. */
+ new = copy_rtx (new);
+
+ /* In this case, we must show that the pseudo is used in this
+ insn so that delete_output_reload will do the right thing. */
+ if (insn != 0 && GET_CODE (insn) != EXPR_LIST
+ && GET_CODE (insn) != INSN_LIST)
+ emit_insn_before (gen_rtx (USE, VOIDmode, SUBREG_REG (x)),
+ insn);
+ }
}
else
new = eliminate_regs (SUBREG_REG (x), mem_mode, insn);
@@ -2907,7 +2919,11 @@ eliminate_regs (x, mem_mode, insn)
smaller. So leave the SUBREG then. */
&& ! (GET_CODE (SUBREG_REG (x)) == REG
&& GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
- && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD)
+ && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD
+ && (GET_MODE_SIZE (GET_MODE (x))
+ > GET_MODE_SIZE (GET_MODE (new)))
+ && INTEGRAL_MODE_P (GET_MODE (new))
+ && LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
#endif
)
{
@@ -3668,11 +3684,12 @@ order_regs_for_reload ()
}
/* Used in reload_as_needed to sort the spilled regs. */
+
static int
compare_spill_regs (r1, r2)
short *r1, *r2;
{
- return *r1 < *r2 ? -1: 1;
+ return *r1 - *r2;
}
/* Reload pseudo-registers into hard regs around each insn as needed.
@@ -3840,7 +3857,7 @@ reload_as_needed (first, live_known)
&& ! reload_optional[i]
&& (reload_in[i] != 0 || reload_out[i] != 0
|| reload_secondary_p[i] != 0))
- abort ();
+ fatal_insn ("Non-optional registers need a spill register", insn);
/* Now compute which reload regs to reload them into. Perhaps
reusing reload regs from previous insns, or else output
@@ -4836,7 +4853,7 @@ allocate_reload_reg (r, insn, last_reload, noerror)
failure:
if (asm_noperands (PATTERN (insn)) < 0)
/* It's the compiler's fault. */
- abort ();
+ fatal_insn ("Could not find a spill register", insn);
/* It's the user's fault; the operand's mode and constraint
don't match. Disable this reload so we don't crash in final. */
@@ -5628,7 +5645,9 @@ emit_reload_insns (insn)
{
register rtx old;
rtx oldequiv_reg = 0;
- rtx store_insn = 0;
+
+ if (reload_spill_index[j] >= 0)
+ new_spill_reg_store[reload_spill_index[j]] = 0;
old = reload_in[j];
if (old != 0 && ! reload_inherited[j]
@@ -6010,9 +6029,9 @@ emit_reload_insns (insn)
third_reload_reg)));
}
else
- gen_input_reload (second_reload_reg, oldequiv,
- reload_opnum[j],
- reload_when_needed[j]);
+ gen_reload (second_reload_reg, oldequiv,
+ reload_opnum[j],
+ reload_when_needed[j]);
oldequiv = second_reload_reg;
}
@@ -6021,8 +6040,8 @@ emit_reload_insns (insn)
#endif
if (! special && ! rtx_equal_p (reloadreg, oldequiv))
- gen_input_reload (reloadreg, oldequiv, reload_opnum[j],
- reload_when_needed[j]);
+ gen_reload (reloadreg, oldequiv, reload_opnum[j],
+ reload_when_needed[j]);
#if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P)
/* We may have to make a REG_DEAD note for the secondary reload
@@ -6246,7 +6265,7 @@ emit_reload_insns (insn)
/* VOIDmode should never happen for an output. */
if (asm_noperands (PATTERN (insn)) < 0)
/* It's the compiler's fault. */
- abort ();
+ fatal_insn ("VOIDmode on an output", insn);
error_for_asm (insn, "output operand is constant in `asm'");
/* Prevent crash--use something we know is valid. */
mode = word_mode;
@@ -6259,7 +6278,7 @@ emit_reload_insns (insn)
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
/* If we need two reload regs, set RELOADREG to the intermediate
- one, since it will be stored into OUT. We might need a secondary
+ one, since it will be stored into OLD. We might need a secondary
register only for an input reload, so check again here. */
if (reload_secondary_out_reload[j] >= 0)
@@ -6289,10 +6308,10 @@ emit_reload_insns (insn)
{
/* See if we need both a scratch and intermediate reload
register. */
+
int secondary_reload = reload_secondary_out_reload[j];
enum insn_code tertiary_icode
= reload_secondary_out_icode[secondary_reload];
- rtx pat;
if (GET_MODE (reloadreg) != mode)
reloadreg = gen_rtx (REG, mode, REGNO (reloadreg));
@@ -6301,44 +6320,24 @@ emit_reload_insns (insn)
{
rtx third_reloadreg
= reload_reg_rtx[reload_secondary_out_reload[secondary_reload]];
- pat = (GEN_FCN (tertiary_icode)
- (reloadreg, second_reloadreg, third_reloadreg));
- }
-#ifdef SECONDARY_MEMORY_NEEDED
- /* If we need a memory location to do the move, do it that way. */
- else if (GET_CODE (reloadreg) == REG
- && REGNO (reloadreg) < FIRST_PSEUDO_REGISTER
- && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (reloadreg)),
- REGNO_REG_CLASS (REGNO (second_reloadreg)),
- GET_MODE (second_reloadreg)))
- {
- /* Get the memory to use and rewrite both registers
- to its mode. */
- rtx loc
- = get_secondary_mem (reloadreg,
- GET_MODE (second_reloadreg),
- reload_opnum[j],
- reload_when_needed[j]);
- rtx tmp_reloadreg;
-
- if (GET_MODE (loc) != GET_MODE (second_reloadreg))
- second_reloadreg = gen_rtx (REG, GET_MODE (loc),
- REGNO (second_reloadreg));
-
- if (GET_MODE (loc) != GET_MODE (reloadreg))
- tmp_reloadreg = gen_rtx (REG, GET_MODE (loc),
- REGNO (reloadreg));
- else
- tmp_reloadreg = reloadreg;
-
- emit_move_insn (loc, second_reloadreg);
- pat = gen_move_insn (tmp_reloadreg, loc);
+
+ /* Copy primary reload reg to secondary reload reg.
+ (Note that these have been swapped above, then
+ secondary reload reg to OLD using our insn. */
+
+ gen_reload (reloadreg, second_reloadreg,
+ reload_opnum[j], reload_when_needed[j]);
+ emit_insn ((GEN_FCN (tertiary_icode)
+ (real_old, reloadreg, third_reloadreg)));
+ special = 1;
}
-#endif
+
else
- pat = gen_move_insn (reloadreg, second_reloadreg);
+ /* Copy between the reload regs here and then to
+ OUT later. */
- emit_insn (pat);
+ gen_reload (reloadreg, second_reloadreg,
+ reload_opnum[j], reload_when_needed[j]);
}
}
}
@@ -6346,34 +6345,8 @@ emit_reload_insns (insn)
/* Output the last reload insn. */
if (! special)
- {
-#ifdef SECONDARY_MEMORY_NEEDED
- /* If we need a memory location to do the move, do it that way. */
- if (GET_CODE (old) == REG && REGNO (old) < FIRST_PSEUDO_REGISTER
- && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (old)),
- REGNO_REG_CLASS (REGNO (reloadreg)),
- GET_MODE (reloadreg)))
- {
- /* Get the memory to use and rewrite both registers to
- its mode. */
- rtx loc = get_secondary_mem (old, GET_MODE (reloadreg),
- reload_opnum[j],
- reload_when_needed[j]);
-
- if (GET_MODE (loc) != GET_MODE (reloadreg))
- reloadreg = gen_rtx (REG, GET_MODE (loc),
- REGNO (reloadreg));
-
- if (GET_MODE (loc) != GET_MODE (old))
- old = gen_rtx (REG, GET_MODE (loc), REGNO (old));
-
- emit_insn (gen_move_insn (loc, reloadreg));
- emit_insn (gen_move_insn (old, loc));
- }
- else
-#endif
- emit_insn (gen_move_insn (old, reloadreg));
- }
+ gen_reload (old, reloadreg, reload_opnum[j],
+ reload_when_needed[j]);
#ifdef PRESERVE_DEATH_INFO_REGNO_P
/* If final will look at death notes for this reg,
@@ -6408,17 +6381,14 @@ emit_reload_insns (insn)
reg_has_output_reload will make this do nothing. */
note_stores (PATTERN (p), forget_old_reloads_1);
- if (reg_mentioned_p (reload_reg_rtx[j], PATTERN (p)))
- store_insn = p;
+ if (reg_mentioned_p (reload_reg_rtx[j], PATTERN (p))
+ && reload_spill_index[j] >= 0)
+ new_spill_reg_store[reload_spill_index[j]] = p;
}
output_reload_insns[reload_opnum[j]] = get_insns ();
end_sequence ();
-
}
-
- if (reload_spill_index[j] >= 0)
- new_spill_reg_store[reload_spill_index[j]] = store_insn;
}
/* Now write all the insns we made for reloads in the order expected by
@@ -6640,14 +6610,15 @@ emit_reload_insns (insn)
}
}
-/* Emit code to perform an input reload of IN to RELOADREG. IN is from
- operand OPNUM with reload type TYPE.
+/* Emit code to perform a reload from IN (which may be a reload register) to
+ OUT (which may also be a reload register). IN or OUT is from operand
+ OPNUM with reload type TYPE.
Returns first insn emitted. */
rtx
-gen_input_reload (reloadreg, in, opnum, type)
- rtx reloadreg;
+gen_reload (out, in, opnum, type)
+ rtx out;
rtx in;
int opnum;
enum reload_type type;
@@ -6714,13 +6685,13 @@ gen_input_reload (reloadreg, in, opnum, type)
it will be A = A + B as constrain_operands expects. */
if (GET_CODE (XEXP (in, 1)) == REG
- && REGNO (reloadreg) == REGNO (XEXP (in, 1)))
+ && REGNO (out) == REGNO (XEXP (in, 1)))
tem = op0, op0 = op1, op1 = tem;
if (op0 != XEXP (in, 0) || op1 != XEXP (in, 1))
in = gen_rtx (PLUS, GET_MODE (in), op0, op1);
- insn = emit_insn (gen_rtx (SET, VOIDmode, reloadreg, in));
+ insn = emit_insn (gen_rtx (SET, VOIDmode, out, in));
code = recog_memoized (insn);
if (code >= 0)
@@ -6749,16 +6720,16 @@ gen_input_reload (reloadreg, in, opnum, type)
&& REGNO (op1) >= FIRST_PSEUDO_REGISTER))
tem = op0, op0 = op1, op1 = tem;
- emit_insn (gen_move_insn (reloadreg, op0));
+ emit_insn (gen_move_insn (out, op0));
- /* If OP0 and OP1 are the same, we can use RELOADREG for OP1.
+ /* If OP0 and OP1 are the same, we can use OUT for OP1.
This fixes a problem on the 32K where the stack pointer cannot
be used as an operand of an add insn. */
if (rtx_equal_p (op0, op1))
- op1 = reloadreg;
+ op1 = out;
- insn = emit_insn (gen_add2_insn (reloadreg, op1));
+ insn = emit_insn (gen_add2_insn (out, op1));
/* If that failed, copy the address register to the reload register.
Then add the constant to the reload register. */
@@ -6777,43 +6748,44 @@ gen_input_reload (reloadreg, in, opnum, type)
delete_insns_since (last);
- emit_insn (gen_move_insn (reloadreg, op1));
- emit_insn (gen_add2_insn (reloadreg, op0));
+ emit_insn (gen_move_insn (out, op1));
+ emit_insn (gen_add2_insn (out, op0));
}
#ifdef SECONDARY_MEMORY_NEEDED
/* If we need a memory location to do the move, do it that way. */
else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
+ && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
- REGNO_REG_CLASS (REGNO (reloadreg)),
- GET_MODE (reloadreg)))
+ REGNO_REG_CLASS (REGNO (out)),
+ GET_MODE (out)))
{
/* Get the memory to use and rewrite both registers to its mode. */
- rtx loc = get_secondary_mem (in, GET_MODE (reloadreg), opnum, type);
+ rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
- if (GET_MODE (loc) != GET_MODE (reloadreg))
- reloadreg = gen_rtx (REG, GET_MODE (loc), REGNO (reloadreg));
+ if (GET_MODE (loc) != GET_MODE (out))
+ out = gen_rtx (REG, GET_MODE (loc), REGNO (out));
if (GET_MODE (loc) != GET_MODE (in))
in = gen_rtx (REG, GET_MODE (loc), REGNO (in));
emit_insn (gen_move_insn (loc, in));
- emit_insn (gen_move_insn (reloadreg, loc));
+ emit_insn (gen_move_insn (out, loc));
}
#endif
/* If IN is a simple operand, use gen_move_insn. */
else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG)
- emit_insn (gen_move_insn (reloadreg, in));
+ emit_insn (gen_move_insn (out, in));
#ifdef HAVE_reload_load_address
else if (HAVE_reload_load_address)
- emit_insn (gen_reload_load_address (reloadreg, in));
+ emit_insn (gen_reload_load_address (out, in));
#endif
- /* Otherwise, just write (set REGLOADREG IN) and hope for the best. */
+ /* Otherwise, just write (set OUT IN) and hope for the best. */
else
- emit_insn (gen_rtx (SET, VOIDmode, reloadreg, in));
+ emit_insn (gen_rtx (SET, VOIDmode, out, in));
/* Return the first insn emitted.
We can not just return get_last_insn, because there may have
@@ -6960,7 +6932,7 @@ inc_for_reload (reloadreg, value, inc_amount)
emit_insn (gen_move_insn (reloadreg, incloc));
/* See if we can directly increment INCLOC. Use a method similar to that
- in gen_input_reload. */
+ in gen_reload. */
last = get_last_insn ();
add_insn = emit_insn (gen_rtx (SET, VOIDmode, incloc,
OpenPOWER on IntegriCloud