[PATCH, PR43236] Miscompilations with tree-loop-distribution

Alexander Monakov amonakov@ispras.ru
Wed Mar 10 11:21:00 GMT 2010


This patch fixes two wrong-code bugs in tree loop distribution, both of which
are demonstrated with the same testcase at different optimization levels (-Os,
-O[123]).

The first problem is wrong calculation of base address for memset zero: it is
(first_access - niter), while it should be (first_access - niter + 1).
Note that generate_memset_zero may benefit from slight refactoring of memset
args construction: if/else blocks are very similar.  I can do that as a
followup.

The second problem is that assignment may end up in the latch block, in which
case we should use number_of_latch_executions, not number_of_exit_cond_execs.
This happens with -Os on the testcase.

Fixed as follows, bootstrapped and regtested with loop distribution enabled by
default on x86_64-linux.  Ok for 4.6?  Ok for trunk (the changes are isolated
and the previous loop distribution patch was approved for trunk)?

2010-08-10  Alexander Monakov  <amonakov@ispras.ru>

        PR tree-optimization/43236
        * tree-loop-distribution.c (generate_memset_zero): Fix off-by-one
        error is calculation of base access in reverse iteration case.
        (generate_builtin): Take number of latch executions if the statement
        is in the latch.

        * gcc.c-torture/execute/pr43236.c: New.

diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 920ab8c..74120c6 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -285,6 +285,8 @@ generate_memset_zero (gimple stmt, tree op0, tree nb_iter,
       addr_base = fold_convert_loc (loc, sizetype, addr_base);
       addr_base = size_binop_loc (loc, MINUS_EXPR, addr_base,
                                  fold_convert_loc (loc, sizetype, nb_bytes));
+      addr_base = size_binop_loc (loc, PLUS_EXPR, addr_base,
+                                 TYPE_SIZE_UNIT (TREE_TYPE (op0)));
       addr_base = fold_build2_loc (loc, POINTER_PLUS_EXPR,
                                   TREE_TYPE (DR_BASE_ADDRESS (dr)),
                                   DR_BASE_ADDRESS (dr), addr_base);
@@ -389,6 +391,8 @@ generate_builtin (struct loop *loop, bitmap partition, bool copy_p)
                goto end;
 
              write = stmt;
+             if (bb == loop->latch)
+               nb_iter = number_of_latch_executions (loop);
            }
        }
     }
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr43236.c b/gcc/testsuite/gcc.c-torture/execute/pr43236.c
new file mode 100644
index 0000000..0401c88
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr43236.c
@@ -0,0 +1,32 @@
+/* { dg-options "-ftree-loop-distribution" } */
+extern void abort(void);
+extern void *memset(void *s, int c, __SIZE_TYPE__ n);
+extern int memcmp(const void *s1, const void *s2, __SIZE_TYPE__ n);
+/*extern int printf(const char *format, ...);*/
+
+int main()
+{
+  char A[30], B[30], C[30];
+  int i;
+
+  /* prepare arrays */
+  memset(A, 1, 30);
+  memset(B, 1, 30);
+
+  for (i = 20; i-- > 10;) {
+    A[i] = 0;
+    B[i] = 0;
+  }
+
+  /* expected result */
+  memset(C, 1, 30);
+  memset(C + 10, 0, 10);
+
+  /* show result */
+/*  for (i = 0; i < 30; i++)
+    printf("%d %d %d\n", A[i], B[i], C[i]); */
+
+  /* compare results */
+  if (memcmp(A, C, 30) || memcmp(B, C, 30)) abort();
+  return 0;
+}



More information about the Gcc-patches mailing list