diff mbox series

[19/nn] Don't treat zero-sized ranges as overlapping

Message ID 87mv4iumpq.fsf@linaro.org
State New
Headers show
Series [19/nn] Don't treat zero-sized ranges as overlapping | expand

Commit Message

Richard Sandiford Oct. 23, 2017, 11:29 a.m. UTC
Most GCC ranges seem to be represented as an offset and a size (rather
than a start and inclusive end or start and exclusive end).  The usual
test for whether X is in a range is of course:

  x >= start && x < start + size
or:
  x >= start && x - start < size

which means that an empty range of size 0 contains nothing.  But other
range tests aren't as obvious.

The usual test for whether one range is contained within another
range is:

  start1 >= start2 && start1 + size1 <= start2 + size2

while the test for whether two ranges overlap (from ranges_overlap_p) is:

     (start1 >= start2 && start1 < start2 + size2)
  || (start2 >= start1 && start2 < start1 + size1)

i.e. the ranges overlap if one range contains the start of the other
range.  This leads to strange results like:

  (start X, size 0) is a subrange of (start X, size 0) but
  (start X, size 0) does not overlap (start X, size 0)

Similarly:

  (start 4, size 0) is a subrange of (start 2, size 2) but
  (start 4, size 0) does not overlap (start 2, size 2)

It seems like "X is a subrange of Y" should imply "X overlaps Y".

This becomes harder to ignore with the runtime sizes and offsets
added for SVE.  The most obvious fix seemed to be to say that
an empty range does not overlap anything, and is therefore not
a subrange of anything.

Using the new definition of subranges didn't seem to cause any
codegen differences in the testsuite.  But there was one change
with the new definition of overlapping ranges.  strncpy-chk.c has:

  memset (dst, 0, sizeof (dst));
  if (strncpy (dst, src, 0) != dst || strcmp (dst, ""))
    abort();

The strncpy is detected as a zero-size write, and so with the new
definition of overlapping ranges, we treat the strncpy as having
no effect on the strcmp (which is true).  The reaching definition
is the memset instead.

This patch makes ranges_overlap_p return false for zero-sized
ranges, even if the other range has an unknown size.


2017-10-23  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* tree-ssa-alias.h (ranges_overlap_p): Return false if either
	range is known to be empty.

Comments

Richard Biener Oct. 26, 2017, 12:13 p.m. UTC | #1
On Mon, Oct 23, 2017 at 1:29 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> Most GCC ranges seem to be represented as an offset and a size (rather

> than a start and inclusive end or start and exclusive end).  The usual

> test for whether X is in a range is of course:

>

>   x >= start && x < start + size

> or:

>   x >= start && x - start < size

>

> which means that an empty range of size 0 contains nothing.  But other

> range tests aren't as obvious.

>

> The usual test for whether one range is contained within another

> range is:

>

>   start1 >= start2 && start1 + size1 <= start2 + size2

>

> while the test for whether two ranges overlap (from ranges_overlap_p) is:

>

>      (start1 >= start2 && start1 < start2 + size2)

>   || (start2 >= start1 && start2 < start1 + size1)

>

> i.e. the ranges overlap if one range contains the start of the other

> range.  This leads to strange results like:

>

>   (start X, size 0) is a subrange of (start X, size 0) but

>   (start X, size 0) does not overlap (start X, size 0)

>

> Similarly:

>

>   (start 4, size 0) is a subrange of (start 2, size 2) but

>   (start 4, size 0) does not overlap (start 2, size 2)

>

> It seems like "X is a subrange of Y" should imply "X overlaps Y".

>

> This becomes harder to ignore with the runtime sizes and offsets

> added for SVE.  The most obvious fix seemed to be to say that

> an empty range does not overlap anything, and is therefore not

> a subrange of anything.

>

> Using the new definition of subranges didn't seem to cause any

> codegen differences in the testsuite.  But there was one change

> with the new definition of overlapping ranges.  strncpy-chk.c has:

>

>   memset (dst, 0, sizeof (dst));

>   if (strncpy (dst, src, 0) != dst || strcmp (dst, ""))

>     abort();

>

> The strncpy is detected as a zero-size write, and so with the new

> definition of overlapping ranges, we treat the strncpy as having

> no effect on the strcmp (which is true).  The reaching definition

> is the memset instead.

>

> This patch makes ranges_overlap_p return false for zero-sized

> ranges, even if the other range has an unknown size.


Ok.

Thanks,
Richard.

>

> 2017-10-23  Richard Sandiford  <richard.sandiford@linaro.org>

>

> gcc/

>         * tree-ssa-alias.h (ranges_overlap_p): Return false if either

>         range is known to be empty.

>

> Index: gcc/tree-ssa-alias.h

> ===================================================================

> --- gcc/tree-ssa-alias.h        2017-03-28 16:19:22.000000000 +0100

> +++ gcc/tree-ssa-alias.h        2017-10-23 11:47:38.181155696 +0100

> @@ -171,6 +171,8 @@ ranges_overlap_p (HOST_WIDE_INT pos1,

>                   HOST_WIDE_INT pos2,

>                   unsigned HOST_WIDE_INT size2)

>  {

> +  if (size1 == 0 || size2 == 0)

> +    return false;

>    if (pos1 >= pos2

>        && (size2 == (unsigned HOST_WIDE_INT)-1

>           || pos1 < (pos2 + (HOST_WIDE_INT) size2)))
diff mbox series

Patch

Index: gcc/tree-ssa-alias.h
===================================================================
--- gcc/tree-ssa-alias.h	2017-03-28 16:19:22.000000000 +0100
+++ gcc/tree-ssa-alias.h	2017-10-23 11:47:38.181155696 +0100
@@ -171,6 +171,8 @@  ranges_overlap_p (HOST_WIDE_INT pos1,
 		  HOST_WIDE_INT pos2,
 		  unsigned HOST_WIDE_INT size2)
 {
+  if (size1 == 0 || size2 == 0)
+    return false;
   if (pos1 >= pos2
       && (size2 == (unsigned HOST_WIDE_INT)-1
 	  || pos1 < (pos2 + (HOST_WIDE_INT) size2)))