OSDN Git Service

* version.c: Bump for new snapshot.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 25 Aug 1997 15:00:44 +0000 (15:00 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 25 Aug 1997 15:00:44 +0000 (15:00 +0000)
        * 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@14915 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/pa/pa.c
gcc/config/pa/pa.h
gcc/fold-const.c
gcc/local-alloc.c
gcc/tm.texi
gcc/version.c

index b2cf836..3166926 100644 (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.
index 774a288..b809f4c 100644 (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,
index ec73235..79bbac3 100644 (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))
+
 \f
 /* Stack layout; function entry, exit and calling.  */
 
index b146e8b..10b13f3 100644 (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;
+    }
+}
+\f
index 4466169..677801e 100644 (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;
 
index 7f66487..d5e4c9f 100644 (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
index eec90a8..ae1e415 100644 (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)";