[PATCH] c-family: Use TYPE_OVERFLOW_UNDEFINED instead of !TYPE_UNSIGNED in pointer_sum [PR95903]

Richard Biener rguenther@suse.de
Sat Jun 27 10:12:59 GMT 2020


On June 27, 2020 10:58:56 AM GMT+02:00, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>For lp64 targets and int off ... ptr[off + 1]
>is lowered in pointer_sum to *(ptr + ((sizetype) off + (sizetype) 1)).
>That is fine when signed integer wrapping is undefined (and is not done
>already if off has unsigned type), but changes behavior for -fwrapv,
>where
>overflow is well defined.  Runtime test could be:
>int
>main ()
>{
>  char *p = __builtin_malloc (0x100000000UL);
>  if (!p) return 0;
>  char *q = p + 0x80000000UL;
>  int o = __INT_MAX__;
>  q[o + 1] = 1;
>  if (q[-__INT_MAX__ - 1] != 1) __builtin_abort ();
>  return 0;
>}
>with -fwrapv or so, not included in the testsuite because it requires
>4GB
>allocation (with some other test it would be enough to have something
>slightly above 2GB, but still...).
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK. 

Richard. 

>On the other side, it would be nice with undefined signed integer
>overflow
>to optimize
>extern signed char arr[];
>int foo (int off) { off++; return arr[off]; }
>at least on targets that have addressing that can include both index
>and
>some immediate, right now we emit
>	addl	$1, %edi
>	movslq	%edi, %rdi
>	movsbl	arr(%rdi), %eax
>but we could emit
>	movslq	%edi, %rdi
>	movsbl	arr+1(%rdi), %eax
>Not sure where to do that; after expansion it is too late, because
>signed
>vs. unsigned addition is lost at that point, so maybe the isel pass or
>some
>other late pass?  Wonder if ivopts is able to do that, but ivopts
>doesn't
>work outside of loops, right?

Right. SLSR was supposed to eventually handle this. 

Richard. 

>2020-06-27  Jakub Jelinek  <jakub@redhat.com>
>
>	PR middle-end/95903
>	* c-common.c (pointer_int_sum): Use TYPE_OVERFLOW_UNDEFINED instead of
>	!TYPE_UNSIGNED check to see if we can apply distributive law and
>handle
>	smaller precision intop operands separately.
>
>	* c-c++-common/pr95903.c: New test.
>
>--- gcc/c-family/c-common.c.jj	2020-06-18 11:26:09.522400264 +0200
>+++ gcc/c-family/c-common.c	2020-06-26 10:28:10.385144734 +0200
>@@ -3141,7 +3141,7 @@ pointer_int_sum (location_t loc, enum tr
>     /* If the constant is unsigned, and smaller than the pointer size,
> 	 then we must skip this optimization.  This is because it could cause
> 	 an overflow error if the constant is negative but INTOP is not.  */
>-      && (!TYPE_UNSIGNED (TREE_TYPE (intop))
>+      && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (intop))
> 	  || (TYPE_PRECISION (TREE_TYPE (intop))
> 	      == TYPE_PRECISION (TREE_TYPE (ptrop)))))
>     {
>--- gcc/testsuite/c-c++-common/pr95903.c.jj	2020-06-26
>10:43:19.325937680 +0200
>+++ gcc/testsuite/c-c++-common/pr95903.c	2020-06-26 10:47:24.017382649
>+0200
>@@ -0,0 +1,19 @@
>+/* PR middle-end/95903 */
>+/* { dg-do compile { target lp64 } } */
>+/* { dg-options "-O2 -fwrapv -fdump-tree-optimized" } */
>+/* Verify that for -fwrapv the + 1 addition is performed in the
>parameter's
>+   type before sign extending it.  */
>+/* { dg-final { scan-tree-dump-times "off_\[0-9]+\\\(D\\\) \\+ 1" 2
>"optimized" } } */
>+
>+char
>+foo (const char *ptr, int off)
>+{
>+  off += 1;
>+  return ptr[off];
>+}
>+
>+char
>+bar (const char *ptr, int off)
>+{
>+  return ptr[off + 1];
>+}
>
>	Jakub



More information about the Gcc-patches mailing list