diff options
author | Richard Kenner <kenner@vlsi1.ultra.nyu.edu> | 2001-11-09 22:52:09 +0000 |
---|---|---|
committer | Richard Kenner <kenner@gcc.gnu.org> | 2001-11-09 17:52:09 -0500 |
commit | a4311dfe6d5ee5539793adb7bf12400b070ba9b1 (patch) | |
tree | 86174706216e85f35260246db13975108f5b73bc | |
parent | 9ddfb1a75bece3f23c95c7d9ec0e8bbff3b1cb67 (diff) | |
download | gcc-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/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/alias.c | 85 |
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)); |