Patchwork [Cilkplus] Continue inside cilk_for

login
register
mail settings
Submitter Iyer, Balaji V
Date June 21, 2012, 11:06 p.m.
Message ID <BF230D13CA30DD48930C31D4099330000F276CC4@FMSMSX102.amr.corp.intel.com>
Download mbox | patch
Permalink /patch/166439/
State New
Headers show

Comments

Iyer, Balaji V - June 21, 2012, 11:06 p.m.
Hello Everyone,
	This patch is for the Cilkplus branch affecting mainly the C++ compiler. This compiler was crashing when a continue was inside a cilk_for. This patch should fix that. I have also added a couple test programs to  the testsuite.

Thanks,

Balaji V. Iyer.

Patch

diff --git a/gcc/cp/ChangeLog.cilk b/gcc/cp/ChangeLog.cilk
index 4981290..340f710 100644
--- a/gcc/cp/ChangeLog.cilk
+++ b/gcc/cp/ChangeLog.cilk
@@ -1,4 +1,14 @@ 
-2012-06-17  balaji.v.iyer  <bviyer@nhelv406>
+2012-06-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* cp-gimplify.c (cp_genericize_r): Added a check for cilk-for.
+	(genericize_cilk_for_stmt): New function.
+	* cilk.c (resolve_continue_stmts): Likewise.
+	(cp_build_cilk_for_body): Added a new label to point goto for continue
+	inside cilk_for.  Also did a walk_tree to fix up all these continues.
+	(cg_hacks): called cp_genericize to breakup all the statements inside
+	cilk-for nested function.
+
+2012-06-17  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* cilk.c (cp_build_cilk_for_body): Set CILK_FN_P field to 1.
 	(cp_make_cilk_frame): Likewise.
diff --git a/gcc/cp/cilk.c b/gcc/cp/cilk.c
index aa23bb0..c65da86 100644
--- a/gcc/cp/cilk.c
+++ b/gcc/cp/cilk.c
@@ -243,6 +243,34 @@  add_incr (tree incr)
     }
 }
 
+/* This function will be used to fixup all the continues inside a cilk_for */
+
+static tree
+resolve_continue_stmts (tree *tp, int *walk_subtrees, void *data)
+{
+  tree goto_label = NULL_TREE, goto_stmt = NULL_TREE;
+  if (!tp || *tp == NULL_TREE)
+    return NULL_TREE;
+
+  if (TREE_CODE (*tp) == CONTINUE_STMT)
+    {
+      goto_label = (tree) data;
+      goto_stmt = build1 (GOTO_EXPR, void_type_node, goto_label);
+      *tp = goto_stmt;
+      *walk_subtrees = 0;
+    }
+  else if (TREE_CODE (*tp) == FOR_STMT || TREE_CODE (*tp) == WHILE_STMT
+	   || TREE_CODE (*tp) == DO_STMT)
+    {
+      /* Inside these statements, the continue goes to a different place not
+       * end of cilk_for, you do not want to go into these trees because we
+       * will resolve those later 
+       */
+      *walk_subtrees = 0;
+    }
+      
+  return NULL_TREE;
+}
 
 /* this function will simplify the cilk loop */
 static tree
@@ -490,7 +518,8 @@  cp_build_cilk_for_body (struct cilk_for_desc *cfd)
   char *cc = NULL;
   char *dd = NULL;
   tree loop_end_comp = NULL_TREE;
-  tree c_for_loop, top_label, slab, cond_expr, mod_expr;
+  tree c_for_loop, top_label, slab, cond_expr, mod_expr, cont_lab;
+  tree continue_label;
   
   push_function_context ();
 
@@ -656,6 +685,13 @@  cp_build_cilk_for_body (struct cilk_for_desc *cfd)
   DECL_IGNORED_P (slab) = 1;
   DECL_CONTEXT (slab) = fndecl;
 
+  cont_lab = build_decl (UNKNOWN_LOCATION, LABEL_DECL, NULL_TREE,
+			 void_type_node);
+  DECL_ARTIFICIAL (cont_lab) = 0;
+  DECL_IGNORED_P (cont_lab) = 1;
+  DECL_CONTEXT (cont_lab) = fndecl;
+  continue_label = build1 (LABEL_EXPR, void_type_node, cont_lab);
+  
   mod_expr = build2 (MODIFY_EXPR, void_type_node, loop_var,
 		     build2 (PLUS_EXPR, count_type, loop_var,
 			     build_int_cst (count_type, 1)));
@@ -667,10 +703,12 @@  cp_build_cilk_for_body (struct cilk_for_desc *cfd)
 
   add_stmt (top_label);
   add_stmt (loop_body);
+  add_stmt (continue_label);
   add_stmt (mod_expr);
   add_stmt (cond_expr);
 
   pop_stmt_list (c_for_loop);
+  walk_tree (&c_for_loop, resolve_continue_stmts, (void *)cont_lab, NULL);
   add_stmt (c_for_loop);
 
   DECL_INITIAL (fndecl) = make_node (BLOCK);
@@ -1901,6 +1939,10 @@  cg_hacks (tree fndecl, bool is_nested)
   push_cfun (f);
   current_function_decl = fndecl;
 
+  /* We did not do this earlier so that we can do it here in the cilk_for
+   * nested function body */
+  cp_genericize (fndecl);
+  
   /* If this is a genuine nested function, the nested function
      handling will deal with it.  If this is not a nested function
      it must be handled now or the compiler will crash in a
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index f2390f2..30d3d43 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -314,6 +314,17 @@  genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data)
   *stmt_p = expr;
 }
 
+/* Genericize a Cilk_FOR node *STMT_P. */
+
+static void
+genericize_cilk_for_stmt (tree *stmt_p ATTRIBUTE_UNUSED, int *walk_subtrees,
+			  void *data ATTRIBUTE_UNUSED)
+{
+  /* When we have a cilk for we resolve all the internal statements such as
+   * continue, while, for etc during gimplification */
+  *walk_subtrees = 0;
+}
+
 /* Genericize a WHILE_STMT node *STMT_P.  */
 
 static void
@@ -1158,6 +1169,8 @@  cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
     gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt));
   else if (TREE_CODE (stmt) == FOR_STMT)
     genericize_for_stmt (stmt_p, walk_subtrees, data);
+  else if (TREE_CODE (stmt) == CILK_FOR_STMT)
+    genericize_cilk_for_stmt (stmt_p, walk_subtrees, data);
   else if (TREE_CODE (stmt) == WHILE_STMT)
     genericize_while_stmt (stmt_p, walk_subtrees, data);
   else if (TREE_CODE (stmt) == DO_STMT)
diff --git a/gcc/testsuite/ChangeLog.cilk b/gcc/testsuite/ChangeLog.cilk
index 19d849b..8201c37 100644
--- a/gcc/testsuite/ChangeLog.cilk
+++ b/gcc/testsuite/ChangeLog.cilk
@@ -1,3 +1,12 @@ 
+2012-06-20  Balaji V. Iyer  <balaji.v.iyer@intel.com>
+
+	* g++.dg/cilk-plus/cilk_for_cont2_inside_for.cc: New test file.
+	* g++.dg/cilk-plus/cilk_for_cont2_inside_for_tplt.cc: Likewise.
+	* g++.dg/cilk-plus/cilk_for_cont_inside_for.cc: Likewise.
+	* g++.dg/cilk-plus/cilk_for_cont_with_for.cc: Likewise.
+	* g++.dg/cilk-plus/cilk_for_cont_with_if.cc: Likewise.
+	* g++.dg/cilk-plus/cilk_for_cont_with_while.cc: Likewise.
+
 2012-06-12  Balaji V. Iyer  <balaji.v.iyer@intel.com>
 
 	* gcc.dg/cilk-plus/elem_fn_tests/test7.c: Enclosed the function inside
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont2_inside_for.cc b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont2_inside_for.cc
new file mode 100644
index 0000000..e27f348
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont2_inside_for.cc
@@ -0,0 +1,21 @@ 
+int q[10], seq[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      cilk_for(int ii=max - 1; ii>=start; ii--) 
+	{ 
+	  if (ii % 2) 
+	    continue;  /* this continue should jump to a different place than
+			  the one below */
+	  for (int jj = 0; jj < 10; jj++)  
+	    {
+	      if (seq[jj] == 5)
+		continue;
+	      else
+		seq[jj] = 2;
+	    }
+	}
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont2_inside_for_tplt.cc b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont2_inside_for_tplt.cc
new file mode 100644
index 0000000..e833039
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont2_inside_for_tplt.cc
@@ -0,0 +1,27 @@ 
+int q[10], seq[10];
+
+template <typename T>
+T my_func  (T max ,T start) 
+{   
+      cilk_for (T ii = max - 1; ii >= start; ii--) 
+	{ 
+	  if (ii % 2) 
+	    continue;  /* this continue should jump to a different place than
+			  the one below */
+	  for (int jj = 0; jj < 10; jj++)  
+	    {
+	      if (seq[jj] == 5)
+		continue;
+	      else
+		seq[jj] = 2;
+	    }
+	}
+      return 0;
+}
+
+int main (int argc, char** argv)
+{
+  my_func <int> (10, 0);
+  my_func <char> (10, 0);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_inside_for.cc b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_inside_for.cc
new file mode 100644
index 0000000..0fd6b70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_inside_for.cc
@@ -0,0 +1,18 @@ 
+int q[10], seq[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      cilk_for(int ii=max - 1; ii>=start; ii--) 
+	{ 
+	  for (int jj = 0; jj < 10; jj++)  
+	    {
+	      if (seq[jj] == 5)
+		continue;
+	      else
+		seq[jj] = 2;
+	    }
+	}
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_for.cc b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_for.cc
new file mode 100644
index 0000000..21e659b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_for.cc
@@ -0,0 +1,14 @@ 
+int q[10], seq2[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      cilk_for(int ii=max - 1; ii>=start; ii--) 
+	{ 
+	  for (int jj = 0; jj < 10; jj++) 
+	    seq2[jj] = 5;
+	  continue;
+	}
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_if.cc b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_if.cc
new file mode 100644
index 0000000..c0b8b01
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_if.cc
@@ -0,0 +1,13 @@ 
+int q[10], seq2[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      cilk_for(int ii = max - 1; ii >= start; ii--) 
+	{ 
+	  if (q[ii] != 0) 
+	    continue;
+	}
+        return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_while.cc b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_while.cc
new file mode 100644
index 0000000..35fbb1b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/cilk_for_cont_with_while.cc
@@ -0,0 +1,18 @@ 
+int q[10], seq2[10];
+int main (int argc, char** argv)
+{
+   
+    int max = 10, start = 0;
+      cilk_for(int ii=max - 1; ii>=start; ii--) 
+	{ 
+	  int jj = 0;
+	  while (jj < 10)
+	    {
+	      seq2[jj] = 1;
+	      jj++;
+	    }
+	  continue;
+	}
+        return 0;
+}
+