+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.
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))
|| GET_CODE (XEXP (tmp, 0)) == LABEL_REF)
&& GET_CODE (XEXP (tmp, 1)) == CONST_INT);
break;
+
default:
is_symbolic = 0;
break;
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,
#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))
+
\f
/* Stack layout; function entry, exit and calling. */
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
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
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;
+ }
+}
+\f
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;
@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
-char *version_string = "egcs-2.90.01 970821 (gcc2-970802 experimental)";
+char *version_string = "egcs-2.90.02 970825 (gcc2-970802 experimental)";