From 39dfb55a01f2182839d6537fbfc56361f9d1e008 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Mon, 25 Aug 1997 09:00:44 -0600 Subject: [PATCH] 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 --- gcc/ChangeLog | 19 ++++++++ gcc/config/pa/pa.c | 21 +++++++++ gcc/config/pa/pa.h | 14 ++++++ gcc/fold-const.c | 113 +++++++++++++++++++++++++++++++++++++++++++++ gcc/local-alloc.c | 16 +++++++ gcc/tm.texi | 10 ++++ gcc/version.c | 2 +- 7 files changed, 194 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b2cf836316c..31669268382 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 774a288135f..b809f4c8dbf 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -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, diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h index ec7323564df..79bbac3d669 100644 --- a/gcc/config/pa/pa.h +++ b/gcc/config/pa/pa.h @@ -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. */ diff --git a/gcc/fold-const.c b/gcc/fold-const.c index b146e8b1fac..10b13f33f7c 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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; + } +} + diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c index 44661695b12..677801e8696 100644 --- a/gcc/local-alloc.c +++ b/gcc/local-alloc.c @@ -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; diff --git a/gcc/tm.texi b/gcc/tm.texi index 7f66487d5d4..d5e4c9fffa4 100644 --- a/gcc/tm.texi +++ b/gcc/tm.texi @@ -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 diff --git a/gcc/version.c b/gcc/version.c index eec90a8f053..ae1e4155d2f 100644 --- a/gcc/version.c +++ b/gcc/version.c @@ -1 +1 @@ -char *version_string = "egcs-2.90.01 970821 (gcc2-970802 experimental)"; +char *version_string = "egcs-2.90.02 970825 (gcc2-970802 experimental)"; -- 2.30.2