*** empty log message ***

From-SVN: r1296
This commit is contained in:
Richard Kenner 1992-06-26 07:06:07 -04:00
parent 3a6e78aded
commit 42495ca044
5 changed files with 198 additions and 63 deletions

View File

@ -1471,17 +1471,31 @@ try_combine (i3, i2, i1)
&& asm_noperands (newpat) < 0)
{
rtx m_split, *split;
rtx ni2dest = i2dest;
/* See if the MD file can split NEWPAT. If it can't, see if letting it
use I2DEST as a scratch register will help. */
use I2DEST as a scratch register will help. In the latter case,
convert I2DEST to the mode of the source of NEWPAT if we can. */
m_split = split_insns (newpat, i3);
if (m_split == 0)
m_split = split_insns (gen_rtx (PARALLEL, VOIDmode,
gen_rtvec (2, newpat,
gen_rtx (CLOBBER, VOIDmode,
i2dest))),
i3);
{
/* If I2DEST is a hard register or the only use of a pseudo,
we can change its mode. */
if (GET_MODE (SET_DEST (newpat)) != GET_MODE (i2dest)
&& (REGNO (i2dest) < FIRST_PSEUDO_REGISTER
|| (reg_n_sets[REGNO (i2dest)] == 1 && ! added_sets_2
&& ! REG_USERVAR_P (i2dest))))
ni2dest = gen_rtx (REG, GET_MODE (SET_DEST (newpat)),
REGNO (i2dest));
m_split = split_insns (gen_rtx (PARALLEL, VOIDmode,
gen_rtvec (2, newpat,
gen_rtx (CLOBBER,
VOIDmode,
ni2dest))),
i3);
}
if (m_split && GET_CODE (m_split) == SEQUENCE
&& XVECLEN (m_split, 0) == 2
@ -1492,6 +1506,13 @@ try_combine (i3, i2, i1)
newi2pat = PATTERN (XVECEXP (m_split, 0, 0));
newpat = PATTERN (XVECEXP (m_split, 0, 1));
/* In case we changed the mode of I2DEST, replace it in the
pseudo-register table here. We can't do it above in case this
code doesn't get executed and we do a split the other way. */
if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest);
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
if (i2_code_number >= 0)
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
@ -2945,6 +2966,18 @@ subst (x, from, to, in_dest, unique_copy)
- INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
goto restart;
}
/* If we are adding two things that have no bits in common, convert
the addition into an IOR. This will often be further simplified,
for example in cases like ((a & 1) + (a & 2)), which can
become a & 3. */
if ((significant_bits (XEXP (x, 0), mode)
& significant_bits (XEXP (x, 1), mode)) == 0)
{
x = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
goto restart;
}
break;
case MULT:
@ -4194,8 +4227,8 @@ make_extraction (mode, inner, pos, pos_rtx, len,
We try, as much as possible, to re-use rtl expressions to save memory.
IN_CODE says what kind of expression we are processing. Normally, it is
SET. In a memory address (inside a MEM or PLUS, the latter being a
kludge), it is MEM. When processing the arguments of a comparison
SET. In a memory address (inside a MEM, PLUS or minus, the latter two
being kludges), it is MEM. When processing the arguments of a comparison
or a COMPARE against zero, it is COMPARE. */
static rtx
@ -4215,7 +4248,7 @@ make_compound_operation (x, in_code)
address, we stay there. If we have a comparison, set to COMPARE,
but once inside, go back to our default of SET. */
next_code = (code == MEM || code == PLUS ? MEM
next_code = (code == MEM || code == PLUS || code == MINUS ? MEM
: ((code == COMPARE || GET_RTX_CLASS (code) == '<')
&& XEXP (x, 1) == const0_rtx) ? COMPARE
: in_code == COMPARE ? SET : in_code);

169
gcc/cse.c
View File

@ -2451,8 +2451,9 @@ find_best_addr (insn, loc)
&& validate_change (insn, loc, fold_rtx (addr, insn), 0))
addr = *loc;
/* If this address is not in the hash table, we can't do any better.
Also, ignore if volatile. */
/* If this address is not in the hash table, we can't look for equivalences
of the whole address. Also, ignore if volatile. */
do_not_record = 0;
hash_code = HASH (addr, Pmode);
addr_volatile = do_not_record;
@ -2465,56 +2466,138 @@ find_best_addr (insn, loc)
elt = lookup (addr, hash_code, Pmode);
if (elt == 0)
return;
#ifndef ADDRESS_COST
our_cost = elt->cost;
/* Find the lowest cost below ours that works. */
for (elt = elt->first_same_value; elt; elt = elt->next_same_value)
if (elt->cost < our_cost
&& (GET_CODE (elt->exp) == REG || exp_equiv_p (elt->exp, elt->exp, 1, 0))
&& validate_change (insn, loc, canon_reg (copy_rtx (elt->exp), 0), 0))
return;
if (elt)
{
our_cost = elt->cost;
/* Find the lowest cost below ours that works. */
for (elt = elt->first_same_value; elt; elt = elt->next_same_value)
if (elt->cost < our_cost
&& (GET_CODE (elt->exp) == REG
|| exp_equiv_p (elt->exp, elt->exp, 1, 0))
&& validate_change (insn, loc,
canon_reg (copy_rtx (elt->exp), 0), 0))
return;
}
#else
/* We need to find the best (under the criteria documented above) entry in
the class that is valid. We use the `flag' field to indicate choices
that were invalid and iterate until we can't find a better one that
hasn't already been tried. */
for (p = elt->first_same_value; p; p = p->next_same_value)
p->flag = 0;
while (found_better)
if (elt)
{
int best_addr_cost = ADDRESS_COST (*loc);
int best_rtx_cost = (elt->cost + 1) >> 1;
struct table_elt *best_elt = elt;
/* We need to find the best (under the criteria documented above) entry
in the class that is valid. We use the `flag' field to indicate
choices that were invalid and iterate until we can't find a better
one that hasn't already been tried. */
found_better = 0;
for (p = elt->first_same_value; p; p = p->next_same_value)
if (! p->flag
&& (GET_CODE (p->exp) == REG || exp_equiv_p (p->exp, p->exp, 1, 0))
&& (ADDRESS_COST (p->exp) < best_addr_cost
|| (ADDRESS_COST (p->exp) == best_addr_cost
&& (p->cost + 1) >> 1 > best_rtx_cost)))
{
found_better = 1;
best_addr_cost = ADDRESS_COST (p->exp);
best_rtx_cost = (p->cost + 1) >> 1;
best_elt = p;
}
p->flag = 0;
if (found_better)
while (found_better)
{
if (validate_change (insn, loc,
canon_reg (copy_rtx (best_elt->exp), 0), 0))
return;
else
best_elt->flag = 1;
int best_addr_cost = ADDRESS_COST (*loc);
int best_rtx_cost = (elt->cost + 1) >> 1;
struct table_elt *best_elt = elt;
found_better = 0;
for (p = elt->first_same_value; p; p = p->next_same_value)
if (! p->flag
&& (GET_CODE (p->exp) == REG
|| exp_equiv_p (p->exp, p->exp, 1, 0))
&& (ADDRESS_COST (p->exp) < best_addr_cost
|| (ADDRESS_COST (p->exp) == best_addr_cost
&& (p->cost + 1) >> 1 > best_rtx_cost)))
{
found_better = 1;
best_addr_cost = ADDRESS_COST (p->exp);
best_rtx_cost = (p->cost + 1) >> 1;
best_elt = p;
}
if (found_better)
{
if (validate_change (insn, loc,
canon_reg (copy_rtx (best_elt->exp), 0), 0))
return;
else
best_elt->flag = 1;
}
}
}
/* If the address is a binary operation with the first operand a register
and the second a constant, do the same as above, but looking for
equivalences of the register. Then try to simplify before checking for
the best address to use. This catches a few cases: First is when we
have REG+const and the register is another REG+const. We can often merge
the constants and eliminate one insn and one register. It may also be
that a machine has a cheap REG+REG+const. Finally, this improves the
code on the Alpha for unaligned byte stores. */
if (flag_expensive_optimizations
&& (GET_RTX_CLASS (GET_CODE (*loc)) == '2'
|| GET_RTX_CLASS (GET_CODE (*loc)) == 'c')
&& GET_CODE (XEXP (*loc, 0)) == REG
&& GET_CODE (XEXP (*loc, 1)) == CONST_INT)
{
rtx c = XEXP (*loc, 1);
do_not_record = 0;
hash_code = HASH (XEXP (*loc, 0), Pmode);
do_not_record = save_do_not_record;
hash_arg_in_memory = save_hash_arg_in_memory;
hash_arg_in_struct = save_hash_arg_in_struct;
elt = lookup (XEXP (*loc, 0), hash_code, Pmode);
if (elt == 0)
return;
/* We need to find the best (under the criteria documented above) entry
in the class that is valid. We use the `flag' field to indicate
choices that were invalid and iterate until we can't find a better
one that hasn't already been tried. */
for (p = elt->first_same_value; p; p = p->next_same_value)
p->flag = 0;
while (found_better)
{
int best_addr_cost = ADDRESS_COST (*loc);
int best_rtx_cost = (COST (*loc) + 1) >> 1;
struct table_elt *best_elt = elt;
rtx best_rtx = *loc;
found_better = 0;
for (p = elt->first_same_value; p; p = p->next_same_value)
if (! p->flag
&& (GET_CODE (p->exp) == REG
|| exp_equiv_p (p->exp, p->exp, 1, 0)))
{
rtx new = simplify_binary_operation (GET_CODE (*loc), Pmode,
p->exp, c);
if (new == 0)
new = gen_rtx (GET_CODE (*loc), Pmode, p->exp, c);
if ((ADDRESS_COST (new) < best_addr_cost
|| (ADDRESS_COST (new) == best_addr_cost
&& (COST (new) + 1) >> 1 > best_rtx_cost)))
{
found_better = 1;
best_addr_cost = ADDRESS_COST (new);
best_rtx_cost = (COST (new) + 1) >> 1;
best_elt = p;
best_rtx = new;
}
}
if (found_better)
{
if (validate_change (insn, loc,
canon_reg (copy_rtx (best_rtx), 0), 0))
return;
else
best_elt->flag = 1;
}
}
}
#endif

View File

@ -2134,7 +2134,6 @@ optimize_bit_field_compare (code, compare_type, lhs, rhs)
#if BYTES_BIG_ENDIAN
lbitpos = lnbitsize - lbitsize - lbitpos;
rbitpos = rnbitsize - rbitsize - rbitpos;
#endif
/* Make the mask to be used against the extracted field. */

View File

@ -846,6 +846,7 @@ gen_split (split)
mybzero (d->strict_low, sizeof strict_low);
d->n_dups = 0;
d->n_alternatives = 0;
d->template = 0;
d->outfun = 0;
d->n_alternatives = 0;

View File

@ -2546,16 +2546,35 @@ expand_end_bindings (vars, mark_ends, dont_jump_in)
#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
if (fixed_regs[ARG_POINTER_REGNUM])
{
/* Now restore our arg pointer from the address at which it was saved
in our stack frame.
If there hasn't be space allocated for it yet, make some now. */
if (arg_pointer_save_area == 0)
arg_pointer_save_area
= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
emit_move_insn (virtual_incoming_args_rtx,
/* We need a pseudo here,
or else instantiate_virtual_regs_1 complains. */
copy_to_reg (arg_pointer_save_area));
#ifdef ELIMINABLE_REGS
/* If the argument pointer can be eliminated in favor of the
frame pointer, we don't need to restore it. We assume here
that if such an elimination is present, it can always be used.
This is the case on all known machines; if we don't make this
assumption, we do unnecessary saving on many machines. */
static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS;
int i;
for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++)
if (elim_regs[i].from == ARG_POINTER_REGNUM
&& elim_regs[i].to == FRAME_POINTER_REGNUM)
break;
if (i == sizeof elim_regs / sizeof elim_regs [0])
#endif
{
/* Now restore our arg pointer from the address at which it
was saved in our stack frame.
If there hasn't be space allocated for it yet, make
some now. */
if (arg_pointer_save_area == 0)
arg_pointer_save_area
= assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0);
emit_move_insn (virtual_incoming_args_rtx,
/* We need a pseudo here, or else
instantiate_virtual_regs_1 complains. */
copy_to_reg (arg_pointer_save_area));
}
}
#endif