OSDN Git Service

* optabs.h (OTI_flodiv, flodiv_optab): Kill.
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index a1f2e0b..a79589f 100644 (file)
@@ -87,7 +87,7 @@ typedef struct alias_set_entry
 
 static int rtx_equal_for_memref_p      PARAMS ((rtx, rtx));
 static rtx find_symbolic_term          PARAMS ((rtx));
-static rtx get_addr                    PARAMS ((rtx));
+rtx get_addr                           PARAMS ((rtx));
 static int memrefs_conflict_p          PARAMS ((int, rtx, int, rtx,
                                                 HOST_WIDE_INT));
 static void record_set                 PARAMS ((rtx, rtx, void *));
@@ -107,8 +107,6 @@ static int aliases_everything_p         PARAMS ((rtx));
 static int write_dependence_p           PARAMS ((rtx, rtx, int));
 static int nonlocal_mentioned_p         PARAMS ((rtx));
 
-static int loop_p                       PARAMS ((void));
-
 /* Set up all info needed to perform alias analysis on memory references.  */
 
 /* Returns the size in bytes of the mode of X.  */
@@ -278,6 +276,24 @@ alias_sets_conflict_p (set1, set2)
   return 0;
 }
 \f
+/* Set the alias set of MEM to SET.  */
+
+void
+set_mem_alias_set (mem, set)
+     rtx mem;
+     HOST_WIDE_INT set;
+{
+  /* We would like to do this test but can't yet since when converting a
+     REG to a MEM, the alias set field is undefined.  */
+#if 0
+  /* If the new and old alias sets don't conflict, something is wrong.  */
+  if (!alias_sets_conflict_p (set, MEM_ALIAS_SET (mem)))
+    abort ();
+#endif
+
+  MEM_ALIAS_SET (mem) = set;
+}
+\f
 /* Return 1 if TYPE is a RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE and has
    has any readonly fields.  If any of the fields have types that
    contain readonly fields, return true as well.  */
@@ -336,7 +352,7 @@ objects_must_conflict_p (t1, t2)
       != (t2 != 0 && AGGREGATE_TYPE_P (t2)))
     return 0;
 
-  /* Otherwise they conflict only if the alias sets conflict. */
+  /* Otherwise they conflict only if the alias sets conflict.  */
   return alias_sets_conflict_p (t1 ? get_alias_set (t1) : 0,
                                t2 ? get_alias_set (t2) : 0);
 }
@@ -383,7 +399,6 @@ find_base_decl (t)
     case '3':
       d0 = find_base_decl (TREE_OPERAND (t, 0));
       d1 = find_base_decl (TREE_OPERAND (t, 1));
-      d0 = find_base_decl (TREE_OPERAND (t, 0));
       d2 = find_base_decl (TREE_OPERAND (t, 2));
 
       /* Set any nonzero values from the last, then from the first.  */
@@ -412,6 +427,7 @@ handled_component_p (t)
     case BIT_FIELD_REF:
     case COMPONENT_REF:
     case ARRAY_REF:
+    case ARRAY_RANGE_REF:
     case NON_LVALUE_EXPR:
       return 1;
 
@@ -445,7 +461,7 @@ can_address_p (t)
           && can_address_p (TREE_OPERAND (t, 0)))
     return 1;
 
-  else if (TREE_CODE (t) == ARRAY_REF
+  else if ((TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
           && ! TYPE_NONALIASED_COMPONENT (TREE_TYPE (TREE_OPERAND (t, 0)))
           && can_address_p (TREE_OPERAND (t, 0)))
     return 1;
@@ -510,6 +526,13 @@ get_alias_set (t)
            return 0;
        }
 
+      /* If we've already determined the alias set for this decl, just
+        return it.  This is necessary for C++ anonymous unions, whose
+        component variables don't look like union members (boo!).  */
+      if (TREE_CODE (t) == VAR_DECL
+         && DECL_RTL_SET_P (t) && GET_CODE (DECL_RTL (t)) == MEM)
+       return MEM_ALIAS_SET (DECL_RTL (t));
+
       /* Give the language another chance to do something special.  */
       if (orig_t != t
          && (set = lang_get_alias_set (t)) != -1)
@@ -741,7 +764,7 @@ find_base_value (src)
       if (GET_CODE (src) != PLUS && GET_CODE (src) != MINUS)
        break;
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case PLUS:
     case MINUS:
@@ -790,7 +813,7 @@ find_base_value (src)
 
     case AND:
       /* If the second operand is constant set the base
-        address to the first operand. */
+        address to the first operand.  */
       if (GET_CODE (XEXP (src, 1)) == CONST_INT && INTVAL (XEXP (src, 1)) != 0)
        return find_base_value (XEXP (src, 0));
       return 0;
@@ -958,12 +981,10 @@ canon_rtx (x)
 
       if (x0 != XEXP (x, 0) || x1 != XEXP (x, 1))
        {
-         /* We can tolerate LO_SUMs being offset here; these
-            rtl are used for nothing other than comparisons.  */
          if (GET_CODE (x0) == CONST_INT)
-           return plus_constant_for_output (x1, INTVAL (x0));
+           return plus_constant (x1, INTVAL (x0));
          else if (GET_CODE (x1) == CONST_INT)
-           return plus_constant_for_output (x0, INTVAL (x1));
+           return plus_constant (x0, INTVAL (x1));
          return gen_rtx_PLUS (GET_MODE (x), x0, x1);
        }
     }
@@ -973,17 +994,8 @@ canon_rtx (x)
      MEM alone, but need to return the canonicalized MEM with
      all the flags with their original values.  */
   else if (GET_CODE (x) == MEM)
-    {
-      rtx addr = canon_rtx (XEXP (x, 0));
+    x = replace_equiv_address_nv (x, canon_rtx (XEXP (x, 0)));
 
-      if (addr != XEXP (x, 0))
-       {
-         rtx new = gen_rtx_MEM (GET_MODE (x), addr);
-
-         MEM_COPY_ATTRIBUTES (new, x);
-         x = new;
-       }
-    }
   return x;
 }
 
@@ -1026,6 +1038,9 @@ rtx_equal_for_memref_p (x, y)
   /* Some RTL can be compared without a recursive examination.  */
   switch (code)
     {
+    case VALUE:
+      return CSELIB_VAL_PTR (x) == CSELIB_VAL_PTR (y);
+
     case REG:
       return REGNO (x) == REGNO (y);
 
@@ -1095,6 +1110,12 @@ rtx_equal_for_memref_p (x, y)
            return 0;
          break;
 
+         /* This can happen for asm operands.  */
+       case 's':
+         if (strcmp (XSTR (x, i), XSTR (y, i)))
+           return 0;
+         break;
+
        /* This can happen for an asm which clobbers memory.  */
        case '0':
          break;
@@ -1308,11 +1329,11 @@ base_alias_check (x, y, x_mode, y_mode)
        return 1;
       if (GET_CODE (x) == AND
          && (GET_CODE (XEXP (x, 1)) != CONST_INT
-             || GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
+             || (int) GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
        return 1;
       if (GET_CODE (y) == AND
          && (GET_CODE (XEXP (y, 1)) != CONST_INT
-             || GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
+             || (int) GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
        return 1;
       /* Differing symbols never alias.  */
       return 0;
@@ -1332,7 +1353,7 @@ base_alias_check (x, y, x_mode, y_mode)
   if (flag_argument_noalias > 1)
     return 0;
 
-  /* Weak noalias assertion (arguments are distinct, but may match globals). */
+  /* Weak noalias assertion (arguments are distinct, but may match globals).  */
   return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode);
 }
 
@@ -1340,7 +1361,7 @@ base_alias_check (x, y, x_mode, y_mode)
    it unchanged unless it is a value; in the latter case we call cselib to get
    a more useful rtx.  */
 
-static rtx
+rtx
 get_addr (x)
      rtx x;
 {
@@ -1765,6 +1786,63 @@ true_dependence (mem, mem_mode, x, varies)
                                              varies);
 }
 
+/* Canonical true dependence: X is read after store in MEM takes place.
+   Variant of true_dependece which assumes MEM has already been 
+   canonicalized (hence we no longer do that here).  
+   The mem_addr argument has been added, since true_dependence computed 
+   this value prior to canonicalizing.  */
+
+int
+canon_true_dependence (mem, mem_mode, mem_addr, x, varies)
+     rtx mem, mem_addr, x;
+     enum machine_mode mem_mode;
+     int (*varies) PARAMS ((rtx, int));
+{
+  register rtx x_addr;
+
+  if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
+    return 1;
+
+  if (DIFFERENT_ALIAS_SETS_P (x, mem))
+    return 0;
+
+  /* If X is an unchanging read, then it can't possibly conflict with any
+     non-unchanging store.  It may conflict with an unchanging write though,
+     because there may be a single store to this address to initialize it.
+     Just fall through to the code below to resolve the case where we have
+     both an unchanging read and an unchanging write.  This won't handle all
+     cases optimally, but the possible performance loss should be
+     negligible.  */
+  if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
+    return 0;
+
+  x_addr = get_addr (XEXP (x, 0));
+
+  if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
+    return 0;
+
+  x_addr = canon_rtx (x_addr);
+  if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
+                           SIZE_FOR_MODE (x), x_addr, 0))
+    return 0;
+
+  if (aliases_everything_p (x))
+    return 1;
+
+  /* We cannot use aliases_everyting_p to test MEM, since we must look
+     at MEM_MODE, rather than GET_MODE (MEM).  */
+  if (mem_mode == QImode || GET_CODE (mem_addr) == AND)
+    return 1;
+
+  /* In true_dependence we also allow BLKmode to alias anything.  Why
+     don't we do this in anti_dependence and output_dependence?  */
+  if (mem_mode == BLKmode || GET_MODE (x) == BLKmode)
+    return 1;
+
+  return ! fixed_scalar_and_varying_struct_p (mem, x, mem_addr, x_addr,
+                                             varies);
+}
+
 /* Returns non-zero if a write to X might alias a previous read from
    (or, if WRITEP is non-zero, a write to) MEM.  */
 
@@ -1862,7 +1940,7 @@ nonlocal_mentioned_p (x)
     {
       /* Constant functions can be constant if they don't use
          scratch memory used to mark function w/o side effects.  */
-      if (code == CALL_INSN && CONST_CALL_P (x))
+      if (code == CALL_INSN && CONST_OR_PURE_CALL_P (x))
         {
          x = CALL_INSN_FUNCTION_USAGE (x);
          if (x == 0)
@@ -1880,7 +1958,7 @@ nonlocal_mentioned_p (x)
        {
          /* Global registers are not local.  */
          if (REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
-             && global_regs[REGNO (SUBREG_REG (x)) + SUBREG_WORD (x)])
+             && global_regs[subreg_regno (x)])
            return 1;
          return 0;
        }
@@ -1980,96 +2058,6 @@ nonlocal_mentioned_p (x)
   return 0;
 }
 
-/* Return non-zero if a loop (natural or otherwise) is present.
-   Inspired by Depth_First_Search_PP described in:
-
-     Advanced Compiler Design and Implementation
-     Steven Muchnick
-     Morgan Kaufmann, 1997
-
-   and heavily borrowed from flow_depth_first_order_compute.  */
-
-static int
-loop_p ()
-{
-  edge *stack;
-  int *pre;
-  int *post;
-  int sp;
-  int prenum = 1;
-  int postnum = 1;
-  sbitmap visited;
-
-  /* Allocate the preorder and postorder number arrays.  */
-  pre = (int *) xcalloc (n_basic_blocks, sizeof (int));
-  post = (int *) xcalloc (n_basic_blocks, sizeof (int));
-
-  /* Allocate stack for back-tracking up CFG.  */
-  stack = (edge *) xmalloc ((n_basic_blocks + 1) * sizeof (edge));
-  sp = 0;
-
-  /* Allocate bitmap to track nodes that have been visited.  */
-  visited = sbitmap_alloc (n_basic_blocks);
-
-  /* None of the nodes in the CFG have been visited yet.  */
-  sbitmap_zero (visited);
-
-  /* Push the first edge on to the stack.  */
-  stack[sp++] = ENTRY_BLOCK_PTR->succ;
-
-  while (sp)
-    {
-      edge e;
-      basic_block src;
-      basic_block dest;
-
-      /* Look at the edge on the top of the stack.  */
-      e = stack[sp - 1];
-      src = e->src;
-      dest = e->dest;
-
-      /* Check if the edge destination has been visited yet.  */
-      if (dest != EXIT_BLOCK_PTR && ! TEST_BIT (visited, dest->index))
-       {
-         /* Mark that we have visited the destination.  */
-         SET_BIT (visited, dest->index);
-
-         pre[dest->index] = prenum++;
-
-         if (dest->succ)
-           {
-             /* Since the DEST node has been visited for the first
-                time, check its successors.  */
-             stack[sp++] = dest->succ;
-           }
-         else
-           post[dest->index] = postnum++;
-       }
-      else
-       {
-         if (dest != EXIT_BLOCK_PTR
-             && pre[src->index] >= pre[dest->index]
-             && post[dest->index] == 0)
-           break;
-
-         if (! e->succ_next && src != ENTRY_BLOCK_PTR)
-           post[src->index] = postnum++;
-
-         if (e->succ_next)
-           stack[sp - 1] = e->succ_next;
-         else
-           sp--;
-       }
-    }
-
-  free (pre);
-  free (post);
-  free (stack);
-  sbitmap_free (visited);
-
-  return sp;
-}
-
 /* Mark the function if it is constant.  */
 
 void
@@ -2086,7 +2074,7 @@ mark_constant_function ()
     return;
 
   /* A loop might not return which counts as a side effect.  */
-  if (loop_p ())
+  if (mark_dfs_back_edges ())
     return;
 
   nonlocal_mentioned = 0;
@@ -2124,7 +2112,7 @@ init_alias_once ()
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     /* Check whether this register can hold an incoming pointer
        argument.  FUNCTION_ARG_REGNO_P tests outgoing register
-       numbers, so translate if necessary due to register windows. */
+       numbers, so translate if necessary due to register windows.  */
     if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
        && HARD_REGNO_MODE_OK (i, Pmode))
       SET_HARD_REG_BIT (argument_registers, i);
@@ -2252,7 +2240,7 @@ init_alias_analysis ()
 
              /* If this insn has a noalias note, process it,  Otherwise,
                 scan for sets.  A simple set will have no side effects
-                which could change the base value of any other register. */
+                which could change the base value of any other register.  */
 
              if (GET_CODE (PATTERN (insn)) == SET
                  && REG_NOTES (insn) != 0
@@ -2291,8 +2279,7 @@ init_alias_analysis ()
                      rtx op0 = XEXP (src, 0);
                      op0 = reg_known_value[REGNO (op0)];
                      reg_known_value[regno]
-                       = plus_constant_for_output (op0,
-                                                   INTVAL (XEXP (src, 1)));
+                       = plus_constant (op0, INTVAL (XEXP (src, 1)));
                      reg_known_equiv_p[regno] = 0;
                    }
                  else if (REG_N_SETS (regno) == 1