Re: [PATCH] Loop splitting breaks with loops of pointer type

2017-03-08 Thread Richard Biener
On Wed, Mar 8, 2017 at 11:53 AM, Andrew Haley  wrote:
> Loop splitting is fine when the control variable is of integer type,
> but when it is a pointer type the upper bound of the new loop is
> calculated incorrectly.
> The calculation should be guard_init + (end-beg), but instead we do
> guard_init - (end-beg).
>
> Fixed thusly.  Bootstrapped, regtested.
>
> OK?

Ok.

Thanks,
Richard.

> Andrew.
>
>
> 2017-03-08  Andrew Haley  
>
> PR tree-optimization/79894
> * tree-ssa-loop-split.c (compute_new_first_bound): When
> calculating the new upper bound, (END-BEG) should be added, not
> subtracted.
>
> Index: gcc/tree-ssa-loop-split.c
> ===
> --- gcc/tree-ssa-loop-split.c   (revision 245948)
> +++ gcc/tree-ssa-loop-split.c   (working copy)
> @@ -436,7 +436,6 @@
>if (POINTER_TYPE_P (TREE_TYPE (guard_init)))
>  {
>enddiff = gimple_convert (stmts, sizetype, enddiff);
> -  enddiff = gimple_build (stmts, NEGATE_EXPR, sizetype, enddiff);
>newbound = gimple_build (stmts, POINTER_PLUS_EXPR,
>TREE_TYPE (guard_init),
>guard_init, enddiff);
>
>
> 2017-03-08  Andrew Haley  
>
> PR tree-optimization/79894
> * gcc.dg/tree-ssa/pr79943.c: New test.
>
> Index: gcc/testsuite/gcc.dg/tree-ssa/pr79943.c
> ===
> --- gcc/testsuite/gcc.dg/tree-ssa/pr79943.c (revision 0)
> +++ gcc/testsuite/gcc.dg/tree-ssa/pr79943.c (revision 0)
> @@ -0,0 +1,40 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -fsplit-loops -fdump-tree-lsplit-details" } */
> +/* { dg-require-effective-target int32plus } */
> +
> +#ifdef __cplusplus
> +extern "C" void abort (void);
> +#else
> +extern void abort (void);
> +#endif
> +
> +typedef struct {
> +  int n;
> +} region_t;
> +
> +void set (region_t *region) __attribute__((noinline));
> +void doit (region_t *beg, region_t *end, region_t *limit)
> +  __attribute__((noinline));
> +
> +region_t regions[10];
> +
> +void
> +set (region_t *region) {
> +  region->n = 1;
> +}
> +
> +void
> +doit (region_t *beg, region_t *end, region_t *limit) {
> +  for (region_t *cur = beg; cur < end; cur++) {
> +if (cur < limit) {
> +  set(cur);
> +}
> +  }
> +}
> +
> +int
> +main (void) {
> +  doit([0], [2], [10]);
> +  if (regions[1].n != 1)
> +abort();
> +}


[PATCH] Loop splitting breaks with loops of pointer type

2017-03-08 Thread Andrew Haley
Loop splitting is fine when the control variable is of integer type,
but when it is a pointer type the upper bound of the new loop is
calculated incorrectly.
The calculation should be guard_init + (end-beg), but instead we do
guard_init - (end-beg).

Fixed thusly.  Bootstrapped, regtested.

OK?

Andrew.


2017-03-08  Andrew Haley  

PR tree-optimization/79894
* tree-ssa-loop-split.c (compute_new_first_bound): When
calculating the new upper bound, (END-BEG) should be added, not
subtracted.

Index: gcc/tree-ssa-loop-split.c
===
--- gcc/tree-ssa-loop-split.c   (revision 245948)
+++ gcc/tree-ssa-loop-split.c   (working copy)
@@ -436,7 +436,6 @@
   if (POINTER_TYPE_P (TREE_TYPE (guard_init)))
 {
   enddiff = gimple_convert (stmts, sizetype, enddiff);
-  enddiff = gimple_build (stmts, NEGATE_EXPR, sizetype, enddiff);
   newbound = gimple_build (stmts, POINTER_PLUS_EXPR,
   TREE_TYPE (guard_init),
   guard_init, enddiff);


2017-03-08  Andrew Haley  

PR tree-optimization/79894
* gcc.dg/tree-ssa/pr79943.c: New test.

Index: gcc/testsuite/gcc.dg/tree-ssa/pr79943.c
===
--- gcc/testsuite/gcc.dg/tree-ssa/pr79943.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr79943.c (revision 0)
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fsplit-loops -fdump-tree-lsplit-details" } */
+/* { dg-require-effective-target int32plus } */
+
+#ifdef __cplusplus
+extern "C" void abort (void);
+#else
+extern void abort (void);
+#endif
+
+typedef struct {
+  int n;
+} region_t;
+
+void set (region_t *region) __attribute__((noinline));
+void doit (region_t *beg, region_t *end, region_t *limit)
+  __attribute__((noinline));
+
+region_t regions[10];
+
+void
+set (region_t *region) {
+  region->n = 1;
+}
+
+void
+doit (region_t *beg, region_t *end, region_t *limit) {
+  for (region_t *cur = beg; cur < end; cur++) {
+if (cur < limit) {
+  set(cur);
+}
+  }
+}
+
+int
+main (void) {
+  doit([0], [2], [10]);
+  if (regions[1].n != 1)
+abort();
+}