alias.c (alias_invariant): New variable.
authorJohn Carr <jfc@mit.edu>
Sat, 25 Apr 1998 16:09:24 +0000 (16:09 +0000)
committerJohn Carr <jfc@gcc.gnu.org>
Sat, 25 Apr 1998 16:09:24 +0000 (16:09 +0000)
* alias.c (alias_invariant): New variable.
(record_base_value): New argument INVARIANT.
(memrefs_conflict_p): If a register has an entry in the alias_invariant
array, try substituting that value for the register.
* rtl.h: Declare record_base_value.
* loop.c, unroll.c: Update callers of record_base_value.
* alias.c (find_base_value, find_base_term): SIGN_EXTEND and
ZERO_EXTEND do not affect base values.

From-SVN: r19408

gcc/ChangeLog
gcc/alias.c
gcc/loop.c
gcc/rtl.h
gcc/unroll.c

index 118c16b07199caf186c1c94a0497eccd4076771d..f98100817f84e76d6b12134bbc175d5e9c5eda12 100644 (file)
@@ -1,3 +1,17 @@
+Sat Apr 25 17:55:54 1998  John Carr  <jfc@mit.edu>
+
+       * alias.c (alias_invariant): New variable.
+       (record_base_value): New argument INVARIANT.
+       (memrefs_conflict_p): If a register has an entry in the alias_invariant
+       array, try substituting that value for the register.
+
+       * rtl.h: Declare record_base_value.
+
+       * loop.c, unroll.c: Update callers of record_base_value.
+
+       * alias.c (find_base_value, find_base_term): SIGN_EXTEND and
+       ZERO_EXTEND do not affect base values.
+
 Fri Apr 24 15:57:02 1998  Jeffrey A Law  (law@cygnus.com)
 
        * dbxout.c (dbxout_type): Fix typo.
index bc0b49c2322900734ed7be7338b85957f486ddef..a9024b8c98f4ab9c2c2b1321d43526ece0f468bf 100644 (file)
@@ -68,6 +68,16 @@ unsigned int reg_base_value_size;    /* size of reg_base_value array */
 #define REG_BASE_VALUE(X) \
        (REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
 
+/* Vector of known invariant relationships between registers.  Set in
+   loop unrolling.  Indexed by register number, if nonzero the value
+   is an expression describing this register in terms of another.
+
+   The length of this array is REG_BASE_VALUE_SIZE.
+
+   Because this array contains only pseudo registers it has no effect
+   after reload.  */
+static rtx *alias_invariant;
+
 /* Vector indexed by N giving the initial (unchanging) value known
    for pseudo-register N.  */
 rtx *reg_known_value;
@@ -205,6 +215,8 @@ find_base_value (src)
        return find_base_value (XEXP (src, 0));
       return 0;
 
+    case ZERO_EXTEND:
+    case SIGN_EXTEND:  /* used for NT/Alpha pointers */
     case HIGH:
       return find_base_value (XEXP (src, 0));
 
@@ -295,16 +307,26 @@ record_set (dest, set)
 
 /* Called from loop optimization when a new pseudo-register is created.  */
 void
-record_base_value (regno, val)
+record_base_value (regno, val, invariant)
      int regno;
      rtx val;
+     int invariant;
 {
   if (regno >= reg_base_value_size)
     return;
+
+  /* If INVARIANT is true then this value also describes an invariant
+     relationship which can be used to deduce that two registers with
+     unknown values are different.  */
+  if (invariant && alias_invariant)
+    alias_invariant[regno] = val;
+
   if (GET_CODE (val) == REG)
     {
       if (REGNO (val) < reg_base_value_size)
-       reg_base_value[regno] = reg_base_value[REGNO (val)];
+       {
+         reg_base_value[regno] = reg_base_value[REGNO (val)];
+       }
       return;
     }
   reg_base_value[regno] = find_base_value (val);
@@ -397,6 +419,10 @@ rtx_equal_for_memref_p (x, y)
     return XEXP (x, 0) == XEXP (y, 0);
   if (code == SYMBOL_REF)
     return XSTR (x, 0) == XSTR (y, 0);
+  if (code == CONST_INT)
+    return INTVAL (x) == INTVAL (y);
+  if (code == ADDRESSOF)
+    return REGNO (XEXP (x, 0)) == REGNO (XEXP (y, 0)) && XINT (x, 1) == XINT (y, 1);
 
   /* For commutative operations, the RTX match if the operand match in any
      order.  Also handle the simple binary and unary cases without a loop.  */
@@ -412,25 +438,20 @@ rtx_equal_for_memref_p (x, y)
     return rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0));
 
   /* Compare the elements.  If any pair of corresponding elements
-     fail to match, return 0 for the whole things.  */
+     fail to match, return 0 for the whole things.
+
+     Limit cases to types which actually appear in addresses.  */
 
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       switch (fmt[i])
        {
-       case 'w':
-         if (XWINT (x, i) != XWINT (y, i))
-           return 0;
-         break;
-
-       case 'n':
        case 'i':
          if (XINT (x, i) != XINT (y, i))
            return 0;
          break;
 
-       case 'V':
        case 'E':
          /* Two vectors must have the same length.  */
          if (XVECLEN (x, i) != XVECLEN (y, i))
@@ -447,19 +468,6 @@ rtx_equal_for_memref_p (x, y)
            return 0;
          break;
 
-       case 'S':
-       case 's':
-         if (strcmp (XSTR (x, i), XSTR (y, i)))
-           return 0;
-         break;
-
-       case 'u':
-         /* These are just backpointers, so they don't matter.  */
-         break;
-
-       case '0':
-         break;
-
          /* It is believed that rtx's at this level will never
             contain anything but integers and other rtx's,
             except for within LABEL_REFs and SYMBOL_REFs.  */
@@ -513,9 +521,9 @@ find_base_term (x)
     case REG:
       return REG_BASE_VALUE (x);
 
+    case ZERO_EXTEND:
+    case SIGN_EXTEND:  /* Used for Alpha/NT pointers */
     case HIGH:
-      return find_base_term (XEXP (x, 0));
-
     case PRE_INC:
     case PRE_DEC:
     case POST_INC:
@@ -747,6 +755,25 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
          return memrefs_conflict_p (xsize, x0, ysize, y0, c);
        }
 
+      case REG:
+       /* Are these registers known not to be equal?  */
+       if (alias_invariant)
+         {
+           int r_x = REGNO (x), r_y = REGNO (y);
+           rtx i_x, i_y;       /* invariant relationships of X and Y */
+
+           i_x = r_x >= reg_base_value_size ? 0 : alias_invariant[r_x];
+           i_y = r_y >= reg_base_value_size ? 0 : alias_invariant[r_y];
+
+           if (i_x == 0 && i_y == 0)
+             break;
+
+           if (! memrefs_conflict_p (xsize, i_x ? i_x : x,
+                                     ysize, i_y ? i_y : y, c))
+             return 0;
+         }
+       break;
+
       default:
        break;
       }
@@ -1034,6 +1061,13 @@ init_alias_analysis ()
   new_reg_base_value = (rtx *)alloca (reg_base_value_size * sizeof (rtx));
   reg_seen = (char *)alloca (reg_base_value_size);
   bzero ((char *) reg_base_value, reg_base_value_size * sizeof (rtx));
+  if (! reload_completed && flag_unroll_loops)
+    {
+      alias_invariant = (rtx *)xrealloc (alias_invariant,
+                                        reg_base_value_size * sizeof (rtx));
+      bzero ((char *)alias_invariant, reg_base_value_size * sizeof (rtx));
+    }
+    
 
   /* The basic idea is that each pass through this loop will use the
      "constant" information from the previous pass to propagate alias
@@ -1203,4 +1237,9 @@ end_alias_analysis ()
   reg_known_value = 0;
   reg_base_value = 0;
   reg_base_value_size = 0;
+  if (alias_invariant)
+    {
+      free ((char *)alias_invariant);
+      alias_invariant = 0;
+    }
 }
index bcc7d2cc663eefad4803418e6896c0e3ed9eb2f9..6b66484647b160a66e4d59f713e957a6a16f48b5 100644 (file)
@@ -5986,7 +5986,7 @@ emit_iv_add_mult (b, m, a, reg, insert_before)
 
   emit_insn_before (seq, insert_before);
 
-  record_base_value (REGNO (reg), b);
+  record_base_value (REGNO (reg), b, 0);
 }
 \f
 /* Test whether A * B can be computed without
index c01770a90f3af24aa256a0e42d72dec95244f242..76b15654c807837392633e903196e96106dbeb99 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1402,4 +1402,6 @@ extern void init_alias_once               PROTO ((void));
 extern void init_alias_analysis                PROTO ((void));
 extern void end_alias_analysis         PROTO ((void));
 
+extern void record_base_value          PROTO ((int, rtx, int));
+
 #endif /* _RTL_H */
index c21e69f93f98c48211aed043ab93c37ae6ef368e..a6cd9bdd5290e3806b1ac844b22f0fb3890f47f7 100644 (file)
@@ -1054,7 +1054,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
                  {
                    map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
                    record_base_value (REGNO (map->reg_map[j]),
-                                      regno_reg_rtx[j]);
+                                      regno_reg_rtx[j], 0);
                  }
              /* The last copy needs the compare/branch insns at the end,
                 so reset copy_end here if the loop ends with a conditional
@@ -1216,7 +1216,7 @@ unroll_loop (loop_end, insn_count, loop_start, end_insert_before,
          {
            map->reg_map[j] = gen_reg_rtx (GET_MODE (regno_reg_rtx[j]));
            record_base_value (REGNO (map->reg_map[j]),
-                              regno_reg_rtx[j]);
+                              regno_reg_rtx[j], 0);
          }
 
       /* If loop starts with a branch to the test, then fix it so that
@@ -1861,7 +1861,12 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
                      tem = gen_reg_rtx (GET_MODE (giv_src_reg));
                      giv_dest_reg = tem;
                      map->reg_map[regno] = tem;
-                     record_base_value (REGNO (tem), giv_src_reg);
+                     record_base_value (REGNO (tem),
+                                        giv_inc == const0_rtx
+                                        ? giv_src_reg
+                                        : gen_rtx_PLUS (GET_MODE (giv_src_reg),
+                                                        giv_src_reg, giv_inc),
+                                        1);
                    }
                  else
                    map->reg_map[regno] = giv_src_reg;
@@ -2560,7 +2565,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
                {
                  rtx tem = gen_reg_rtx (bl->biv->mode);
 
-                 record_base_value (REGNO (tem), bl->biv->add_val);
+                 record_base_value (REGNO (tem), bl->biv->add_val, 0);
                  emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
                                    loop_start);
 
@@ -2617,7 +2622,7 @@ find_splittable_regs (unroll_type, loop_start, loop_end, end_insert_before,
                 this insn will always be executed, no matter how the loop
                 exits.  */
              rtx tem = gen_reg_rtx (bl->biv->mode);
-             record_base_value (REGNO (tem), bl->biv->add_val);
+             record_base_value (REGNO (tem), bl->biv->add_val, 0);
 
              emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
                                loop_start);
@@ -2799,7 +2804,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
            {
              rtx tem = gen_reg_rtx (bl->biv->mode);
 
-             record_base_value (REGNO (tem), bl->biv->add_val);
+             record_base_value (REGNO (tem), bl->biv->add_val, 0);
              emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
                                loop_start);
              biv_initial_value = tem;
@@ -2841,7 +2846,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
                      || GET_CODE (XEXP (value, 1)) != CONST_INT))
                {
                  rtx tem = gen_reg_rtx (v->mode);
-                 record_base_value (REGNO (tem), v->add_val);
+                 record_base_value (REGNO (tem), v->add_val, 0);
                  emit_iv_add_mult (bl->initial_value, v->mult_val,
                                    v->add_val, tem, loop_start);
                  value = tem;
@@ -2900,7 +2905,7 @@ find_splittable_givs (bl, unroll_type, loop_start, loop_end, increment,
                     Emit insn to initialize its value before loop start.  */
 
                  rtx tem = gen_reg_rtx (v->mode);
-                 record_base_value (REGNO (tem), v->add_val);
+                 record_base_value (REGNO (tem), v->add_val, 0);
                  v->unrolled = 1;
 
                  /* If the address giv has a constant in its new_reg value,
@@ -3216,7 +3221,7 @@ final_biv_value (bl, loop_start, loop_end)
             case it is needed later.  */
 
          tem = gen_reg_rtx (bl->biv->mode);
-         record_base_value (REGNO (tem), bl->biv->add_val);
+         record_base_value (REGNO (tem), bl->biv->add_val, 0);
          /* Make sure loop_end is not the last insn.  */
          if (NEXT_INSN (loop_end) == 0)
            emit_note_after (NOTE_INSN_DELETED, loop_end);
@@ -3315,7 +3320,7 @@ final_giv_value (v, loop_start, loop_end)
 
          /* Put the final biv value in tem.  */
          tem = gen_reg_rtx (bl->biv->mode);
-         record_base_value (REGNO (tem), bl->biv->add_val);
+         record_base_value (REGNO (tem), bl->biv->add_val, 0);
          emit_iv_add_mult (increment, GEN_INT (loop_n_iterations),
                            bl->initial_value, tem, insert_before);