The following makes sure to hoist loop invariants after unswitching
a loop.  Invariant stmts in a loop can make vectorization less
effective and now confuse it.  While if-conversion moves invariants
already, when there's nothing to if-convert this isn't done.  This
follows what loop interchange and unroll-and-jam already do.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

On x86 this will cause

FAIL: gcc.target/i386/pr125238.c scan-assembler movabsq[\\\\t]+\\\\\$858993459
4, %r[a-z0-9]+
FAIL: gcc.target/i386/pr89523-1a.c scan-assembler addr32 vgather
FAIL: gcc.target/i386/pr89523-1b.c scan-assembler addr32 vgather

all are testisms, I have not quickly figured how to preserve what those
intended to test, but the patch will reduce the fallout from the
recent vectorizer changes, so I'll leave those for followups.

        PR tree-optimization/126997
        * tree-ssa-loop-unswitch.cc (tree_ssa_unswitch_loops):
        Perform invariant motion when we unswitched a loop.

        * gcc.dg/torture/pr126997.c: New testcase.
---
 gcc/testsuite/gcc.dg/torture/pr126997.c | 10 ++++++++++
 gcc/tree-ssa-loop-unswitch.cc           |  6 +++++-
 2 files changed, 15 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr126997.c

diff --git a/gcc/testsuite/gcc.dg/torture/pr126997.c 
b/gcc/testsuite/gcc.dg/torture/pr126997.c
new file mode 100644
index 00000000000..5a2d7ab2d0b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr126997.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+unsigned short
+f (unsigned int hl, unsigned int scheme, unsigned int n)
+{
+  unsigned short tot = 0;
+  for (unsigned short i = 0; i < n; i++)
+    tot += hl == 1 ? (scheme != 0) : (i == 0);
+  return tot;
+}
diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
index 6b3c8c4a291..e1650c1f9ae 100644
--- a/gcc/tree-ssa-loop-unswitch.cc
+++ b/gcc/tree-ssa-loop-unswitch.cc
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-range.h"
 #include "dbgcnt.h"
 #include "cfganal.h"
+#include "tree-cfgcleanup.h"
 
 /* This file implements the loop unswitching, i.e. transformation of loops like
 
@@ -452,7 +453,10 @@ tree_ssa_unswitch_loops (function *fun)
     clean_up_after_unswitching (ignored_edge_flag);
 
   if (changed_unswitch || changed_hoist)
-    return TODO_cleanup_cfg;
+    cleanup_tree_cfg ();
+
+  if (changed_unswitch)
+    return loop_invariant_motion_in_fun (cfun, false);
 
   return 0;
 }
-- 
2.51.0

Reply via email to