re PR rtl-optimization/57425 (RTL alias analysis unprepared to handle stack slot...
[gcc.git] / gcc / alias.c
index 970bdb0ee9a17b351a3e66ce70fd7cf6d99f5a38..902ed334769b84c92b0b7e7dcf5c571f8c7ba729 100644 (file)
@@ -148,7 +148,7 @@ typedef struct alias_set_entry_d *alias_set_entry;
 static int rtx_equal_for_memref_p (const_rtx, const_rtx);
 static int memrefs_conflict_p (int, rtx, int, rtx, HOST_WIDE_INT);
 static void record_set (rtx, const_rtx, void *);
-static int base_alias_check (rtx, rtx, enum machine_mode,
+static int base_alias_check (rtx, rtx, rtx, rtx, enum machine_mode,
                             enum machine_mode);
 static rtx find_base_value (rtx);
 static int mems_in_disjoint_alias_sets_p (const_rtx, const_rtx);
@@ -156,7 +156,8 @@ static int insert_subset_children (splay_tree_node, void*);
 static alias_set_entry get_alias_set_entry (alias_set_type);
 static bool nonoverlapping_component_refs_p (const_rtx, const_rtx);
 static tree decl_for_component_ref (tree);
-static int write_dependence_p (const_rtx, const_rtx, int);
+static int write_dependence_p (const_rtx, enum machine_mode, rtx, const_rtx,
+                              bool, bool);
 
 static void memory_modified_1 (rtx, const_rtx, void *);
 
@@ -1672,35 +1673,31 @@ find_base_term (rtx x)
        if (tmp1 == pic_offset_table_rtx && CONSTANT_P (tmp2))
          return find_base_term (tmp2);
 
-       /* If either operand is known to be a pointer, then use it
+       /* If either operand is known to be a pointer, then prefer it
           to determine the base term.  */
        if (REG_P (tmp1) && REG_POINTER (tmp1))
+         ;
+       else if (REG_P (tmp2) && REG_POINTER (tmp2))
          {
-           rtx base = find_base_term (tmp1);
-           if (base)
-             return base;
+           rtx tem = tmp1;
+           tmp1 = tmp2;
+           tmp2 = tem;
          }
 
-       if (REG_P (tmp2) && REG_POINTER (tmp2))
-         {
-           rtx base = find_base_term (tmp2);
-           if (base)
-             return base;
-         }
-
-       /* Neither operand was known to be a pointer.  Go ahead and find the
-          base term for both operands.  */
-       tmp1 = find_base_term (tmp1);
-       tmp2 = find_base_term (tmp2);
-
-       /* If either base term is named object or a special address
+       /* Go ahead and find the base term for both operands.  If either base
+          term is from a pointer or is a named object or a special address
           (like an argument or stack reference), then use it for the
           base term.  */
-       if (tmp1 != 0 && known_base_value_p (tmp1))
-         return tmp1;
-
-       if (tmp2 != 0 && known_base_value_p (tmp2))
-         return tmp2;
+       rtx base = find_base_term (tmp1);
+       if (base != NULL_RTX
+           && ((REG_P (tmp1) && REG_POINTER (tmp1))
+                || known_base_value_p (base)))
+         return base;
+       base = find_base_term (tmp2);
+       if (base != NULL_RTX
+           && ((REG_P (tmp2) && REG_POINTER (tmp2))
+                || known_base_value_p (base)))
+         return base;
 
        /* We could not determine which of the two operands was the
           base register and which was the index.  So we can determine
@@ -1736,12 +1733,9 @@ may_be_sp_based_p (rtx x)
    objects, 1 if they might be pointers to the same object.  */
 
 static int
-base_alias_check (rtx x, rtx y, enum machine_mode x_mode,
-                 enum machine_mode y_mode)
+base_alias_check (rtx x, rtx x_base, rtx y, rtx y_base,
+                 enum machine_mode x_mode, enum machine_mode y_mode)
 {
-  rtx x_base = find_base_term (x);
-  rtx y_base = find_base_term (y);
-
   /* If the address itself has no known base see if a known equivalent
      value has one.  If either address still has no known base, nothing
      is known about aliasing.  */
@@ -2511,7 +2505,9 @@ true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
                   && CONSTANT_POOL_ADDRESS_P (base))))
     return 0;
 
-  if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
+  rtx mem_base = find_base_term (mem_addr);
+  if (! base_alias_check (x_addr, base, mem_addr, mem_base,
+                         GET_MODE (x), mem_mode))
     return 0;
 
   x_addr = canon_rtx (x_addr);
@@ -2558,15 +2554,22 @@ canon_true_dependence (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr,
 }
 
 /* Returns nonzero if a write to X might alias a previous read from
-   (or, if WRITEP is nonzero, a write to) MEM.  */
+   (or, if WRITEP is true, a write to) MEM.
+   If MEM_CANONCALIZED is nonzero, CANON_MEM_ADDR is the canonicalized
+   address of MEM, and MEM_MODE the mode for that access.  */
 
 static int
-write_dependence_p (const_rtx mem, const_rtx x, int writep)
+write_dependence_p (const_rtx mem, enum machine_mode mem_mode,
+                   rtx canon_mem_addr, const_rtx x,
+                   bool mem_canonicalized, bool writep)
 {
   rtx x_addr, mem_addr;
   rtx base;
   int ret;
 
+  gcc_checking_assert (mem_canonicalized ? (canon_mem_addr != NULL_RTX)
+                      : (canon_mem_addr == NULL_RTX && mem_mode == VOIDmode));
+
   if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
     return 1;
 
@@ -2603,23 +2606,29 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
       mem_addr = get_addr (mem_addr);
     }
 
-  if (! writep)
-    {
-      base = find_base_term (mem_addr);
-      if (base && (GET_CODE (base) == LABEL_REF
-                  || (GET_CODE (base) == SYMBOL_REF
-                      && CONSTANT_POOL_ADDRESS_P (base))))
-       return 0;
-    }
+  base = find_base_term (mem_addr);
+  if (! writep
+      && base
+      && (GET_CODE (base) == LABEL_REF
+         || (GET_CODE (base) == SYMBOL_REF
+             && CONSTANT_POOL_ADDRESS_P (base))))
+    return 0;
 
-  if (! base_alias_check (x_addr, mem_addr, GET_MODE (x),
+  rtx x_base = find_base_term (x_addr);
+  if (! base_alias_check (x_addr, x_base, mem_addr, base, GET_MODE (x),
                          GET_MODE (mem)))
     return 0;
 
   x_addr = canon_rtx (x_addr);
-  mem_addr = canon_rtx (mem_addr);
+  if (mem_canonicalized)
+    mem_addr = canon_mem_addr;
+  else
+    {
+      mem_addr = canon_rtx (mem_addr);
+      mem_mode = GET_MODE (mem);
+    }
 
-  if ((ret = memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
+  if ((ret = memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
                                 SIZE_FOR_MODE (x), x_addr, 0)) != -1)
     return ret;
 
@@ -2634,7 +2643,20 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
 int
 anti_dependence (const_rtx mem, const_rtx x)
 {
-  return write_dependence_p (mem, x, /*writep=*/0);
+  return write_dependence_p (mem, VOIDmode, NULL_RTX, x,
+                            /*mem_canonicalized=*/false, /*writep=*/false);
+}
+
+/* Likewise, but we already have a canonicalized MEM_ADDR for MEM.
+   Also, consider MEM in MEM_MODE (which might be from an enclosing
+   STRICT_LOW_PART / ZERO_EXTRACT).  */
+
+int
+canon_anti_dependence (const_rtx mem, enum machine_mode mem_mode,
+                      rtx mem_addr, const_rtx x)
+{
+  return write_dependence_p (mem, mem_mode, mem_addr, x,
+                            /*mem_canonicalized=*/true, /*writep=*/false);
 }
 
 /* Output dependence: X is written after store in MEM takes place.  */
@@ -2642,7 +2664,8 @@ anti_dependence (const_rtx mem, const_rtx x)
 int
 output_dependence (const_rtx mem, const_rtx x)
 {
-  return write_dependence_p (mem, x, /*writep=*/1);
+  return write_dependence_p (mem, VOIDmode, NULL_RTX, x,
+                            /*mem_canonicalized=*/false, /*writep=*/true);
 }
 \f
 
@@ -2692,7 +2715,10 @@ may_alias_p (const_rtx mem, const_rtx x)
       mem_addr = get_addr (mem_addr);
     }
 
-  if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), GET_MODE (mem_addr)))
+  rtx x_base = find_base_term (x_addr);
+  rtx mem_base = find_base_term (mem_addr);
+  if (! base_alias_check (x_addr, x_base, mem_addr, mem_base,
+                         GET_MODE (x), GET_MODE (mem_addr)))
     return 0;
 
   x_addr = canon_rtx (x_addr);