version.c: Bump for new snapshot.

* version.c: Bump for new snapshot.

        * local-alloc.c (update_equiv_regs): All the target to reject
        promotion of some REG_EQUAL to REG_EQUIV notes.
        * pa.h (DONT_RECORD_EQUIVALENCE): Define.
Fixes some c-torture failures, also improves generated code.

        * pa.c (secondary_reload_class): (mem (mem ... )) does not need
        secondary reloads.
Fixes 094.fpppp/twldrv.f abort.

        * pa.c (hppa_builtin_saveregs): Emit a blockage insn after the
        store of the argument registers.
Fixes c-torture failure.

        * fold-const.c (multiple_of_p): New function.
        (fold): Turn some cases of *_DIV_EXPR into EXACT_DIV_EXPR.
One of the performance patches from the g77 folks.

From-SVN: r14915
This commit is contained in:
Jeff Law 1997-08-25 09:00:44 -06:00
parent d78778ebf9
commit 39dfb55a01
7 changed files with 194 additions and 1 deletions

View file

@ -1,3 +1,22 @@
Mon Aug 25 08:55:00 1997 Jeffrey A Law (law@cygnus.com)
* version.c: Bump for new snapshot.
* local-alloc.c (update_equiv_regs): All the target to reject
promotion of some REG_EQUAL to REG_EQUIV notes.
* pa.h (DONT_RECORD_EQUIVALENCE): Define.
* pa.c (secondary_reload_class): (mem (mem ... )) does not need
secondary reloads.
* pa.c (hppa_builtin_saveregs): Emit a blockage insn after the
store of the argument registers.
Mon Aug 25 08:39:02 1997 Craig Burley (burley@gnu.ai.mit.edu)
* fold-const.c (multiple_of_p): New function.
(fold): Turn some cases of *_DIV_EXPR into EXACT_DIV_EXPR.
Mon Aug 25 01:47:41 1997 Jeffrey A Law (law@cygnus.com)
* expr.h (insn_gen_function): Temporarily remove prototype.

View file

@ -4195,6 +4195,15 @@ secondary_reload_class (class, mode, in)
else
regno = -1;
/* If we have something like (mem (mem (...)), we can safely assume the
inner MEM will end up in a general register after reloading, so there's
no need for a secondary reload. */
if (GET_CODE (in) == MEM
&& GET_CODE (XEXP (in, 0)) == MEM)
return NO_REGS;
/* Handle out of range displacement for integer mode loads/stores of
FP registers. */
if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
&& GET_MODE_CLASS (mode) == MODE_INT
&& FP_REG_CLASS_P (class))
@ -4223,6 +4232,7 @@ secondary_reload_class (class, mode, in)
|| GET_CODE (XEXP (tmp, 0)) == LABEL_REF)
&& GET_CODE (XEXP (tmp, 1)) == CONST_INT);
break;
default:
is_symbolic = 0;
break;
@ -4291,6 +4301,17 @@ hppa_builtin_saveregs (arglist)
plus_constant (current_function_internal_arg_pointer, -16));
move_block_from_reg (23, dest, 4, 4 * UNITS_PER_WORD);
/* move_block_from_reg will emit code to store the argument registers
individually as scalar stores.
However, other insns may later load from the same addresses for
a struture load (passing a struct to a varargs routine).
The alias code assumes that such aliasing can never happen, so we
have to keep memory referencing insns from moving up beyond the
last argument register store. So we emit a blockage insn here. */
emit_insn (gen_blockage ());
if (flag_check_memory_usage)
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
dest, ptr_mode,

View file

@ -793,6 +793,20 @@ enum reg_class { NO_REGS, R1_REGS, GENERAL_REGS, FP_REGS, GENERAL_OR_FP_REGS,
#define CLASS_MAX_NREGS(CLASS, MODE) \
(!TARGET_SNAKE && (CLASS) == FP_REGS ? 1 : \
((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* We do not want to record equivalences for expressions which are
likely to cause a spill of %r1 if they are used by reload.
Nor do we want to record an equivalence of a constant expression
that the target can not handle appearing in an insn, but which
also must be accepted by LEGITIMATE_CONSTANT_P.
On the PA, these two goals are the same -- don't record any equivalences
for symbolic operands that are not read_only_operands. */
#define DONT_RECORD_EQUIVALENCE(NOTE) \
(symbolic_operand (XEXP (NOTE, 0), VOIDmode) \
&& !read_only_operand (XEXP (NOTE, 0), VOIDmode))
/* Stack layout; function entry, exit and calling. */

View file

@ -91,6 +91,7 @@ static tree fold_range_test PROTO((tree));
static tree unextend PROTO((tree, int, int, tree));
static tree fold_truthop PROTO((enum tree_code, tree, tree, tree));
static tree strip_compound_expr PROTO((tree, tree));
static int multiple_of_p PROTO((tree, tree, tree));
#ifndef BRANCH_COST
#define BRANCH_COST 1
@ -4548,6 +4549,17 @@ fold (expr)
if (integer_zerop (arg1))
return t;
/* If arg0 is a multiple of arg1, then rewrite to the fastest div
operation, EXACT_DIV_EXPR.
Note that only CEIL_DIV_EXPR is rewritten now, only because the
others seem to be faster in some cases. This is probably just
due to more work being done to optimize others in expmed.c than on
EXACT_DIV_EXPR. */
if (code == CEIL_DIV_EXPR
&& multiple_of_p (type, arg0, arg1))
return fold (build (EXACT_DIV_EXPR, type, arg0, arg1));
/* If we have ((a / C1) / C2) where both division are the same type, try
to simplify. First see if C1 * C2 overflows or not. */
if (TREE_CODE (arg0) == code && TREE_CODE (arg1) == INTEGER_CST
@ -5723,3 +5735,104 @@ fold (expr)
return t;
} /* switch (code) */
}
/* Determine if first argument is a multiple of second argument.
Return 0 if it is not, or is not easily determined to so be.
An example of the sort of thing we care about (at this point --
this routine could surely be made more general, and expanded
to do what the *_DIV_EXPR's fold() cases do now) is discovering
that
SAVE_EXPR (I) * SAVE_EXPR (J * 8)
is a multiple of
SAVE_EXPR (J * 8)
when we know that the two `SAVE_EXPR (J * 8)' nodes are the
same node (which means they will have the same value at run
time, even though we don't know when they'll be assigned).
This code also handles discovering that
SAVE_EXPR (I) * SAVE_EXPR (J * 8)
is a multiple of
8
(of course) so we don't have to worry about dealing with a
possible remainder.
Note that we _look_ inside a SAVE_EXPR only to determine
how it was calculated; it is not safe for fold() to do much
of anything else with the internals of a SAVE_EXPR, since
fold() cannot know when it will be evaluated at run time.
For example, the latter example above _cannot_ be implemented
as
SAVE_EXPR (I) * J
or any variant thereof, since the value of J at evaluation time
of the original SAVE_EXPR is not necessarily the same at the time
the new expression is evaluated. The only optimization of this
sort that would be valid is changing
SAVE_EXPR (I) * SAVE_EXPR (SAVE_EXPR (J) * 8)
divided by
8
to
SAVE_EXPR (I) * SAVE_EXPR (J)
(where the same SAVE_EXPR (J) is used in the original and the
transformed version). */
static int
multiple_of_p (type, top, bottom)
tree type;
tree top;
tree bottom;
{
if (operand_equal_p (top, bottom, 0))
return 1;
if (TREE_CODE (type) != INTEGER_TYPE)
return 0;
switch (TREE_CODE (top))
{
case MULT_EXPR:
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
|| multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
case PLUS_EXPR:
case MINUS_EXPR:
return (multiple_of_p (type, TREE_OPERAND (top, 0), bottom)
&& multiple_of_p (type, TREE_OPERAND (top, 1), bottom));
case NOP_EXPR:
/* Punt if conversion from non-integral or wider integral type. */
if ((TREE_CODE (TREE_TYPE (TREE_OPERAND (top, 0))) != INTEGER_TYPE)
|| (TYPE_PRECISION (type)
< TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (top, 0)))))
return 0;
/* Fall through. */
case SAVE_EXPR:
return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
case INTEGER_CST:
if ((TREE_CODE (bottom) != INTEGER_CST)
|| (tree_int_cst_sgn (top) < 0)
|| (tree_int_cst_sgn (bottom) < 0))
return 0;
return integer_zerop (const_binop (TRUNC_MOD_EXPR,
top, bottom, 0));
default:
return 0;
}
}

View file

@ -1048,6 +1048,22 @@ update_equiv_regs ()
note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
#ifdef DONT_RECORD_EQUIVALENCE
/* Allow the target to reject promotions of some REG_EQUAL notes to
REG_EQUIV notes.
In some cases this can improve register allocation if the existence
of the REG_EQUIV note is likely to increase the lifetime of a register
that is likely to be spilled.
It may also be necessary if the target can't handle certain constant
expressions appearing randomly in insns, but for whatever reason
those expressions must be considered legitimate constant expressions
to prevent them from being forced into memory. */
if (note && DONT_RECORD_EQUIVALENCE (note))
note = NULL;
#endif
/* Record this insn as initializing this register. */
reg_equiv_init_insn[regno] = insn;

View file

@ -4177,6 +4177,16 @@ an immediate operand on the target machine. You can assume that
@var{x} satisfies @code{CONSTANT_P}, so you need not check this. In fact,
@samp{1} is a suitable definition for this macro on machines where
anything @code{CONSTANT_P} is valid.@refill
@findex DONT_RECORD_EQUIVALENCE
@item DONT_RECORD_EQUIVALENCE (@var{note})
A C expression that is nonzero if the @code{REG_EQUAL} note @var{x} should not
be promoted to a @code{REG_EQUIV} note.
Define this macro if @var{note} refers to a constant that must be accepted
by @code{LEGITIMATE_CONSTANT_P}, but must not appear as an immediate operand.
Most machine descriptions do not need to define this macro.
@end table
@node Condition Code

View file

@ -1 +1 @@
char *version_string = "egcs-2.90.01 970821 (gcc2-970802 experimental)";
char *version_string = "egcs-2.90.02 970825 (gcc2-970802 experimental)";