From patchwork Fri Mar 15 16:27:38 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 228087 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]) by ozlabs.org (Postfix) with SMTP id D8BA22C00BE for ; Sat, 16 Mar 2013 03:28:05 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1363969686; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To: MIME-Version:Content-Type:Content-Disposition:User-Agent: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=r+Qb2p+gLJK66WMjhopW DUKYX6M=; b=Fs3nybcToX5UWuGsfkYnfXshhT+kZ+XFbzlXYfEP8yWHRMSV3Q8H xNfofMF18zWanWRI7ajcY/x0OtNFvuKacxbXAJJgZjIhkDNmPeiadjM8te55LPUh W+Xxj+RzD8vTzPPwUepy5X+O/s64LKcVFbouXU7KdCyg1+mIauRRI7M= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:Received:Received:Received:Date:From:To:Cc:Subject:Message-ID:Reply-To:MIME-Version:Content-Type:Content-Disposition:User-Agent:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=ZjCFLXn3CK3syiY9r6pkdakGYembcqd8jpgdz2OlE9+afpqX2CH/3d97gq7vlO Q8BzdzIfHxgA5VbL9O8ZGPmgD8JK/7w7EIaPpX37Zi+edGag3q23/Nk6tpStfag4 5LUYTjC42wrdB3xm4O3lOumFGXls5E1B3ngSdpADXgP9M=; Received: (qmail 24662 invoked by alias); 15 Mar 2013 16:27:53 -0000 Received: (qmail 24650 invoked by uid 22791); 15 Mar 2013 16:27:52 -0000 X-SWARE-Spam-Status: No, hits=-7.5 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_SPAMHAUS_DROP, RCVD_IN_DNSWL_HI, RCVD_IN_HOSTKARMA_W, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_TM X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 15 Mar 2013 16:27:41 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r2FGRfAq022863 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 15 Mar 2013 12:27:41 -0400 Received: from zalov.cz (vpn1-4-107.ams2.redhat.com [10.36.4.107]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r2FGRdIO016626 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 15 Mar 2013 12:27:40 -0400 Received: from zalov.cz (localhost [127.0.0.1]) by zalov.cz (8.14.5/8.14.5) with ESMTP id r2FGRcMX031440; Fri, 15 Mar 2013 17:27:38 +0100 Received: (from jakub@localhost) by zalov.cz (8.14.5/8.14.5/Submit) id r2FGRciU031439; Fri, 15 Mar 2013 17:27:38 +0100 Date: Fri, 15 Mar 2013 17:27:38 +0100 From: Jakub Jelinek To: Jason Merrill , Richard Henderson Cc: gcc-patches@gcc.gnu.org Subject: [gomp4] C++ OpenMP 4.0 atomics support Message-ID: <20130315162738.GN12913@tucnak.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes 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 Hi! As the updated comments show, OpenMP 4.0 (rc2 so far) has added a bunch of new #pragma omp {,update,capture} forms. Here is C++ support for that, depending on http://gcc.gnu.org/ml/gcc-patches/2013-03/msg00546.html Queued for gomp-4_0-branch (to be created next week). Comments? I'm afraid C support will be harder, given the lack of tentative parsing support and no counterpart to cp_tree_equal (operand_equal_p won't do it, that one returns false on side-effects etc.). 2013-03-15 Jakub Jelinek * c-parser.c (c_parser_omp_atomic): Adjust comment. Add another argument to c_finish_omp_atomic. * parser.c (cp_parser_binary_expression): Handle no_toplevel_fold_p even for binary operations other than comparison. (cp_parser_omp_atomic): Handle parsing OpenMP 4.0 atomics. * pt.c (tsubst_expr) : Handle atomic exchange. * semantics.c (finish_omp_atomic): Use cp_tree_equal to diagnose expression mismatches and to find out if c_finish_omp_atomic should be called with swapped set to true or false. * c-omp.c (c_finish_omp_atomic): Add swapped argument, if true, build the operation first with rhs, lhs arguments and use NOP_EXPR build_modify_expr. * c-common.h (c_finish_omp_atomic): Adjust prototype. * c-c++-common/gomp/atomic-15.c: Remove error test that is now valid in OpenMP 4.0. * testsuite/libgomp.c++/atomic-10.C: New test. * testsuite/libgomp.c++/atomic-11.C: New test. * testsuite/libgomp.c++/atomic-12.C: New test. * testsuite/libgomp.c++/atomic-13.C: New test. Jakub --- gcc/c/c-parser.c.jj 2013-02-13 09:29:17.000000000 +0100 +++ gcc/c/c-parser.c 2013-03-15 14:40:29.145039411 +0100 @@ -9500,10 +9500,18 @@ c_parser_omp_structured_block (c_parser update-stmt: expression-stmt | x = x binop expr capture-stmt: - v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x + v = expression-stmt capture-block: { v = x; update-stmt; } | { update-stmt; v = x; } + OpenMP 4.0: + update-stmt: + expression-stmt | x = x binop expr | x = expr binop x + capture-stmt: + v = update-stmt + capture-block: + { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; } + where x and v are lvalue expressions with scalar type. LOC is the location of the #pragma token. */ @@ -9826,7 +9834,8 @@ stmt_done: c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"); } done: - stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1); + stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, + false); if (stmt != error_mark_node) add_stmt (stmt); --- gcc/cp/parser.c.jj 2013-03-07 15:32:40.000000000 +0100 +++ gcc/cp/parser.c 2013-03-15 14:20:15.361064904 +0100 @@ -7471,9 +7471,11 @@ cp_parser_binary_expression (cp_parser* */ if (no_toplevel_fold_p && lookahead_prec <= current.prec - && sp == stack - && TREE_CODE_CLASS (current.tree_type) == tcc_comparison) - current.lhs = build2 (current.tree_type, boolean_type_node, + && sp == stack) + current.lhs = build2 (current.tree_type, + TREE_CODE_CLASS (current.tree_type) + == tcc_comparison + ? boolean_type_node : TREE_TYPE (current.lhs), current.lhs, rhs); else current.lhs = build_x_binary_op (current.loc, current.tree_type, @@ -26426,10 +26428,18 @@ cp_parser_omp_structured_block (cp_parse update-stmt: expression-stmt | x = x binop expr capture-stmt: - v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x + v = expression-stmt capture-block: { v = x; update-stmt; } | { update-stmt; v = x; } + OpenMP 4.0: + update-stmt: + expression-stmt | x = x binop expr | x = expr binop x + capture-stmt: + v = update-stmt + capture-block: + { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; } + where x and v are lvalue expressions with scalar type. */ static void @@ -26596,75 +26606,139 @@ restart: opcode = BIT_XOR_EXPR; break; case CPP_EQ: - if (structured_block || code == OMP_ATOMIC) + enum cp_parser_prec oprec; + cp_token *token; + cp_lexer_consume_token (parser->lexer); + cp_parser_parse_tentatively (parser); + rhs1 = cp_parser_simple_cast_expression (parser); + if (rhs1 == error_mark_node) { - enum cp_parser_prec oprec; - cp_token *token; - cp_lexer_consume_token (parser->lexer); - rhs1 = cp_parser_unary_expression (parser, /*address_p=*/false, - /*cast_p=*/false, NULL); - if (rhs1 == error_mark_node) - goto saw_error; - token = cp_lexer_peek_token (parser->lexer); - switch (token->type) + cp_parser_abort_tentative_parse (parser); + cp_parser_simple_cast_expression (parser); + goto saw_error; + } + token = cp_lexer_peek_token (parser->lexer); + if (token->type != CPP_SEMICOLON && !cp_tree_equal (lhs, rhs1)) + { + cp_parser_abort_tentative_parse (parser); + cp_parser_parse_tentatively (parser); + rhs = cp_parser_binary_expression (parser, false, true, + PREC_NOT_OPERATOR, NULL); + if (rhs == error_mark_node) + { + cp_parser_abort_tentative_parse (parser); + cp_parser_binary_expression (parser, false, true, + PREC_NOT_OPERATOR, NULL); + goto saw_error; + } + switch (TREE_CODE (rhs)) { - case CPP_SEMICOLON: - if (code == OMP_ATOMIC_CAPTURE_NEW) + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case PLUS_EXPR: + case MINUS_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case BIT_AND_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + if (cp_tree_equal (lhs, TREE_OPERAND (rhs, 1))) { - code = OMP_ATOMIC_CAPTURE_OLD; - v = lhs; - lhs = NULL_TREE; - lhs1 = rhs1; - rhs1 = NULL_TREE; - cp_lexer_consume_token (parser->lexer); - goto restart; + if (cp_parser_parse_definitely (parser)) + { + opcode = TREE_CODE (rhs); + rhs1 = TREE_OPERAND (rhs, 0); + rhs = TREE_OPERAND (rhs, 1); + goto stmt_done; + } + else + goto saw_error; } - cp_parser_error (parser, - "invalid form of %<#pragma omp atomic%>"); - goto saw_error; - case CPP_MULT: - opcode = MULT_EXPR; - break; - case CPP_DIV: - opcode = TRUNC_DIV_EXPR; - break; - case CPP_PLUS: - opcode = PLUS_EXPR; - break; - case CPP_MINUS: - opcode = MINUS_EXPR; - break; - case CPP_LSHIFT: - opcode = LSHIFT_EXPR; - break; - case CPP_RSHIFT: - opcode = RSHIFT_EXPR; - break; - case CPP_AND: - opcode = BIT_AND_EXPR; - break; - case CPP_OR: - opcode = BIT_IOR_EXPR; - break; - case CPP_XOR: - opcode = BIT_XOR_EXPR; break; default: - cp_parser_error (parser, - "invalid operator for %<#pragma omp atomic%>"); - goto saw_error; + break; } - oprec = TOKEN_PRECEDENCE (token); - gcc_assert (oprec != PREC_NOT_OPERATOR); - if (commutative_tree_code (opcode)) - oprec = (enum cp_parser_prec) (oprec - 1); - cp_lexer_consume_token (parser->lexer); - rhs = cp_parser_binary_expression (parser, false, false, - oprec, NULL); - if (rhs == error_mark_node) - goto saw_error; - goto stmt_done; + cp_parser_abort_tentative_parse (parser); + if (structured_block && code == OMP_ATOMIC_CAPTURE_OLD) + { + rhs = cp_parser_expression (parser, /*cast_p=*/false, NULL); + if (rhs == error_mark_node) + goto saw_error; + opcode = NOP_EXPR; + rhs1 = NULL_TREE; + goto stmt_done; + } + cp_parser_error (parser, + "invalid form of %<#pragma omp atomic%>"); + goto saw_error; + } + if (!cp_parser_parse_definitely (parser)) + goto saw_error; + switch (token->type) + { + case CPP_SEMICOLON: + if (code == OMP_ATOMIC_CAPTURE_NEW) + { + code = OMP_ATOMIC_CAPTURE_OLD; + v = lhs; + lhs = NULL_TREE; + lhs1 = rhs1; + rhs1 = NULL_TREE; + cp_lexer_consume_token (parser->lexer); + goto restart; + } + else if (structured_block) + { + opcode = NOP_EXPR; + rhs = rhs1; + rhs1 = NULL_TREE; + goto stmt_done; + } + cp_parser_error (parser, + "invalid form of %<#pragma omp atomic%>"); + goto saw_error; + case CPP_MULT: + opcode = MULT_EXPR; + break; + case CPP_DIV: + opcode = TRUNC_DIV_EXPR; + break; + case CPP_PLUS: + opcode = PLUS_EXPR; + break; + case CPP_MINUS: + opcode = MINUS_EXPR; + break; + case CPP_LSHIFT: + opcode = LSHIFT_EXPR; + break; + case CPP_RSHIFT: + opcode = RSHIFT_EXPR; + break; + case CPP_AND: + opcode = BIT_AND_EXPR; + break; + case CPP_OR: + opcode = BIT_IOR_EXPR; + break; + case CPP_XOR: + opcode = BIT_XOR_EXPR; + break; + default: + cp_parser_error (parser, + "invalid operator for %<#pragma omp atomic%>"); + goto saw_error; } + oprec = TOKEN_PRECEDENCE (token); + gcc_assert (oprec != PREC_NOT_OPERATOR); + if (commutative_tree_code (opcode)) + oprec = (enum cp_parser_prec) (oprec - 1); + cp_lexer_consume_token (parser->lexer); + rhs = cp_parser_binary_expression (parser, false, false, + oprec, NULL); + if (rhs == error_mark_node) + goto saw_error; + goto stmt_done; /* FALLTHROUGH */ default: cp_parser_error (parser, --- gcc/cp/pt.c.jj 2013-02-27 22:32:13.000000000 +0100 +++ gcc/cp/pt.c 2013-03-15 16:53:03.047114106 +0100 @@ -13268,6 +13268,8 @@ tsubst_expr (tree t, tree args, tsubst_f lhs = RECUR (TREE_OPERAND (op11, 0)); rhs = RECUR (TREE_OPERAND (op11, 1)); opcode = TREE_CODE (op11); + if (opcode == MODIFY_EXPR) + opcode = NOP_EXPR; } else { --- gcc/cp/semantics.c.jj 2013-03-12 09:59:36.000000000 +0100 +++ gcc/cp/semantics.c 2013-03-15 15:13:18.410956888 +0100 @@ -5009,8 +5009,36 @@ finish_omp_atomic (enum tree_code code, } if (!dependent_p) { + bool swapped = false; + if (rhs1 && cp_tree_equal (lhs, rhs)) + { + tree tem = rhs; + rhs = rhs1; + rhs1 = tem; + swapped = !commutative_tree_code (opcode); + } + if (rhs1 && !cp_tree_equal (lhs, rhs1)) + { + if (code == OMP_ATOMIC) + error ("%<#pragma omp atomic update%> uses two different " + "expressions for memory"); + else + error ("%<#pragma omp atomic capture%> uses two different " + "expressions for memory"); + return; + } + if (lhs1 && !cp_tree_equal (lhs, lhs1)) + { + if (code == OMP_ATOMIC) + error ("%<#pragma omp atomic update%> uses two different " + "expressions for memory"); + else + error ("%<#pragma omp atomic capture%> uses two different " + "expressions for memory"); + return; + } stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs, - v, lhs1, rhs1); + v, lhs1, rhs1, swapped); if (stmt == error_mark_node) return; } --- gcc/c-family/c-omp.c.jj 2013-02-13 17:05:52.000000000 +0100 +++ gcc/c-family/c-omp.c 2013-03-15 15:27:13.938149171 +0100 @@ -122,7 +122,7 @@ c_finish_omp_taskyield (location_t loc) tree c_finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, tree lhs, tree rhs, - tree v, tree lhs1, tree rhs1) + tree v, tree lhs1, tree rhs1, bool swapped) { tree x, type, addr; @@ -176,8 +176,12 @@ c_finish_omp_atomic (location_t loc, enu /* There are lots of warnings, errors, and conversions that need to happen in the course of interpreting a statement. Use the normal mechanisms to do this, and then take it apart again. */ - x = build_modify_expr (input_location, lhs, NULL_TREE, opcode, - input_location, rhs, NULL_TREE); + if (swapped) + { + rhs = build2_loc (loc, opcode, TREE_TYPE (lhs), rhs, lhs); + opcode = NOP_EXPR; + } + x = build_modify_expr (loc, lhs, NULL_TREE, opcode, loc, rhs, NULL_TREE); if (x == error_mark_node) return error_mark_node; gcc_assert (TREE_CODE (x) == MODIFY_EXPR); --- gcc/c-family/c-common.h.jj 2013-02-13 23:48:14.000000000 +0100 +++ gcc/c-family/c-common.h 2013-03-15 14:55:47.394049396 +0100 @@ -1035,7 +1035,7 @@ extern tree c_finish_omp_critical (locat extern tree c_finish_omp_ordered (location_t, tree); extern void c_finish_omp_barrier (location_t); extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code, - tree, tree, tree, tree, tree); + tree, tree, tree, tree, tree, bool); extern void c_finish_omp_flush (location_t); extern void c_finish_omp_taskwait (location_t); extern void c_finish_omp_taskyield (location_t); --- gcc/testsuite/c-c++-common/gomp/atomic-15.c.jj 2011-11-07 12:40:45.000000000 +0100 +++ gcc/testsuite/c-c++-common/gomp/atomic-15.c 2013-03-15 11:35:26.030192060 +0100 @@ -20,8 +20,6 @@ main () #pragma omp atomic x = x / 7 / 2; /* { dg-error "expected" } */ #pragma omp atomic capture - v = x = x | 6; /* { dg-error "invalid operator" } */ - #pragma omp atomic capture { v = x; x = x * 7 + 6; } /* { dg-error "expected" } */ #pragma omp atomic capture { v = x; x = x * 7 ^ 6; } /* { dg-error "expected" } */ --- libgomp/testsuite/libgomp.c++/atomic-10.C.jj 2013-03-15 12:33:27.115827431 +0100 +++ libgomp/testsuite/libgomp.c++/atomic-10.C 2013-03-15 15:58:52.751175890 +0100 @@ -0,0 +1,99 @@ +// { dg-do run } + +extern "C" void abort (void); +int x = 6; + +int +main () +{ + int v, l = 2, s = 1; + #pragma omp atomic + x = -3 + x; + #pragma omp atomic read + v = x; + if (v != 3) + abort (); + #pragma omp atomic update + x = 3 * 2 * 1 + x; + #pragma omp atomic read + v = x; + if (v != 9) + abort (); + #pragma omp atomic capture + v = x = x | 16; + if (v != 25) + abort (); + #pragma omp atomic capture + v = x = x + 14 * 2 / 4; + if (v != 32) + abort (); + #pragma omp atomic capture + v = x = 5 | x; + if (v != 37) + abort (); + #pragma omp atomic capture + v = x = 40 + 12 - 2 - 7 - x; + if (v != 6) + abort (); + #pragma omp atomic read + v = x; + if (v != 6) + abort (); + #pragma omp atomic capture + { v = x; x = 3 + x; } + if (v != 6) + abort (); + #pragma omp atomic capture + { v = x; x = -1 * -1 * -1 * -1 - x; } + if (v != 9) + abort (); + #pragma omp atomic read + v = x; + if (v != -8) + abort (); + #pragma omp atomic capture + { x = 2 * 2 - x; v = x; } + if (v != 12) + abort (); + #pragma omp atomic capture + { x = 7 & x; v = x; } + if (v != 4) + abort (); + #pragma omp atomic capture + { v = x; x = 6; } + if (v != 4) + abort (); + #pragma omp atomic read + v = x; + if (v != 6) + abort (); + #pragma omp atomic capture + { v = x; x = 7 * 8 + 23; } + if (v != 6) + abort (); + #pragma omp atomic read + v = x; + if (v != 79) + abort (); + #pragma omp atomic capture + { v = x; x = 23 + 6 * 4; } + if (v != 79) + abort (); + #pragma omp atomic read + v = x; + if (v != 47) + abort (); + #pragma omp atomic capture + { v = x; x = l ? 17 : 12; } + if (v != 47) + abort (); + #pragma omp atomic capture + { v = x; x = l = s++ + 3; } + if (v != 17 || l != 4 || s != 2) + abort (); + #pragma omp atomic read + v = x; + if (v != 4) + abort (); + return 0; +} --- libgomp/testsuite/libgomp.c++/atomic-11.C.jj 2013-03-15 15:57:41.557587843 +0100 +++ libgomp/testsuite/libgomp.c++/atomic-11.C 2013-03-15 15:59:51.916833343 +0100 @@ -0,0 +1,108 @@ +// { dg-do run } + +extern "C" void abort (void); + +template +void +foo () +{ + extern T x; + T v, l = 2, s = 1; + #pragma omp atomic + x = -3 + x; + #pragma omp atomic read + v = x; + if (v != 3) + abort (); + #pragma omp atomic update + x = 3 * 2 * 1 + x; + #pragma omp atomic read + v = x; + if (v != 9) + abort (); + #pragma omp atomic capture + v = x = x | 16; + if (v != 25) + abort (); + #pragma omp atomic capture + v = x = x + 14 * 2 / 4; + if (v != 32) + abort (); + #pragma omp atomic capture + v = x = 5 | x; + if (v != 37) + abort (); + #pragma omp atomic capture + v = x = 40 + 12 - 2 - 7 - x; + if (v != 6) + abort (); + #pragma omp atomic read + v = x; + if (v != 6) + abort (); + #pragma omp atomic capture + { v = x; x = 3 + x; } + if (v != 6) + abort (); + #pragma omp atomic capture + { v = x; x = -1 * -1 * -1 * -1 - x; } + if (v != 9) + abort (); + #pragma omp atomic read + v = x; + if (v != -8) + abort (); + #pragma omp atomic capture + { x = 2 * 2 - x; v = x; } + if (v != 12) + abort (); + #pragma omp atomic capture + { x = 7 & x; v = x; } + if (v != 4) + abort (); + #pragma omp atomic capture + { v = x; x = 6; } + if (v != 4) + abort (); + #pragma omp atomic read + v = x; + if (v != 6) + abort (); + #pragma omp atomic capture + { v = x; x = 7 * 8 + 23; } + if (v != 6) + abort (); + #pragma omp atomic read + v = x; + if (v != 79) + abort (); + #pragma omp atomic capture + { v = x; x = 23 + 6 * 4; } + if (v != 79) + abort (); + #pragma omp atomic read + v = x; + if (v != 47) + abort (); + #pragma omp atomic capture + { v = x; x = l ? 17 : 12; } + if (v != 47) + abort (); + #pragma omp atomic capture + { v = x; x = l = s++ + 3; } + if (v != 17 || l != 4 || s != 2) + abort (); + #pragma omp atomic read + v = x; + if (v != 4) + abort (); +} + +int x = 6; + +int +main () +{ + foo (); + return 0; +} --- libgomp/testsuite/libgomp.c++/atomic-12.C.jj 2013-03-15 16:03:22.572614293 +0100 +++ libgomp/testsuite/libgomp.c++/atomic-12.C 2013-03-15 16:30:56.801464851 +0100 @@ -0,0 +1,58 @@ +// { dg-do run } + +extern "C" void abort (); +int x = 6, cnt; + +int +foo () +{ + return cnt++; +} + +int +main () +{ + int v, *p; + p = &x; + #pragma omp atomic update + p[foo (), 0] = 16 + 6 - p[foo (), 0]; + #pragma omp atomic read + v = x; + if (cnt != 2 || v != 16) + abort (); + #pragma omp atomic capture + v = p[foo () + foo (), 0] = p[foo () + foo (), 0] + 3; + if (cnt != 6 || v != 19) + abort (); + #pragma omp atomic capture + v = p[foo (), 0] = 12 * 1 / 2 + (foo (), 0) + p[foo (), 0]; + if (cnt != 9 || v != 25) + abort (); + #pragma omp atomic capture + { + v = p[foo () & 0]; p[foo () & 0] = (foo (), 1) * 9 - p[foo () & 0]; + } + if (cnt != 13 || v != 25) + abort (); + #pragma omp atomic read + v = x; + if (v != -16) + abort (); + #pragma omp atomic capture + { + p[0 & foo ()] = 16 - 2 + 3 + p[0 & foo ()]; v = p[0 & foo ()]; + } + if (cnt != 16 || v != 1) + abort (); + #pragma omp atomic capture + { + v = p[foo (), 0]; p[foo (), 0] = (foo (), 7) ? 13 : foo () + 6; + } + if (cnt != 19 || v != 1) + abort (); + #pragma omp atomic read + v = x; + if (v != 13) + abort (); + return 0; +} --- libgomp/testsuite/libgomp.c++/atomic-13.C.jj 2013-03-15 16:31:29.522285808 +0100 +++ libgomp/testsuite/libgomp.c++/atomic-13.C 2013-03-15 16:50:41.906915812 +0100 @@ -0,0 +1,68 @@ +// { dg-do run } + +extern "C" void abort (); +int cnt; + +int +foo () +{ + return cnt++; +} + +template +void +bar () +{ + extern T x; + T v, *p; + p = &x; + #pragma omp atomic update + p[foo (), 0] = 16 + 6 - p[foo (), 0]; + #pragma omp atomic read + v = x; + if (cnt != 2 || v != 16) + abort (); + #pragma omp atomic capture + v = p[foo () + foo (), 0] = p[foo () + foo (), 0] + 3; + if (cnt != 6 || v != 19) + abort (); + #pragma omp atomic capture + v = p[foo (), 0] = 12 * 1 / 2 + (foo (), 0) + p[foo (), 0]; + if (cnt != 9 || v != 25) + abort (); + #pragma omp atomic capture + { + v = p[foo () & 0]; p[foo () & 0] = (foo (), 1) * 9 - p[foo () & 0]; + } + if (cnt != 13 || v != 25) + abort (); + #pragma omp atomic read + v = x; + if (v != -16) + abort (); + #pragma omp atomic capture + { + p[0 & foo ()] = 16 - 2 + 3 + p[0 & foo ()]; v = p[0 & foo ()]; + } + if (cnt != 16 || v != 1) + abort (); + #pragma omp atomic capture + { + v = p[foo (), 0]; p[foo (), 0] = (foo (), 7) ? 13 : foo () + 6; + } + if (cnt != 19 || v != 1) + abort (); + #pragma omp atomic read + v = x; + if (v != 13) + abort (); +} + +int x = 6; + +int +main () +{ + bar (); + return 0; +}