The fragile PHI copying logic in the vectorizer got confused by constants in loop-closed PHI nodes. Fixed like the following.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. >From a965417cbefd54f45ac6f2b6e3d5dc39c307da09 Mon Sep 17 00:00:00 2001 From: Richard Guenther <rguent...@suse.de> Date: Mon, 5 Nov 2018 13:02:48 +0100 Subject: [PATCH] fix-pr87873 2018-11-05 Richard Biener <rguent...@suse.de> PR tree-optimization/87873 * tree-ssa-loop-manip.h (split_loop_exit_edge): Add copy_constants_p argument. * tree-ssa-loop-manip.c (split_loop_exit_edge): Likewise. * tree-vect-loop.c (vect_transform_loop): When splitting the loop exit also create forwarder PHIs for constants. * tree-vect-loop-manip.c (slpeel_duplicate_current_defs_from_edges): Handle constant to_arg, add extra checking we match up the correct PHIs. * gcc.dg/pr87873.c: New testcase. diff --git a/gcc/testsuite/gcc.dg/pr87873.c b/gcc/testsuite/gcc.dg/pr87873.c new file mode 100644 index 00000000000..63d05342b40 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr87873.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ftree-loop-vectorize" } */ + +long k3; +int gs; + +void +s2 (int aj) +{ + while (aj < 1) + { + gs ^= 1; + k3 = (long) gs * 2; + if (k3 != 0) + k3 = 0; + + ++aj; + } +} diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index 5acee6c98f3..726590ac6df 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -773,10 +773,12 @@ verify_loop_closed_ssa (bool verify_ssa_p, struct loop *loop) } /* Split loop exit edge EXIT. The things are a bit complicated by a need to - preserve the loop closed ssa form. The newly created block is returned. */ + preserve the loop closed ssa form. If COPY_CONSTANTS_P is true then + forwarder PHIs are also created for constant arguments. + The newly created block is returned. */ basic_block -split_loop_exit_edge (edge exit) +split_loop_exit_edge (edge exit, bool copy_constants_p) { basic_block dest = exit->dest; basic_block bb = split_edge (exit); @@ -796,12 +798,13 @@ split_loop_exit_edge (edge exit) /* If the argument of the PHI node is a constant, we do not need to keep it inside loop. */ - if (TREE_CODE (name) != SSA_NAME) + if (TREE_CODE (name) != SSA_NAME + && !copy_constants_p) continue; /* Otherwise create an auxiliary phi node that will copy the value of the SSA name out of the loop. */ - new_name = duplicate_ssa_name (name, NULL); + new_name = duplicate_ssa_name (PHI_RESULT (phi), NULL); new_phi = create_phi_node (new_name, bb); add_phi_arg (new_phi, name, exit, locus); SET_USE (op_p, new_name); diff --git a/gcc/tree-ssa-loop-manip.h b/gcc/tree-ssa-loop-manip.h index 390ac6f8278..ddda5cf7515 100644 --- a/gcc/tree-ssa-loop-manip.h +++ b/gcc/tree-ssa-loop-manip.h @@ -37,7 +37,7 @@ checking_verify_loop_closed_ssa (bool verify_ssa_p, struct loop *loop = NULL) verify_loop_closed_ssa (verify_ssa_p, loop); } -extern basic_block split_loop_exit_edge (edge); +extern basic_block split_loop_exit_edge (edge, bool = false); extern basic_block ip_end_pos (struct loop *); extern basic_block ip_normal_pos (struct loop *); extern void standard_iv_increment_position (struct loop *, diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index 1d1d1147696..f1b023b4e4e 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -977,10 +977,15 @@ slpeel_duplicate_current_defs_from_edges (edge from, edge to) } if (TREE_CODE (from_arg) != SSA_NAME) gcc_assert (operand_equal_p (from_arg, to_arg, 0)); - else + else if (TREE_CODE (to_arg) == SSA_NAME) { if (get_current_def (to_arg) == NULL_TREE) - set_current_def (to_arg, get_current_def (from_arg)); + { + gcc_assert (types_compatible_p (TREE_TYPE (to_arg), + TREE_TYPE (get_current_def + (from_arg)))); + set_current_def (to_arg, get_current_def (from_arg)); + } } gsi_next (&gsi_from); gsi_next (&gsi_to); diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 3cdf46d723c..51be405b5a0 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -8236,7 +8236,7 @@ vect_transform_loop (loop_vec_info loop_vinfo) edge e = single_exit (loop); if (! single_pred_p (e->dest)) { - split_loop_exit_edge (e); + split_loop_exit_edge (e, true); if (dump_enabled_p ()) dump_printf (MSG_NOTE, "split exit edge\n"); }