aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@vlsi1.ultra.nyu.edu>2001-11-09 22:52:09 +0000
committerRichard Kenner <kenner@gcc.gnu.org>2001-11-09 17:52:09 -0500
commita4311dfe6d5ee5539793adb7bf12400b070ba9b1 (patch)
tree86174706216e85f35260246db13975108f5b73bc
parent9ddfb1a75bece3f23c95c7d9ec0e8bbff3b1cb67 (diff)
downloadgcc-a4311dfe6d5ee5539793adb7bf12400b070ba9b1.zip
gcc-a4311dfe6d5ee5539793adb7bf12400b070ba9b1.tar.gz
gcc-a4311dfe6d5ee5539793adb7bf12400b070ba9b1.tar.bz2
alias.c (nonoverlapping_memrefs_p): New function.
* alias.c (nonoverlapping_memrefs_p): New function. (true_dependence, canon_true_depenence, write_dependence_p): Call it. From-SVN: r46897
-rw-r--r--gcc/ChangeLog3
-rw-r--r--gcc/alias.c85
2 files changed, 88 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 59683bd..5c8c34d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,8 @@
Fri Nov 9 17:51:09 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
+ * alias.c (nonoverlapping_memrefs_p): New function.
+ (true_dependence, canon_true_depenence, write_dependence_p): Call it.
+
* emit-rtl.c (set_mem_attributes): Get alignments for constants.
2001-11-09 Aldy Hernandez <aldyh@redhat.com>
diff --git a/gcc/alias.c b/gcc/alias.c
index 84fbdc9..add9c94 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -104,6 +104,7 @@ static alias_set_entry get_alias_set_entry PARAMS ((HOST_WIDE_INT));
static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, rtx, rtx,
int (*) (rtx, int)));
static int aliases_everything_p PARAMS ((rtx));
+static int nonoverlapping_memrefs_p PARAMS ((rtx, rtx));
static int write_dependence_p PARAMS ((rtx, rtx, int));
static int nonlocal_mentioned_p PARAMS ((rtx));
@@ -1761,6 +1762,81 @@ aliases_everything_p (mem)
return 0;
}
+/* Return nonzero if we can deterimine the decls corresponding to memrefs
+ X and Y and they do not overlap. */
+
+static int
+nonoverlapping_memrefs_p (x, y)
+ rtx x, y;
+{
+ rtx rtlx, rtly;
+ rtx basex, basey;
+ HOST_WIDE_INT offsetx = 0, offsety = 0, sizex, sizey, tem;
+
+ /* Unless both have decls, we can't tell anything. */
+ if (MEM_DECL (x) == 0 || MEM_DECL (y) == 0)
+ return 0;
+
+ rtlx = DECL_RTL (MEM_DECL (x));
+ rtly = DECL_RTL (MEM_DECL (y));
+
+ /* If either RTL is a REG, they can't overlap unless they are the same
+ because we never reuse that part of the stack frame used for locals for
+ spilled pseudos. */
+ if ((REG_P (rtlx) || REG_P (rtly)) && ! rtx_equal_p (rtlx, rtly))
+ return 1;
+
+ /* Get the base and offsets of both decls. If either is a register, we
+ know both are and are the same, so use that as the base. The only
+ we can avoid overlap is if we can deduce that they are nonoverlapping
+ pieces of that decl, which is very rare. */
+ basex = REG_P (rtlx) ? rtlx : XEXP (rtlx, 0);
+ if (GET_CODE (basex) == PLUS && GET_CODE (XEXP (basex, 1)) == CONST_INT)
+ offsetx = INTVAL (XEXP (basex, 1)), basex = XEXP (basex, 0);
+
+ basey = REG_P (rtly) ? rtly : XEXP (rtly, 0);
+ if (GET_CODE (basey) == PLUS && GET_CODE (XEXP (basey, 1)) == CONST_INT)
+ offsety = INTVAL (XEXP (basey, 1)), basey = XEXP (basey, 0);
+
+ /* If the bases are both constant and they are different, we know these
+ do not overlap. If they are both registers, we can only deduce
+ something if they are the same register. */
+ if (CONSTANT_P (basex) && CONSTANT_P (basey) && ! rtx_equal_p (basex, basey))
+ return 1;
+ else if (! rtx_equal_p (basex, basey))
+ return 0;
+
+ sizex = (REG_P (rtlx) ? GET_MODE_SIZE (GET_MODE (rtlx))
+ : MEM_SIZE (rtlx) ? INTVAL (MEM_SIZE (rtlx))
+ : -1);
+ sizey = (REG_P (rtly) ? GET_MODE_SIZE (GET_MODE (rtly))
+ : MEM_SIZE (rtly) ? INTVAL (MEM_SIZE (rtly)) :
+ -1);
+
+ /* If we have an offset or size for either memref, it can update the values
+ computed above. */
+ if (MEM_OFFSET (x))
+ offsetx += INTVAL (MEM_OFFSET (x));
+ if (MEM_OFFSET (y))
+ offsety += INTVAL (MEM_OFFSET (y));
+
+ if (MEM_SIZE (x))
+ sizex = INTVAL (MEM_SIZE (x));
+ if (MEM_SIZE (y))
+ sizey = INTVAL (MEM_SIZE (y));
+
+ /* Put the values of the memref with the lower offset in X's values. */
+ if (offsetx > offsety)
+ {
+ tem = offsetx, offsetx = offsety, offsety = tem;
+ tem = sizex, sizex = sizey, sizey = tem;
+ }
+
+ /* If we don't know the size of the lower-offset value, we can't tell
+ if they conflict. Otherwise, we do the test. */
+ return sizex >= 0 && offsety > offsetx + sizex;
+}
+
/* True dependence: X is read after store in MEM takes place. */
int
@@ -1792,6 +1868,9 @@ true_dependence (mem, mem_mode, x, varies)
if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
return 0;
+ if (nonoverlapping_memrefs_p (mem, x))
+ return 0;
+
if (mem_mode == VOIDmode)
mem_mode = GET_MODE (mem);
@@ -1861,6 +1940,9 @@ canon_true_dependence (mem, mem_mode, mem_addr, x, varies)
if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
return 0;
+ if (nonoverlapping_memrefs_p (x, mem))
+ return 0;
+
x_addr = get_addr (XEXP (x, 0));
if (! base_alias_check (x_addr, mem_addr, GET_MODE (x), mem_mode))
@@ -1917,6 +1999,9 @@ write_dependence_p (mem, x, writep)
if (! writep && RTX_UNCHANGING_P (mem))
return 0;
+ if (nonoverlapping_memrefs_p (x, mem))
+ return 0;
+
x_addr = get_addr (XEXP (x, 0));
mem_addr = get_addr (XEXP (mem, 0));