Be conservative about negative sizes on symbols, use abs elsewhere
From: Alexandre Oliva <aoliva@redhat.com>
for gcc/ChangeLog
PR rtl-optimization/55547
PR rtl-optimization/53827
PR debug/53671
PR debug/49888
* alias.c (memrefs_conflict_p): Use abs of sizes all over,
retaining the conservative special case for symbolic
constants.
---
gcc/alias.c | 46 ++++++++++++++++++++++++++++------------------
1 files changed, 28 insertions(+), 18 deletions(-)
@@ -1904,6 +1904,20 @@ addr_side_effect_eval (rtx addr, int size, int n_refs)
return addr;
}
+/* Return TRUE if an object X sized at XSIZE bytes and another object
+ Y sized at YSIZE bytes, starting C bytes after X, may overlap. If
+ any of the sizes is zero, assume an overlap, otherwise use the
+ absolute value of the sizes as the actual sizes. */
+
+static inline bool
+offset_overlap_p (HOST_WIDE_INT c, int xsize, int ysize)
+{
+ return (xsize == 0 || ysize == 0
+ || (c >= 0
+ ? (abs (xsize) > c)
+ : (abs (ysize) > -c)));
+}
+
/* Return one if X and Y (memory addresses) reference the
same location in memory or if the references overlap.
Return zero if they do not overlap, else return
@@ -1976,23 +1990,17 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
else if (GET_CODE (x) == LO_SUM)
x = XEXP (x, 1);
else
- x = addr_side_effect_eval (x, xsize, 0);
+ x = addr_side_effect_eval (x, abs (xsize), 0);
if (GET_CODE (y) == HIGH)
y = XEXP (y, 0);
else if (GET_CODE (y) == LO_SUM)
y = XEXP (y, 1);
else
- y = addr_side_effect_eval (y, ysize, 0);
+ y = addr_side_effect_eval (y, abs (ysize), 0);
if (rtx_equal_for_memref_p (x, y))
{
- if (xsize <= 0 || ysize <= 0)
- return 1;
- if (c >= 0 && xsize > c)
- return 1;
- if (c < 0 && ysize+c > 0)
- return 1;
- return 0;
+ return offset_overlap_p (c, xsize, ysize);
}
/* This code used to check for conflicts involving stack references and
@@ -2062,8 +2070,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
x0 = canon_rtx (XEXP (x, 0));
y0 = canon_rtx (XEXP (y, 0));
if (rtx_equal_for_memref_p (x0, y0))
- return (xsize == 0 || ysize == 0
- || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
+ return offset_overlap_p (c, xsize, ysize);
/* Can't properly adjust our sizes. */
if (!CONST_INT_P (x1))
@@ -2093,7 +2100,8 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
{
if (xsize > 0)
xsize = -xsize;
- xsize += sc + 1;
+ if (xsize)
+ xsize += sc + 1;
c -= sc + 1;
return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),
ysize, y, c);
@@ -2107,7 +2115,8 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
{
if (ysize > 0)
ysize = -ysize;
- ysize += sc + 1;
+ if (ysize)
+ ysize += sc + 1;
c += sc + 1;
return memrefs_conflict_p (xsize, x,
ysize, canon_rtx (XEXP (y, 0)), c);
@@ -2119,8 +2128,7 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
if (CONST_INT_P (x) && CONST_INT_P (y))
{
c += (INTVAL (y) - INTVAL (x));
- return (xsize <= 0 || ysize <= 0
- || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
+ return offset_overlap_p (c, xsize, ysize);
}
if (GET_CODE (x) == CONST)
@@ -2136,10 +2144,12 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
return memrefs_conflict_p (xsize, x, ysize,
canon_rtx (XEXP (y, 0)), c);
+ /* Assume a potential overlap for symbolic addresses that went
+ through alignment adjustments (i.e., that have negative
+ sizes), because we can't know how far they are from each
+ other. */
if (CONSTANT_P (y))
- return (xsize <= 0 || ysize <= 0
- || (rtx_equal_for_memref_p (x, y)
- && ((c >= 0 && xsize > c) || (c < 0 && ysize+c > 0))));
+ return (xsize < 0 || ysize < 0 || offset_overlap_p (c, xsize, ysize));
return -1;
}