This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR87873


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 <rguenther@suse.de>
Date: Mon, 5 Nov 2018 13:02:48 +0100
Subject: [PATCH] fix-pr87873

2018-11-05  Richard Biener  <rguenther@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");
     }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]