This is a respin of https://gcc.gnu.org/ml/gcc-patches/2015-05/msg02139.html .
Changes are:
* Separate the two passes by descending from a common base class, allowing
different predicates;
* Test flag_tree_vectorize, and loop-force_vectorize/dont_vectorize - this
fixes the test failing before;
* Simplify the check for code after exit edge;
* Revert unnecessary changes to pass_tree_loop_init::execute;
* Revert change to slp-perm-7 test (following fix by Marc Glisse)
Bootstrapped + check-gcc on aarch64 and x86_64 (linux).
gcc/ChangeLog:
* tree-pass.h (make_pass_ch_vect): New.
* passes.def: Add pass_ch_vect just before pass_if_conversion.
* tree-ssa-loop-ch.c (pass_ch_base, pass_ch_vect, pass_data_ch_vect,
pass_ch::process_loop_p): New.
(pass_ch): Extend pass_ch_base.
(pass_ch::execute): Move all but loop_optimizer_init/finalize to...
(pass_ch_base::execute): ...here.
gcc/testsuite/ChangeLog:
* gcc.dg/vect/vect-strided-a-u16-i4.c (main1): Narrow scope of x,y,z,w.
of unsigned
* gcc.dg/vect/vect-ifcvt-11.c: New.
diff --git a/gcc/passes.def b/gcc/passes.def
index 4690e23..5755035 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -247,6 +247,7 @@ along with GCC; see the file COPYING3. If not see
PUSH_INSERT_PASSES_WITHIN (pass_parallelize_loops)
NEXT_PASS (pass_expand_omp_ssa);
POP_INSERT_PASSES ()
+ NEXT_PASS (pass_ch_vect);
NEXT_PASS (pass_if_conversion);
/* pass_vectorize must immediately follow pass_if_conversion.
Please do not add any other passes in between. */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-11.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-11.c
new file mode 100644
index 000..7e32369
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-11.c
@@ -0,0 +1,36 @@
+/* { dg-require-effective-target vect_condition } */
+/* { dg-require-effective-target vect_int } */
+
+#include tree-vect.h
+
+#define N 16
+
+extern void abort (void);
+
+int A[N] = {36, 39, 42, 45, 43, 32, 21, 12, 23, 34, 45, 56, 67, 78, 81, 11};
+int B[N] = {144,195,210,225,172,128,105,60, 92, 136,225,280,268,390,324,55};
+
+__attribute__((noinline))
+void foo ()
+{
+ for (int i = 0; i N; i++)
+{
+ int m = (A[i] i) ? 5 : 4;
+ A[i] = A[i] * m;
+}
+}
+
+int main ()
+{
+
+ check_vect ();
+ foo ();
+ /* check results: */
+ for (int i = 0; i N; i++)
+if (A[i] != B[i])
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times vectorized 1 loops 1 vect } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i4.c b/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i4.c
index af33ed4..0be68b3 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i4.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-strided-a-u16-i4.c
@@ -21,7 +21,6 @@ main1 ()
s *ptr = arr;
s res[N];
int i;
- unsigned short x, y, z, w;
for (i = 0; i N; i++)
{
@@ -35,6 +34,7 @@ main1 ()
for (i = 0; i N; i++)
{
+ unsigned short x, y, z, w;
x = ptr-b - ptr-a;
y = ptr-d - ptr-c;
res[i].c = x + y;
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 172bd82..083e771 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -380,6 +380,7 @@ extern gimple_opt_pass *make_pass_loop_prefetch (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_iv_optimize (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_tree_loop_done (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_ch (gcc::context *ctxt);
+extern gimple_opt_pass *make_pass_ch_vect (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_ccp (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_phi_only_cprop (gcc::context *ctxt);
extern gimple_opt_pass *make_pass_build_ssa (gcc::context *ctxt);
diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c
index 6ece78b..bd409ef 100644
--- a/gcc/tree-ssa-loop-ch.c
+++ b/gcc/tree-ssa-loop-ch.c
@@ -144,6 +144,17 @@ do_while_loop_p (struct loop *loop)
namespace {
+class ch_base : public gimple_opt_pass
+{
+ protected:
+ch_base (pass_data data, gcc::context *ctxt)
+ : gimple_opt_pass (data, ctxt)
+{}
+
+ unsigned int copy_headers (function *fun);
+ virtual bool process_loop_p (struct loop *loop) = 0;
+};
+
const pass_data pass_data_ch =
{
GIMPLE_PASS, /* type */
@@ -157,21 +168,61 @@ const pass_data pass_data_ch =
0, /* todo_flags_finish */
};
-class pass_ch : public gimple_opt_pass
+/* This pass calls loop_optimizer_init before it executes,
+ and loop_optimizer_finalize after. */
+class pass_ch : public ch_base
{
public:
pass_ch (gcc::context *ctxt)
-: gimple_opt_pass (pass_data_ch, ctxt)
+: ch_base (pass_data_ch, ctxt)
{}
/* opt_pass methods: */
virtual bool gate (function *) { return flag_tree_ch != 0; }
virtual unsigned int execute (function *);
+protected:
+ /* ch_base method: */
+ virtual bool process_loop_p (struct loop *loop);
}; // class pass_ch