From patchwork Wed Jan 20 17:57:38 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Burn X-Patchwork-Id: 570839 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id A03F0140317 for ; Thu, 21 Jan 2016 04:57:52 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Z0Mcoadb; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; q= dns; s=default; b=yubKlSyNs8Dfl8ZlLaDgv3xjIsub0KzS2I3263QsCmKfGK 9LQz2LLhfOmdNp0knfU7a9XYJayXnWt0IDUym3S2pHcTLWXZ4XwH2vdz3XHB8Wac cOzmWm6vzy+4STtUdHs2Cenf45uFTxs3cZtkRykJ0bzCedkv4njMAwJKGmNcQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; s= default; bh=vot7ZcfmGchA7AdVy6t2X0g1HfE=; b=Z0McoadbKmpanwxuA8cP OUb8FuralKbijW7nLPvOvGsVlnfzYluPCkhDrp/mfHolVBUQwdAK8ie4wLgN/3bT zHCBP2j9quQQgQsFtaj1gX3VQrfsdAoWtAdK+NN4Slc9lFwl+2injOGoZmSv5xuQ BfWhvJRuQI0UwsloaqtrdNw= Received: (qmail 24195 invoked by alias); 20 Jan 2016 17:57:45 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 24180 invoked by uid 89); 20 Jan 2016 17:57:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 spammy=7507, cfun, fndecl, 138 X-HELO: mail-oi0-f48.google.com Received: from mail-oi0-f48.google.com (HELO mail-oi0-f48.google.com) (209.85.218.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 20 Jan 2016 17:57:41 +0000 Received: by mail-oi0-f48.google.com with SMTP id p187so10207563oia.2 for ; Wed, 20 Jan 2016 09:57:40 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to :content-type; bh=x/Eo0JwuX1hwEV+CjPxmeKtQJg3NNOJU6UVxHw7y3os=; b=TKlrmyiqCUmGINTGhLWuEqOBB8H7RRE9cSkqHhW08kBeg7RBnWPt0dLE2sCSXbjCac dksUkc58RhzlX1ZkMxPlJgh3gJMOn+wy7b3Ro+sl/3vfEs5kz0DgaUfS/8QsvuLhZua3 tIsXU2ftwSe0H3HpF47rGVnf3DE0x9e9FSxyeTZqSxb0WOdPCLJ+TSrBoaDWVWi+Ic4w Z3JgoKfCNo8cOLR194lqFcxCeK1lkefzOodYwXCPoUTSIkP5oV+re8TTxDTjho0yO+VO AuRM7vbCFRSfEiBvxqaSq/Eu72BFz/bPtjX0x56VBnerCQu+3wgL5MQFH7iTbEPkSfp4 3rMA== X-Gm-Message-State: ALoCoQlpbu0TMOYaEoagNZYvBU2+uco1ZZtqv5P7Vyn9HM4fp6J4I67rTo+p5gya6Fo4ygGWoxOql3L0uoX7qA0VwC0WQgzApg== MIME-Version: 1.0 X-Received: by 10.202.172.80 with SMTP id v77mr27811374oie.18.1453312658729; Wed, 20 Jan 2016 09:57:38 -0800 (PST) Received: by 10.202.75.147 with HTTP; Wed, 20 Jan 2016 09:57:38 -0800 (PST) Date: Wed, 20 Jan 2016 12:57:38 -0500 Message-ID: Subject: [PATCH][cilkplus] fix c++ implicit conversions with cilk_spawn (PR/69024, PR/68997) From: Ryan Burn To: gcc-patches@gcc.gnu.org, Jason Merrill , Jeff Law , igor.zamyatin@intel.com, Jakub Jelinek X-IsSubscribed: yes 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 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 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 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. 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 x = _Cilk_spawn f(); /* { dg-error "invalid use of" } */ + std::vector x = _Cilk_spawn f (); std::vector 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 (); +}