]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/111583 - loop distribution issue
authorRichard Biener <rguenther@suse.de>
Fri, 29 Sep 2023 09:08:18 +0000 (11:08 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 10 Nov 2023 13:22:24 +0000 (14:22 +0100)
The following conservatively fixes loop distribution to only
recognize memset/memcpy and friends when at least one element
is going to be processed.  This avoids having an unconditional
builtin call in the IL that might imply the source and destination
pointers are non-NULL when originally pointers were not always
dereferenced.

With -Os loop header copying is less likely to ensure this.

PR tree-optimization/111583
* tree-loop-distribution.cc (find_single_drs): Ensure the
load/store are always executed.

* gcc.dg/tree-ssa/pr111583-1.c: New testcase.
* gcc.dg/tree-ssa/pr111583-2.c: Likewise.

(cherry picked from commit 962ca7149d652e4077a2259886e5cd2ea3cea0ab)

gcc/testsuite/gcc.dg/tree-ssa/pr111583-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/pr111583-2.c [new file with mode: 0644]
gcc/tree-loop-distribution.cc

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr111583-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr111583-1.c
new file mode 100644 (file)
index 0000000..1dd8dbc
--- /dev/null
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-Os" } */
+
+short a, f, i;
+static const int *e;
+short *g;
+long h;
+int main()
+{
+    {
+      unsigned j = i;
+      a = 1;
+      for (; a; a++) {
+           {
+             long b = j, d = h;
+             int c = 0;
+             while (d--)
+               *(char *)b++ = c;
+           }
+         if (e)
+           break;
+      }
+      j && (*g)--;
+      const int **k = &e;
+      *k = 0;
+    }
+  if (f != 0)
+    __builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr111583-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr111583-2.c
new file mode 100644 (file)
index 0000000..0ee2185
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-Os" } */
+
+int b, c, d;
+char e;
+short f;
+const unsigned short **g;
+char h(char k) {
+  if (k)
+    return '0';
+  return 0;
+}
+int l() {
+  b = 0;
+  return 1;
+}
+static short m(unsigned k) {
+  const unsigned short *n[65];
+  g = &n[4];
+  k || l();
+  long a = k;
+  char i = 0;
+  unsigned long j = k;
+  while (j--)
+    *(char *)a++ = i;
+  c = h(d);
+  f = k;
+  return 0;
+}
+int main() {
+  long o = (e < 0) << 5;
+  m(o);
+  if (f != 0)
+    __builtin_abort ();
+  return 0;
+}
index 431bd45c5223bfb972b9770331099db99f5909f8..c674da97b02f8376b54f8efceaed40e417575dfe 100644 (file)
@@ -1573,6 +1573,7 @@ find_single_drs (class loop *loop, struct graph *rdg, const bitmap &partition_st
 
   basic_block bb_ld = NULL;
   basic_block bb_st = NULL;
+  edge exit = single_exit (loop);
 
   if (single_ld)
     {
@@ -1588,6 +1589,14 @@ find_single_drs (class loop *loop, struct graph *rdg, const bitmap &partition_st
       bb_ld = gimple_bb (DR_STMT (single_ld));
       if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_ld))
        return false;
+
+      /* The data reference must also be executed before possibly exiting
+        the loop as otherwise we'd for example unconditionally execute
+        memset (ptr, 0, n) which even with n == 0 implies ptr is non-NULL.  */
+      if (bb_ld != loop->header
+         && (!exit
+             || !dominated_by_p (CDI_DOMINATORS, exit->src, bb_ld)))
+       return false;
     }
 
   if (single_st)
@@ -1603,6 +1612,12 @@ find_single_drs (class loop *loop, struct graph *rdg, const bitmap &partition_st
       bb_st = gimple_bb (DR_STMT (single_st));
       if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb_st))
        return false;
+
+      /* And before exiting the loop.  */
+      if (bb_st != loop->header
+         && (!exit
+             || !dominated_by_p (CDI_DOMINATORS, exit->src, bb_st)))
+       return false;
     }
 
   if (single_ld && single_st)