[PATCH][cilkplus] fix c++ implicit conversions with cilk_spawn (PR/69024, PR/68997)

Ryan Burn rnickb731@gmail.com
Wed Jan 20 17:57:00 GMT 2016


This patch follows on from
https://gcc.gnu.org/ml/gcc-patches/2015-12/msg02142.html

As discussed, it creates a separate function
cilk_cp_detect_spawn_and_unwrap in gcc/cp to handle processing
cilk_spawn expressions for c++ and adds support for implicit
constructor and type conversions.

Bootstrapped and regression tested on x86_64-linux.

gcc/c-family/ChangeLog:
2015-01-20  Ryan Burn  <contact@rnburn.com>

  PR c++/69024
  PR c++/68997
  * cilk.c (cilk_ignorable_spawn_rhs_op): Change to have external linkage.
  * cilk.c (recognize_spawn): Rename to cilk_recognize_spawn. Change to have
  external linkage.
  * cilk.c (cilk_detect_and_unwrap): Rename to recognize_spawn to
  cilk_recognize_spawn.
  * cilk.c (extract_free_variables): Don't extract free variables from
  AGGR_INIT_EXPR slot.

gcc/cp/ChangeLog
2015-01-20  Ryan Burn  <contact@rnburn.com>

  PR c++/69024
  PR c++/68997
  * cp-gimplify.c (cp_gimplify_expr): Call cilk_cp_detect_spawn_and_unwrap
  instead of cilk_detect_spawn_and_unwrap.
  * cp-cilkplus.c (is_conversion_operator_function_decl_p): New.
  * cp-cilkplus.c (find_spawn): New.
  * cp-cilkplus.c (cilk_cp_detect_spawn_and_unwrap): New.

gcc/testsuite/ChangeLog
2015-01-20  Ryan Burn  <contact@rnburn.com>

  PR c++/69024
  PR c++/68997
  * g++.dg/cilk-plus/CK/pr68001.cc: Fix to not depend on broken diagnostic.
  * g++.dg/cilk-plus/CK/pr69024.cc: New test.
  * g++.dg/cilk-plus/CK/pr68997.cc: New test.
-------------- next part --------------
Index: gcc/c-family/cilk.c
===================================================================
--- gcc/c-family/cilk.c	(revision 232444)
+++ gcc/c-family/cilk.c	(working copy)
@@ -185,7 +185,7 @@
    A comparison to constant is simple enough to allow, and
    is used to convert to bool.  */
 
-static bool
+bool
 cilk_ignorable_spawn_rhs_op (tree exp)
 {
   enum tree_code code = TREE_CODE (exp);
@@ -223,8 +223,8 @@
 /* Returns true when EXP is a CALL_EXPR with _Cilk_spawn in front.  Unwraps
    CILK_SPAWN_STMT wrapper from the CALL_EXPR in *EXP0 statement.  */
 
-static bool
-recognize_spawn (tree exp, tree *exp0)
+bool
+cilk_recognize_spawn (tree exp, tree *exp0)
 {
   bool spawn_found = false;
   if (TREE_CODE (exp) == CILK_SPAWN_STMT)
@@ -292,7 +292,7 @@
   
   /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around 
      it, or return false.  */
-  if (recognize_spawn (exp, exp0))
+  if (cilk_recognize_spawn (exp, exp0))
     return true;
   return false;
 }
@@ -1251,6 +1251,21 @@
       return;
 
     case AGGR_INIT_EXPR:
+      {
+	int len = 0;
+	int ii = 0;
+	extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ);
+	if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST)
+	  {
+	    len = TREE_INT_CST_LOW (TREE_OPERAND (t, 0));
+
+	    for (ii = 3; ii < len; ii++)
+	      extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ);
+	    extract_free_variables (TREE_TYPE (t), wd, ADD_READ);
+	  }
+	break;
+      }
+
     case CALL_EXPR:
       {
 	int len = 0;
Index: gcc/cp/cp-gimplify.c
===================================================================
--- gcc/cp/cp-gimplify.c	(revision 232444)
+++ gcc/cp/cp-gimplify.c	(working copy)
@@ -39,6 +39,7 @@
 static tree cp_fold_r (tree *, int *, void *);
 static void cp_genericize_tree (tree*);
 static tree cp_fold (tree);
+bool cilk_cp_detect_spawn_and_unwrap (tree *);
 
 /* Local declarations.  */
 
@@ -619,7 +620,7 @@
     case INIT_EXPR:
       if (fn_contains_cilk_spawn_p (cfun))
 	{
-	  if (cilk_detect_spawn_and_unwrap (expr_p))
+	  if (cilk_cp_detect_spawn_and_unwrap (expr_p))
 	    {
 	      cilk_cp_gimplify_call_params_in_spawned_fn (expr_p,
 							  pre_p, post_p);
@@ -637,7 +638,7 @@
     modify_expr_case:
       {
 	if (fn_contains_cilk_spawn_p (cfun)
-	    && cilk_detect_spawn_and_unwrap (expr_p)
+	    && cilk_cp_detect_spawn_and_unwrap (expr_p)
 	    && !seen_error ())
 	  {
 	    cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p);
@@ -738,7 +739,7 @@
 
     case CILK_SPAWN_STMT:
       gcc_assert(fn_contains_cilk_spawn_p (cfun)
-		 && cilk_detect_spawn_and_unwrap (expr_p));
+		 && cilk_cp_detect_spawn_and_unwrap (expr_p));
 
       if (!seen_error ())
 	{
@@ -749,7 +750,7 @@
 
     case CALL_EXPR:
       if (fn_contains_cilk_spawn_p (cfun)
-	  && cilk_detect_spawn_and_unwrap (expr_p)
+	  && cilk_cp_detect_spawn_and_unwrap (expr_p)
 	  && !seen_error ())
 	{
 	  cilk_cp_gimplify_call_params_in_spawned_fn (expr_p, pre_p, post_p);
Index: gcc/cp/cp-cilkplus.c
===================================================================
--- gcc/cp/cp-cilkplus.c	(revision 232444)
+++ gcc/cp/cp-cilkplus.c	(working copy)
@@ -27,6 +27,108 @@
 #include "tree-iterator.h"
 #include "cilk.h"
 
+bool cilk_ignorable_spawn_rhs_op (tree);
+bool cilk_recognize_spawn (tree, tree *);
+
+/* Return TRUE if T is a FUNCTION_DECL for a type-conversion operator.  */
+
+static bool
+is_conversion_operator_function_decl_p (tree t) {
+  if (TREE_CODE (t) != FUNCTION_DECL)
+    return false;
+
+  return DECL_NAME (t) && IDENTIFIER_TYPENAME_P (DECL_NAME (t));
+}
+
+/* Recursively traverse EXP to search for a CILK_SPAWN_STMT subtree.  Return the
+   CILK_SPAWN_STMT subtree if found; otherwise, the last subtree searched.  */
+
+static tree
+find_spawn (tree exp)
+{
+  /* Happens with C++ TARGET_EXPR.  */
+  if (exp == NULL_TREE)
+    return exp;
+
+  if (cilk_ignorable_spawn_rhs_op (exp))
+    return find_spawn (TREE_OPERAND (exp, 0));
+
+  switch (TREE_CODE (exp))
+    {
+    case AGGR_INIT_EXPR:
+      {
+	/* Check for initialization via a constructor call that represents
+	   implicit conversion.  */
+	if (AGGR_INIT_VIA_CTOR_P (exp) && aggr_init_expr_nargs (exp) == 2)
+	  return find_spawn (AGGR_INIT_EXPR_ARG (exp, 1));
+
+	/* Check for initialization via a call to a type-conversion
+	   operator.  */
+	tree fn = AGGR_INIT_EXPR_FN (exp);
+	if (TREE_CODE (fn) == ADDR_EXPR
+	    && is_conversion_operator_function_decl_p (TREE_OPERAND (fn, 0))
+	    && aggr_init_expr_nargs (exp) == 1)
+	  return find_spawn (AGGR_INIT_EXPR_ARG (exp, 0));
+      }
+      break;
+
+    case CALL_EXPR:
+      {
+	/* Check for a call to a type-conversion operator.  */
+	tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+	if (is_conversion_operator_function_decl_p (fndecl)
+	    && call_expr_nargs (exp) == 1)
+	  return find_spawn (CALL_EXPR_ARG (exp, 0));
+      }
+      break;
+
+    case TARGET_EXPR:
+      return find_spawn (TARGET_EXPR_INITIAL (exp));
+
+    case CLEANUP_POINT_EXPR:
+    case COMPOUND_EXPR:
+    case EXPR_STMT:
+      return find_spawn (TREE_OPERAND (exp, 0));
+
+    default:
+      break;
+    }
+
+    return exp;
+}
+
+/* Returns true if *EXP0 is a recognized form of spawn.  Recognized forms are,
+   after conversion to void, a call expression at outer level or an assignment
+   at outer level with the right hand side being a spawned call.
+   In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the
+   CALL_EXPR that is being spawned.
+   Note that `=' in C++ may turn into a CALL_EXPR rather than a MODIFY_EXPR.  */
+
+bool
+cilk_cp_detect_spawn_and_unwrap (tree *exp0)
+{
+  tree exp = *exp0;
+
+  if (!TREE_SIDE_EFFECTS (exp))
+    return false;
+
+  /* Strip off any conversion to void.  It does not affect whether spawn
+     is supported here.  */
+  if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp)))
+    exp = TREE_OPERAND (exp, 0);
+
+  if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR)
+    exp = TREE_OPERAND (exp, 1);
+
+  exp = find_spawn (exp);
+  if (exp == NULL_TREE)
+    return false;
+
+  /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around
+     it, or return false.  */
+  return cilk_recognize_spawn (exp, exp0);
+}
+
 /* Callback for cp_walk_tree to validate the body of a pragma simd loop
    or _cilk_for loop.
 
Index: gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc	(revision 232444)
+++ gcc/testsuite/g++.dg/cilk-plus/CK/pr68001.cc	(working copy)
@@ -11,7 +11,7 @@
 
 int main()
 {
-  std::vector<double> x = _Cilk_spawn f(); /* { dg-error "invalid use of" } */
+  std::vector<double> x = _Cilk_spawn f ();
   std::vector<double> y = f();
   _Cilk_sync;
   return 0;
Index: gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/CK/pr69024.cc	(working copy)
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+struct A1 {
+};
+
+struct A2 {
+  A2 () {}
+  A2 (const A2&) {}
+};
+
+struct B1 {
+  operator A1 () {
+    return A1 ();
+  }
+};
+
+B1 fb1 () {
+  return B1 ();
+}
+
+struct B2 {
+  operator A2 () {
+    return A2 ();
+  }
+};
+
+B2 fb2 () {
+  return B2 ();
+}
+
+void t1 () {
+  A1 a1 = _Cilk_spawn fb1 ();
+}
+
+void t2 () {
+  A2 a2 = _Cilk_spawn fb2 ();
+}
Index: gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc
===================================================================
--- gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc	(revision 0)
+++ gcc/testsuite/g++.dg/cilk-plus/CK/pr68997.cc	(working copy)
@@ -0,0 +1,68 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c++11 -fcilkplus" } */
+
+struct A1 {
+  A1 () {}
+  A1 (const A1&) {}
+};
+
+A1 fa1 () {
+  return A1 ();
+}
+
+struct A2 {
+  A2 () {}
+  A2 (A2&&) {}
+};
+
+A2 fa2 () {
+  A2 ();
+}
+
+struct B1 {
+};
+
+B1 fb1 () {
+  return B1 ();
+}
+
+struct A3 {
+  A3 (const B1&) {}
+};
+
+struct A4 {
+  A4 (B1) {}
+};
+
+struct B2 {
+  B2 () {}
+  B2 (const B2&) {}
+};
+
+B2 fb2 () {
+  return B2 ();
+}
+
+struct A5 {
+  A5 (B2) {}
+};
+
+void t1 () {
+  A1 a1 = _Cilk_spawn fa1 ();
+}
+
+void t2 () {
+  A2 a2 = _Cilk_spawn fa2 ();
+}
+
+void t3 () {
+  A3 a3 = _Cilk_spawn fb1 ();
+}
+
+void t4 () {
+  A4 a4 = _Cilk_spawn fb1 ();
+}
+
+void t5 () {
+  A5 a5 = _Cilk_spawn fb2 ();
+}


More information about the Gcc-patches mailing list