From patchwork Mon Feb 10 18:07:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandra Loosemore X-Patchwork-Id: 106298 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1FE403857015 for ; Mon, 10 Feb 2025 18:17:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1FE403857015 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=nY4iypeO X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-il1-x131.google.com (mail-il1-x131.google.com [IPv6:2607:f8b0:4864:20::131]) by sourceware.org (Postfix) with ESMTPS id 9CA553857038 for ; Mon, 10 Feb 2025 18:07:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9CA553857038 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9CA553857038 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::131 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210859; cv=none; b=HLH64lFDE+dBmENmFHcSAHm+GQ4w8eEpZluSQj5vJUrDEwrKoq4btAhvXXVCAcp6cDIAzjaXfXKKBnoaJS1uIpTg6y//UuCNPRS6Ive0+17hRh7KfSSE+L+Wc3/fIisLLBxH2kdbWStNVuEGP8zJ+LM/jkX+1xrRjiwQY0O17ww= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210859; c=relaxed/simple; bh=GzCdhuP6VMfXcR0qaneq0xHH6tl0E1fnvY2Dq0tjGD0=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=fhrVgBmaLvZfIijcrLl2UyFeQ07AUFH9Nx4UnCuMyTXE0/gCRUl6UG3rAzlL0HO1I3R6xdF4JypSC7OC1zanYWKlj2+nuFbEMxVXUhULtDOJZla6ZlksPvRU6ru/U16r+LDVDvhKDIDHyjUvgZre0uG3KKWdwgGBpbSZgD3B7OQ= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9CA553857038 Received: by mail-il1-x131.google.com with SMTP id e9e14a558f8ab-3d14dec3236so7439425ab.0 for ; Mon, 10 Feb 2025 10:07:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1739210858; x=1739815658; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gE1ZtwsfzLg9hp9gaUf9v9tq09FKzJQnQFs1sn2ejrE=; b=nY4iypeOIJAhJMsOyPmVEDxwy2FIXL4Fker4UrznEYKDZ1kyiASNHxHvIvS7ZP4B0k gUhrLbVGjnlvl9aLsByZJm91LmvvCLmUO3d8qsqfulRamgnz/lOEkhHC9HAALhnX+BwN rYns0D4yIT18uUlazKp2QL0owEwwsWGtGH3VDwZmt8+Ef0GxANfS8p87xG1kxkNpgEhN M/hozjdD1DXKFN8ae1BCkTl1tWLj2seguULBRmoul44cjrKY2n8QcVeLjSLwCjBcpT5m TGdFSud9BMeDxrsMsE8QQxhwyflZyFQsc2qHzDHyjuVUiXaGqKIAbyQ7j5Jsvw81aNsH O+SQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739210858; x=1739815658; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gE1ZtwsfzLg9hp9gaUf9v9tq09FKzJQnQFs1sn2ejrE=; b=iOAJKDeNbfWaxuukODpfIYQX0pzMdyz1YHhTSx3v9vgJkRoFI3QlCBDH2GL5PZLgW1 7IwhIktxSvx6DDBPfdgEARQ/XCYD56ykS4UngA/oDAV7Elz8cGhq4UEy0UyKoIyeH8oF GuI6ow9IPW8A+pbTfzs2bR+lyyuqiLwPKFeO+mWQeBVzMsG5jBK7C+cFb0xHuDZTCfVx JvvtSEgDtVnfmMnId3PQeXo9wg94cOUATrNz6krQH8h4PMiE4vwU9WlEqHDBbKKhiIlR pyNAc2dJtNjRHhCaJJpRkSjkUHHlTuokYHC8WC+bPQBHBpJGPEXp4kavArzNPCV7zStb MbsA== X-Gm-Message-State: AOJu0YyuVtx2aUiUkCrDJgjztldV7/sFiJtgwPIkBS2E+cA2jpNxjVaX 2ZHbtolDT5Oo2jROolvjvgnVTzII6u0hqnobjf/LsvF0zoopoe/T0OcWZyobcKWm2Dv39pwk/Py m X-Gm-Gg: ASbGncvLHGWCY4Y03UrlthtHeONN09ZxxFh7O6l14OYHLVGaCdVYioD/t8YOowTIweL /EIe8OVLP/h+M49CdBPdfFXrTi21ub/oO1LpMhetp+RqwxIOWzX5bshCBPqZyVJrRR2VvFF2DbB lXiUigGaBGSXMUbL2sYMWSO4enblWIjLtjJ/D51/75wDGzguQwaAuDSD9GtqkQ6h6khJYpiqlsZ tsoUGODY0xgRd0b/K0tifcAcQwOAWLvoPHUwLnUABLWHCATLjSQ734GMi9q+YkNMGoMdDPhxvrM xqaqt/wpHLP9DWvhvHqQnYH5G80= X-Google-Smtp-Source: AGHT+IGs04JPbGfPg5wbyMDBiwp/ZkALGZHyiWutPqW4SZ5M20auFQ/UE9KBZnQEY4zdn+SPV4qHZw== X-Received: by 2002:a05:6e02:1546:b0:3d0:10a6:99a3 with SMTP id e9e14a558f8ab-3d13dd4f5c5mr92216765ab.12.1739210858465; Mon, 10 Feb 2025 10:07:38 -0800 (PST) Received: from pondscum.hsd1.co.comcast.net ([2601:281:d901:97c0::af71]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-3d13d83c967sm19615365ab.45.2025.02.10.10.07.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2025 10:07:37 -0800 (PST) From: Sandra Loosemore To: gcc-patches@gcc.gnu.org Cc: jakub@redhat.com, tburnus@baylibre.com Subject: [PATCH 1/7] OpenMP: Bug fixes for comparing context selectors Date: Mon, 10 Feb 2025 11:07:19 -0700 Message-Id: <20250210180725.2076678-2-sloosemore@baylibre.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250210180725.2076678-1-sloosemore@baylibre.com> References: <20250210180725.2076678-1-sloosemore@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org gcc/ChangeLog * omp-general.cc (omp_context_selector_props_compare): Handle arbitrary expressions in the "user" and "device_num" selectors. (omp_context_selector_set_compare): Detect mismatch when one selector specifies a score and the other doesn't. --- gcc/omp-general.cc | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index 2ce79bfc9d8..0d6f02ece31 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -2350,8 +2350,26 @@ omp_context_selector_props_compare (enum omp_tss_code set, if (set == OMP_TRAIT_SET_USER && sel == OMP_TRAIT_USER_CONDITION) { - if (integer_zerop (OMP_TP_VALUE (p1)) - != integer_zerop (OMP_TP_VALUE (p2))) + /* Recognize constants that have equal truth values, + otherwise assume all expressions are unique. */ + tree v1 = OMP_TP_VALUE (p1); + tree v2 = OMP_TP_VALUE (p2); + if (TREE_CODE (v1) != INTEGER_CST + || TREE_CODE (v2) != INTEGER_CST + || integer_zerop (v1) != integer_zerop (v2)) + return 2; + break; + } + if (set == OMP_TRAIT_SET_TARGET_DEVICE + && sel == OMP_TRAIT_DEVICE_NUM) + { + /* Recognize constants that have equal values, + otherwise assume all expressions are unique. */ + tree v1 = OMP_TP_VALUE (p1); + tree v2 = OMP_TP_VALUE (p2); + if (TREE_CODE (v1) != INTEGER_CST + || TREE_CODE (v2) != INTEGER_CST + || tree_int_cst_compare (v1, v2) != 0) return 2; break; } @@ -2469,7 +2487,9 @@ omp_context_selector_set_compare (enum omp_tss_code set, tree ctx1, tree ctx2) { tree score1 = OMP_TS_SCORE (ts1); tree score2 = OMP_TS_SCORE (ts2); - if (score1 && score2 && !simple_cst_equal (score1, score2)) + if ((score1 && score2 && !simple_cst_equal (score1, score2)) + || (score1 && !score2) + || (!score1 && score2)) return 2; int r = omp_context_selector_props_compare (set, OMP_TS_CODE (ts1), From patchwork Mon Feb 10 18:07:20 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandra Loosemore X-Patchwork-Id: 106299 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9740F385772D for ; Mon, 10 Feb 2025 18:18:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9740F385772D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=fiJguyiw X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-il1-x12f.google.com (mail-il1-x12f.google.com [IPv6:2607:f8b0:4864:20::12f]) by sourceware.org (Postfix) with ESMTPS id DDEA83857003 for ; Mon, 10 Feb 2025 18:07:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org DDEA83857003 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org DDEA83857003 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::12f ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210863; cv=none; b=otz4krmtOML8ucVugF0KR7zQpFSavUBbb0Xw0YF0FbvPoA3xTbuBfZQxTsXR9yhr8oi6qfQXY1NGaRr9MlutVHvXyWYPUn48A4DOaHcSeV6sjjHLvFNrXW0azRNFewIOyy6KnXbQd2jlat5b85DZOV+UaWVALiwcbKPnT1H980s= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210863; c=relaxed/simple; bh=5z6cdyKMIljuFYZn1FZev0tdPnrKwJd//K8gk0AseMU=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=ONA3EVo48x8c0cjDb05AVq8kh2LrpN/EzXdeCBlsuzaoldvrNflBsFYfbggCNYtLOCVND7Pdl6/FZfjmdz6oU846lP65f4oiMYEZTIcZuLNAGfVhVBsaDB+BglCBSS+5MWtBrK8n10RB/Cf6qml1r8mOxYRYCGn8I2O8qxjYdY4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DDEA83857003 Received: by mail-il1-x12f.google.com with SMTP id e9e14a558f8ab-3d144f1f68bso10684865ab.3 for ; Mon, 10 Feb 2025 10:07:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1739210861; x=1739815661; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Mm+Fs2WplkqSxu0tLENdTMnRucMVPdxCKU/JIxBQvD4=; b=fiJguyiwx3zemdzFdffwA6cAMLZGr0wAln9VhS7lh00Hpen2GRdFtOrZbqkZecpUzF 0KGllGxQzeddc+jL28Gnd9ReM/DN5fsNNEjtTg/6+rkrGmh4nsKynJqd9gMs9pwIgDq/ RD2e7A7QBlfUx4Baf2XncgKmhrY+0oUv0sXhP2nTmg1eZBoWvxuwZ7K0obw95OpeHGe6 8Az4V+7QZA4IhFml8HcOmsqUPrBtYSyCySh3EMJvS3D5SV3+2qf+cEOkP39mlWgUELYs qlVTGDyat7ukmVG71txmeE7XxpQUTcNgwQV63sDcpreTFKpJvpb5pLWwsZVHGbavAXd9 Ui7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739210861; x=1739815661; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Mm+Fs2WplkqSxu0tLENdTMnRucMVPdxCKU/JIxBQvD4=; b=uFgUKtGP+I5WIHpWrB6nhv1HUBMFPlMTsCTOqirywgkcxjQxdCytVLs3HLNMbbjCyk f7oxsvGMCtEwoZ2goReC+tGLFxce7rMFZoUuKfQzd/p5kPclpyuNWxQb+mUwI7Ehj8vl pznSemFae1GUuM7wSpkrguROrQq4hzmekaYbGNKmrDplS2AQA4SWgFm/KZb2rmRWD8nT n5XVdQRfRZV2Oso+NEHu7o5yuka9nW+Q32Yy1tpWCpleLF5Vljym/96p8LW4YU6rhQlB MkmJlHsoqJtovA9AjZdVmG/XaaorfxKNhtbMVr1bPJfWrDXafVnlf8cQVuQ7JYF4O39c K4bw== X-Gm-Message-State: AOJu0YwhhKrI1M6S8eA7kPPDBUhZ6XOBQvYnDnsHJZ1S0lU1oFjzfLYw yBj8C5E8pWlG9Q+Q7C2Tz7s00CQNvZ/cRml/uwdaOzzHcsAZNV4URQgZ2XpQBXIFGS+wEg2xe3P b X-Gm-Gg: ASbGncuOl5sVBLZC1mHLrz2U9GLvuFmsLcADMsc72qEL9kmgIOdV3X43n0QZjhHspd1 q/FYkb+netPzjRKxCfSCr9phkeXCZ/SNcBk5UTZRlF/tXluVWugiRAxhp03DbPzAOF87xkxejBW E0YvhPf4s1X2kNf3LRu/YByDCqWtL+jhVzECu75ju6crJog2zIy4pXg/19HuQKw5cLNAI3Xz365 Bo5Z2a0M1SNOPnN2g3J8tXZzytfyBVJcAdeYq/MCyu9tdrfWwli8r8+/Lky8OmZczSmQxA+WRuI qddoTI6YIu/jLmsnST8qHJpoBvA= X-Google-Smtp-Source: AGHT+IHVZqEHTquT0Dom/JoAAKtNyD/bk6J/254OHlOFLQQjV7+VjGl9z/00NdujQSdMixMvCHYC9g== X-Received: by 2002:a05:6e02:3b84:b0:3d0:1ee6:731b with SMTP id e9e14a558f8ab-3d13df00890mr131974195ab.15.1739210861092; Mon, 10 Feb 2025 10:07:41 -0800 (PST) Received: from pondscum.hsd1.co.comcast.net ([2601:281:d901:97c0::af71]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-3d13d83c967sm19615365ab.45.2025.02.10.10.07.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2025 10:07:39 -0800 (PST) From: Sandra Loosemore To: gcc-patches@gcc.gnu.org Cc: jakub@redhat.com, tburnus@baylibre.com Subject: [PATCH 2/7] OpenMP: Pass a 3-way flag to omp_check_context_selector instead of a bool. Date: Mon, 10 Feb 2025 11:07:20 -0700 Message-Id: <20250210180725.2076678-3-sloosemore@baylibre.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250210180725.2076678-1-sloosemore@baylibre.com> References: <20250210180725.2076678-1-sloosemore@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org The OpenMP "begin declare variant" directive has slightly different requirements for context selectors than regular "declare variant", so something more than a bool is required to tell the error-checking routine what to check. gcc/ChangeLog * omp-general.cc (omp_check_context_selector): Change metadirective_p argument to a 3-way flag. Add extra check for OMP_CTX_BEGIN_DECLARE_VARIANT. * omp-general.h (enum omp_ctx_directive): New. (omp_check_context_selector): Adjust declaration. gcc/c/ChangeLog * c-parser.cc (c_finish_omp_declare_variant): Update call to omp_check_context_selector. (c_parser_omp_metadirective): Likewise. gcc/cp/ChangeLog * parser.cc (cp_finish_omp_declare_variant): Update call to omp_check_context_selector. (cp_parser_omp_metadirective): Likewise. gcc/fortran/ChangeLog * trans-openmp.cc (gfc_trans_omp_declare_variant): Update call to omp_check_context_selector. (gfc_trans_omp_metadirective): Likewise. --- gcc/c/c-parser.cc | 6 ++++-- gcc/cp/parser.cc | 6 ++++-- gcc/fortran/trans-openmp.cc | 5 +++-- gcc/omp-general.cc | 18 +++++++++++++++--- gcc/omp-general.h | 6 +++++- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 106a5b48093..62c6bc031d6 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -26982,7 +26982,8 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) ctx = c_parser_omp_context_selector_specification (parser, parms); if (ctx == error_mark_node) goto fail; - ctx = omp_check_context_selector (match_loc, ctx, false); + ctx = omp_check_context_selector (match_loc, ctx, + OMP_CTX_DECLARE_VARIANT); if (ctx != error_mark_node && variant != error_mark_node) { if (TREE_CODE (variant) != FUNCTION_DECL) @@ -29099,7 +29100,8 @@ c_parser_omp_metadirective (c_parser *parser, bool *if_p) NULL_TREE); if (ctx == error_mark_node) goto error; - ctx = omp_check_context_selector (match_loc, ctx, true); + ctx = omp_check_context_selector (match_loc, ctx, + OMP_CTX_METADIRECTIVE); if (ctx == error_mark_node) goto error; diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index bd43f885ebe..9d0970b4d83 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -50437,7 +50437,8 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, ctx = cp_parser_omp_context_selector_specification (parser, true); if (ctx == error_mark_node) goto fail; - ctx = omp_check_context_selector (match_loc, ctx, false); + ctx = omp_check_context_selector (match_loc, ctx, + OMP_CTX_DECLARE_VARIANT); if (ctx != error_mark_node && variant != error_mark_node) { tree match_loc_node @@ -51424,7 +51425,8 @@ cp_parser_omp_metadirective (cp_parser *parser, cp_token *pragma_tok, ctx = cp_parser_omp_context_selector_specification (parser, false); if (ctx == error_mark_node) goto fail; - ctx = omp_check_context_selector (match_loc, ctx, true); + ctx = omp_check_context_selector (match_loc, ctx, + OMP_CTX_METADIRECTIVE); if (ctx == error_mark_node) goto fail; diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index e9103cd3bac..580d5837bd5 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -8776,7 +8776,8 @@ gfc_trans_omp_declare_variant (gfc_namespace *ns) continue; } set_selectors = omp_check_context_selector - (gfc_get_location (&odv->where), set_selectors, false); + (gfc_get_location (&odv->where), set_selectors, + OMP_CTX_DECLARE_VARIANT); if (set_selectors != error_mark_node) { if (!variant_proc_sym->attr.implicit_type @@ -9082,7 +9083,7 @@ gfc_trans_omp_metadirective (gfc_code *code) tree ctx = gfc_trans_omp_set_selector (variant->selectors, variant->where); ctx = omp_check_context_selector (gfc_get_location (&variant->where), - ctx, true); + ctx, OMP_CTX_METADIRECTIVE); if (ctx == error_mark_node) return error_mark_node; diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index 0d6f02ece31..0a2dd6b5be7 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -1302,7 +1302,8 @@ expr_uses_parm_decl (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, it is correct or error_mark_node otherwise. */ tree -omp_check_context_selector (location_t loc, tree ctx, bool metadirective_p) +omp_check_context_selector (location_t loc, tree ctx, + enum omp_ctx_directive directive) { bool tss_seen[OMP_TRAIT_SET_LAST], ts_seen[OMP_TRAIT_LAST]; @@ -1398,7 +1399,7 @@ omp_check_context_selector (location_t loc, tree ctx, bool metadirective_p) /* This restriction is documented in the spec in the section for the metadirective "when" clause (7.4.1 in the 5.2 spec). */ - if (metadirective_p + if (directive == OMP_CTX_METADIRECTIVE && ts_code == OMP_TRAIT_CONSTRUCT_SIMD && OMP_TS_PROPERTIES (ts)) { @@ -1408,10 +1409,21 @@ omp_check_context_selector (location_t loc, tree ctx, bool metadirective_p) return error_mark_node; } + /* "simd" is not allowed at all in "begin declare variant" + selectors. */ + if (directive == OMP_CTX_BEGIN_DECLARE_VARIANT + && ts_code == OMP_TRAIT_CONSTRUCT_SIMD) + { + error_at (loc, + "the % selector is not permitted in a " + "% context selector"); + return error_mark_node; + } + /* Reject expressions that reference parameter variables in "declare variant", as this is not yet implemented. FIXME; see PR middle-end/113904. */ - if (!metadirective_p + if (directive != OMP_CTX_METADIRECTIVE && (ts_code == OMP_TRAIT_DEVICE_NUM || ts_code == OMP_TRAIT_USER_CONDITION)) { diff --git a/gcc/omp-general.h b/gcc/omp-general.h index 4e143ed586b..5d44ff979f0 100644 --- a/gcc/omp-general.h +++ b/gcc/omp-general.h @@ -194,8 +194,12 @@ extern tree find_combined_omp_for (tree *, int *, void *); extern poly_uint64 omp_max_vf (bool); extern int omp_max_simt_vf (void); extern const char *omp_context_name_list_prop (tree); +enum omp_ctx_directive + { OMP_CTX_DECLARE_VARIANT, + OMP_CTX_BEGIN_DECLARE_VARIANT, + OMP_CTX_METADIRECTIVE }; extern tree omp_check_context_selector (location_t loc, tree ctx, - bool metadirective_p); + enum omp_ctx_directive directive); extern void omp_mark_declare_variant (location_t loc, tree variant, tree construct); extern int omp_context_selector_matches (tree, tree, bool); From patchwork Mon Feb 10 18:07:21 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandra Loosemore X-Patchwork-Id: 106294 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3C9E6385772D for ; Mon, 10 Feb 2025 18:11:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3C9E6385772D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=J5gsLkLG X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-il1-x12d.google.com (mail-il1-x12d.google.com [IPv6:2607:f8b0:4864:20::12d]) by sourceware.org (Postfix) with ESMTPS id 07925385780F for ; Mon, 10 Feb 2025 18:07:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 07925385780F Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 07925385780F Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::12d ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210865; cv=none; b=UZZZyKSapRok39s+B5HuDiWHDFu8A3dlTrPd0zGK74aGgDd5SfENuqhV5z2O7Dfkn3UAifhZBfeAB/5t12qZYQRdPsVXUp5IFYVHprZoMDcMZo6Tn8qQu4erycbW4PQ1KFVeBEGxCboMwmg2FIzfDZsCKnL/8ZihRdfmUPvmAJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210865; c=relaxed/simple; bh=TWdoj8CXPYCPWWj0jVUqQtA14Zw9NQ6rCV8Cz+cmR6Q=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=pjR28YMlXkxzg7M2MVlhJepgtN6rbrL0FbMHUoUN+XOVmLlgVr106gFUD3DIzzIsJqKTI54C+WFjGbEirXdVtxO7Arq4NxQ7lI1uRg9wFddBzWrA92BBQSsmfOtQzWUZR4fHtnth3TXp1VTjPmKULx6wYwqPh13byLkiHahHf/Y= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 07925385780F Received: by mail-il1-x12d.google.com with SMTP id e9e14a558f8ab-3d150512bd5so7234015ab.3 for ; Mon, 10 Feb 2025 10:07:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1739210864; x=1739815664; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=MckLKp7OoFmg4dXeAAMxGSCptk+TibcJByH71RNgE7o=; b=J5gsLkLGYkQNj6n2MGIm6FBo0Sdc1tCTPLPyzC4ICbu62Ac7420rjpsJ1+cmKZYvwq R7Pii5Tn9wDSvDqpHdqhfouCIs4fMSRKcNSJRiyWBX+bqjShnphJhR7x7zMZgjEysFm3 dsCHUBwgL60DDk1TObX6pCanq8eZWYtCayY+1//CQDUxqA2gKjtI0CLEx1VDSyqzuuH5 LHukSLR274UOyINvYYgj2yxJ5BiIfCmDI15D7GZhBOtKBps4PMbGYzcNViYPJSG/IDiF BigiA9Le2d+IotYEBMuPxrGg7VAQ4uBPaNkmJeSzuuhOQVhSqFXvx8ASrXGp9cX7UMch OCbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739210864; x=1739815664; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MckLKp7OoFmg4dXeAAMxGSCptk+TibcJByH71RNgE7o=; b=DxIZI4vbiXDFKfcWIKNBd7KGPhUw/El4V2e588NBw9HoNNUhZ38aUucflkVgTakzLa I7TKWHc8MAn2bnwImrU9T/G+3NOCd7qJDtIFDuZvKppMuxmAmrEoTtou2GSuh1d1Arxl PN6t0hj4PC0WdLxWlovf8OAfEDyxVQlj9dglHw1yPYvWWtHjfZ3dIcYRwJ2TESCGx1rz qWWIQNs3UifvhzW2xFrRspDJl7ve+9xY/Nd+lrh7ttFTaJ6nMwf57BjpkJ0o0ZhEe6ax 7zvjLl84i2ooxatyKGo8eLt/ooxIxtjHfOO2jOCdySQqUY+3oYm6+wShFMp4T46f3kAh gkoQ== X-Gm-Message-State: AOJu0Ywea3KEQPklkN6D7cvkz1kpT+zfeAHTtgh4bjw6WEWLqBR5byYp uaZq0kGP3Cf7ETvqXDPkmO3Hgw62hb6ILLUNVUmOlRBg91NqWiDA2OAQdxLEzJWlR8q9xnbAGWE Q X-Gm-Gg: ASbGncsWe0tazRsbcIrWznndMsqFsFv/5dVI3izey73WUg4/VSxJeftiBw+ilM90JQU Fv1F6VntOD+v1TM/w/VEOkaRUm6Vy3QuDW9i0nwfZYXTc1sJO3mkF0NiFYGnBK1KXZOqqKC/S9G LFSoqmDDr+k6IyVQEZVzNzQVaDa2Cto6EDnGG3vM3wNW5GSuoewj8K8HCcjdxE5azlocoQ9nkEp jOkyibRuGm4yADBKYwLig6YCnhcIR5CkKGz+8hyGWUxKXleiqxrbD16rBXwuSeRsVPS8RKOonAj tN7yXl+FUYbMX2KwklHWhqFalI0= X-Google-Smtp-Source: AGHT+IH2LoWMvZSyL941bBsE0eYc1WnwSJNMsoq5jW8L6LDtOxd4yehaJGdCzqUaXmA2MSWfj4ZP+w== X-Received: by 2002:a05:6e02:1aae:b0:3cf:fe1f:f5c5 with SMTP id e9e14a558f8ab-3d13dd13f64mr105143935ab.9.1739210863799; Mon, 10 Feb 2025 10:07:43 -0800 (PST) Received: from pondscum.hsd1.co.comcast.net ([2601:281:d901:97c0::af71]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-3d13d83c967sm19615365ab.45.2025.02.10.10.07.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2025 10:07:42 -0800 (PST) From: Sandra Loosemore To: gcc-patches@gcc.gnu.org Cc: jakub@redhat.com, tburnus@baylibre.com Subject: [PATCH 3/7] OpenMP: Support functions for nested "begin declare variant" Date: Mon, 10 Feb 2025 11:07:21 -0700 Message-Id: <20250210180725.2076678-4-sloosemore@baylibre.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250210180725.2076678-1-sloosemore@baylibre.com> References: <20250210180725.2076678-1-sloosemore@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org This patch adds functions for variant name mangling and context selector merging that are shared by the C and C++ front ends. The OpenMP specification says that name mangling is supposed to encode the context selector for the variant, but also provides for no way to reference these functions directly by name or from a different compilation unit. It also gives no guidance on how dynamic selectors might be encoded across compilation units. The GCC implementation of this feature instead treats variant functions as if they have no linkage and uses a simple counter to generate names. gcc/ChangeLog * omp-general.cc (omp_mangle_variant_name): New. (omp_check_for_duplicate_variant): New. (omp_copy_trait_set): New. (omp_trait_selectors_equivalent): New. (omp_combine_trait_sets): New. (omp_merge_context_selectors): New. * omp-general.h (omp_mangle_variant_name): Declare. (omp_check_for_duplicate_variant): Declare. (omp_merge_context_selectors): Declare. --- gcc/omp-general.cc | 194 +++++++++++++++++++++++++++++++++++++++++++++ gcc/omp-general.h | 5 ++ 2 files changed, 199 insertions(+) diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index 0a2dd6b5be7..c7b8e17d1f7 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -1501,6 +1501,66 @@ omp_check_context_selector (location_t loc, tree ctx, return ctx; } +/* Produce a mangled version of BASE_ID for the name of the variant + function with context selector CTX. SEP is a separator string. + The return value is an IDENTIFIER_NODE. + + Per the OpenMP spec, "the symbol names of two definitions of a function are + considered to be equal if and only if their effective context selectors are + equivalent". However, if we did have two such definitions, we'd get an ODR + violation. We already take steps in the front ends to make variant + functions internal to the compilation unit, since there is no (portable) way + to reference them directly by name or declare them as extern in another + compilation unit. So, we can diagnose the would-be ODR violations by + checking that there is not already a variant for the same function with an + equivalent context selector, and otherwise just use a simple counter to name + the variant functions instead of any complicated scheme to encode the + context selector in the name. */ + +tree +omp_mangle_variant_name (tree base_id, tree ctx ATTRIBUTE_UNUSED, + const char *sep) +{ + const char *base_name = IDENTIFIER_POINTER (base_id); + + /* Now do the actual mangling. */ + static int variant_counter; + /* The numeric suffix and terminating byte ought to need way less than + 32 bytes extra, that's just a magic number. */ + size_t buflen = (strlen (base_name) + strlen (sep) + strlen ("ompvariant") + + 32); + char *buffer = (char *) alloca (buflen); + snprintf (buffer, buflen, "%s%sompvariant%d", base_name, sep, + ++variant_counter); + return get_identifier (buffer); +} + +/* Forward declaration. */ +static int omp_context_selector_compare (tree ctx1, tree ctx2); + +/* Diagnose an error if there is already a variant with CTX registered + for BASE_DECL. Returns true if OK, false otherwise. */ +bool +omp_check_for_duplicate_variant (location_t loc, tree base_decl, tree ctx) +{ + for (tree attr = DECL_ATTRIBUTES (base_decl); attr; attr = TREE_CHAIN (attr)) + { + attr = lookup_attribute ("omp declare variant base", attr); + if (attr == NULL_TREE) + break; + + tree selector = TREE_VALUE (TREE_VALUE (attr)); + if (omp_context_selector_compare (ctx, selector) == 0) + { + error_at (loc, + "Multiple definitions of variants with the same " + "context selector violate the one-definition rule"); + return false; + } + } + return true; +} + /* Forward declarations. */ static int omp_context_selector_set_compare (enum omp_tss_code, tree, tree); static int omp_construct_simd_compare (tree, tree, bool); @@ -4925,3 +4985,137 @@ omp_maybe_apply_loop_xforms (tree *expr_p, tree for_clauses) } } +/* The next group of functions support merging of context selectors for + nested "begin declare variant" directives. The spec says: + + ...the effective context selectors of the outer directive are + appended to the context selector of the inner directive to form the + effective context selector of the inner directive. If a + trait-set-selector is present on both directives, the trait-selector + list of the outer directive is appended to the trait-selector list + of the inner directive after equivalent trait-selectors have been + removed from the outer list. + + In other words, there is no requirement to combine non-equivalent + trait-selectors according to their peculiar semantics, such as allowing + "any" as a wildcard, ANDing trait-property-expressions of "condition" trait + property expressions together, etc. Also there is no special provision for + treating the "construct" selector as an ordered list. + + Note that the spec does not explicitly say what "equivalent" means; + whether the properties and score of the trait-selectors must be identical, + or only the name of the trait-selector. This code assumes the former + except for the construct trait set where the order of selectors + is significant (so that it is *not* equivalent to have the same + trait-selector appearing in a different order in the list). */ + +/* Copy traits from FROM_TS and push them onto TAIL. */ + +static tree +omp_copy_trait_set (tree from_ts, tree tail) +{ + for (tree ts = from_ts; ts; ts = TREE_CHAIN (ts)) + tail = make_trait_selector (OMP_TS_CODE (ts), OMP_TS_SCORE (ts), + OMP_TS_PROPERTIES (ts), tail); + return nreverse (tail); +} + +/* Return true if trait selectors TS1 and TS2 for set TSS are "equivalent". */ + +static bool +omp_trait_selectors_equivalent (tree ts1, tree ts2, enum omp_tss_code tss) +{ + if (OMP_TS_CODE (ts1) != OMP_TS_CODE (ts2)) + return false; + + tree score1 = OMP_TS_SCORE (ts1); + tree score2 = OMP_TS_SCORE (ts2); + if ((score1 && score2 && !simple_cst_equal (score1, score2)) + || (score1 && !score2) + || (!score1 && score2)) + return false; + + return (omp_context_selector_props_compare (tss, OMP_TS_CODE (ts1), + OMP_TS_PROPERTIES (ts1), + OMP_TS_PROPERTIES (ts2)) + == 0); +} + +/* Merge lists of the trait selectors OUTER_TS and INNER_TS for selector set + TSS: "the trait-selector list of the outer directive is appended to the + trait-selector list of the inner directive after equivalent trait-selectors + have been removed from the outer list". */ + +static tree +omp_combine_trait_sets (tree outer_ts, tree inner_ts, enum omp_tss_code tss) +{ + unsigned HOST_WIDE_INT inner_traits = 0; + tree to_list = NULL_TREE; + + for (tree inner = inner_ts; inner; inner = TREE_CHAIN (inner)) + { + omp_ts_code ts_code = OMP_TS_CODE (inner); + inner_traits |= 1 << ts_code; + to_list + = make_trait_selector (ts_code, OMP_TS_SCORE (inner), + unshare_expr (OMP_TS_PROPERTIES (inner)), + to_list); + } + + for (tree outer = outer_ts; outer; outer = TREE_CHAIN (outer)) + { + omp_ts_code ts_code = OMP_TS_CODE (outer); + bool remove = false; + if (inner_traits & (1 << ts_code)) + for (tree inner = inner_ts; inner; inner = TREE_CHAIN (inner)) + if (OMP_TS_CODE (inner) == ts_code) + { + if (omp_trait_selectors_equivalent (inner, outer, tss)) + remove = true; + break; + } + if (!remove) + to_list + = make_trait_selector (ts_code, OMP_TS_SCORE (outer), + unshare_expr (OMP_TS_PROPERTIES (outer)), + to_list); + } + + return nreverse (to_list); +} + +/* Merge context selector INNER_CTX with OUTER_CTX. LOC and DIRECTIVE are + used for error checking. Returns the merged context, or error_mark_node + if the contexts cannot be merged. */ + +tree +omp_merge_context_selectors (location_t loc, tree outer_ctx, tree inner_ctx, + enum omp_ctx_directive directive) +{ + tree merged_ctx = NULL_TREE; + + if (inner_ctx == error_mark_node || outer_ctx == error_mark_node) + return error_mark_node; + + for (unsigned i = OMP_TRAIT_SET_CONSTRUCT; i != OMP_TRAIT_SET_LAST; i++) + { + omp_tss_code tss_code = static_cast(i); + tree outer_ts = omp_get_context_selector_list (outer_ctx, tss_code); + tree inner_ts = omp_get_context_selector_list (inner_ctx, tss_code); + tree merged_ts = NULL_TREE; + + if (inner_ts && outer_ts) + merged_ts = omp_combine_trait_sets (outer_ts, inner_ts, tss_code); + else if (inner_ts) + merged_ts = omp_copy_trait_set (inner_ts, NULL_TREE); + else if (outer_ts) + merged_ts = omp_copy_trait_set (outer_ts, NULL_TREE); + + if (merged_ts) + merged_ctx = make_trait_set_selector (tss_code, merged_ts, + merged_ctx); + } + + merged_ctx = nreverse (merged_ctx); + return omp_check_context_selector (loc, merged_ctx, directive); +} diff --git a/gcc/omp-general.h b/gcc/omp-general.h index 5d44ff979f0..466a70c9485 100644 --- a/gcc/omp-general.h +++ b/gcc/omp-general.h @@ -200,9 +200,14 @@ enum omp_ctx_directive OMP_CTX_METADIRECTIVE }; extern tree omp_check_context_selector (location_t loc, tree ctx, enum omp_ctx_directive directive); +extern tree omp_mangle_variant_name (tree base_id, tree ctx, const char *sep); +extern bool omp_check_for_duplicate_variant (location_t loc, + tree base_decl, tree ctx); extern void omp_mark_declare_variant (location_t loc, tree variant, tree construct); extern int omp_context_selector_matches (tree, tree, bool); +extern tree omp_merge_context_selectors (location_t, tree, tree, + enum omp_ctx_directive); extern tree resolve_omp_target_device_matches (tree node); extern tree omp_get_context_selector (tree, enum omp_tss_code, enum omp_ts_code); From patchwork Mon Feb 10 18:07:22 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandra Loosemore X-Patchwork-Id: 106295 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 70AF6385772D for ; Mon, 10 Feb 2025 18:14:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 70AF6385772D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=iJgKnh3U X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-il1-x12e.google.com (mail-il1-x12e.google.com [IPv6:2607:f8b0:4864:20::12e]) by sourceware.org (Postfix) with ESMTPS id 965023858288 for ; Mon, 10 Feb 2025 18:07:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 965023858288 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 965023858288 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::12e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210867; cv=none; b=expgAewwhy3mAXxC/KQa/VlYO+Vy18b1j9NoPTkLlNsrI/9Gv1uowj9Jb8DR33yrQiGKnDyAZocdnlgZOIh5zCg8OmmT+d2WyHhsVgCKfwk9YOxKNvsC0eU98TNQwL8x9ai1CsdI1png13rHDEzAM9+lo9hddP809/nGVw9yPTs= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210867; c=relaxed/simple; bh=fdQiP/zm5xMwV0migcQMDKVmco2kd403IY/mvjR/5CM=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=Y0ekeBQIoL9BX2UJJTK0dnm74h4kgF3OLddPnJ1Q7Jp+UlOYmT5sWmnWUHzGej3slp+eN02vNJqF5AAorjdeT02zZxIdSC1BDjRokJ7pwZGsrjMKjoMgEAKpIz+RQwaqONqSSG/G3SSv71Jc1OTBLdHzOoQT+Y8wHgUFPaB+qR4= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 965023858288 Received: by mail-il1-x12e.google.com with SMTP id e9e14a558f8ab-3cfc79a8a95so15587035ab.2 for ; Mon, 10 Feb 2025 10:07:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1739210866; x=1739815666; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VCbXbykSwKCpz+zpTOrBLzyJsYHFrsEwdF7+KVjfaxM=; b=iJgKnh3UtuJfAJypL0xM6P/eCKZ6i32CzSf6SKuZrC/uraalpX74aBzCXoI3G9Qs7Y 4uK8VvZl/n2DlzvccRSWJ7G4iplrat3zLe2ONnLJNURK6AQoO5jeNIMfrqEk/Ntb52tK WgvBb/sRdeJodscl003uYWRnq5zOiDsbAtG2VGEGsm0z2J3Q0qyxji+4sSzC0gdHmFeB GOizS5FwCsGJnQF1Vc4/xrORIy1OtUVG0L+4gorlPyWvKYSQWa7Jfvzthqyjnzpy4qwN 5AnEcrP7mxgs6ekM+s8m3Olji7EFQMLIrWJPDFz1e2e7zOxVETGusIYqg6Lt31nZ3HH2 wBhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739210866; x=1739815666; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VCbXbykSwKCpz+zpTOrBLzyJsYHFrsEwdF7+KVjfaxM=; b=XruA9/ujJF+N/yc1T6uCiKBR3ZyGWWJMQW1GKtN2HEgYDCjtrCajnVPJ8SDP74I8Sr 276yVqOCeHDotGsNyzqdwjCthr2zbxN5iVPrsoTPfxvWSjUWMbAgZ7xfKg3xe44C11rF hLVVrWUYBzYIV0tD8n0TBxL8THXeEcIe3OZkb6GwSAdiKK3amP6G/HLvy/AweoNBc9d2 MaNsohoFMfcZdSKNfCpoBvzfBRAvd7zHpmGTztRrvjVr+HWhqGqmzmuODK1S/Sbis4Lr KMkxqGu8cdoflSUd3JsH/8zHSoJZhCYqw72q8WGnfp/aSoOarku+YGCxWb3z0HXoDXJv Kocg== X-Gm-Message-State: AOJu0YzJsbx6PMZz1SIX7QgV1wOo5EiPznKl0R7E+6HZHm7ShiCJUEvq VpbXdDikodoj9OBtBRvc4qLiMLD4oHnLolnJOBkLgaXQbrxV/1r31s0XIh5zgWxQwUPohDN9QOq q X-Gm-Gg: ASbGnctT9uNrA0UfojnvknbrAyZP3Ypkya0ZkE56ZCV3p92HkdZyCZpcNt99U3PRrtX +pVwQm8GRjY2MH9jtAUMvq7pE24moCIQwZJKDK+a+ZER3nd2V5xwnDUVuaoniChdvfv/udF7K5S 8FfK8vgpTVZwiZNzNBgjDn5UKEVr63QlCtHo/4Gi+QUsHlQKznYqCZG0jpbgLBmqSg5VyYr50Yx ibh7BtBR0oalNWSoAl/pv6bljRtD/71uqqmEAXM0tys9DWUxTyHCSWKpsVtQazU8Hqj5VWDYfZS o5nP2LPxfWW0GimomlTmOOweNzI= X-Google-Smtp-Source: AGHT+IE5GvgCXaD/nY8m9ObBvE+Er+V1K827mGDTgV4V4T5K11LU82vV3kaCpvOun85aJ2bGmQq68g== X-Received: by 2002:a05:6e02:20c8:b0:3d0:21aa:a752 with SMTP id e9e14a558f8ab-3d13dd2c035mr111193375ab.2.1739210866403; Mon, 10 Feb 2025 10:07:46 -0800 (PST) Received: from pondscum.hsd1.co.comcast.net ([2601:281:d901:97c0::af71]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-3d13d83c967sm19615365ab.45.2025.02.10.10.07.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2025 10:07:45 -0800 (PST) From: Sandra Loosemore To: gcc-patches@gcc.gnu.org Cc: jakub@redhat.com, tburnus@baylibre.com Subject: [PATCH 4/7] OpenMP: Add flag for code elision to omp_context_selector_matches. Date: Mon, 10 Feb 2025 11:07:22 -0700 Message-Id: <20250210180725.2076678-5-sloosemore@baylibre.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250210180725.2076678-1-sloosemore@baylibre.com> References: <20250210180725.2076678-1-sloosemore@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org The "begin declare variant" has different rules for determining whether a context selector cannot match for purposes of code elision than we normally use; it excludes the case of a constant false "condition" selector for the "user" set. gcc/ChangeLog * omp-general.cc (omp_context_selector_matches): Add an optional bool argument for the code elision case. * omp-general.h (omp_context_selector_matches): Likewise. --- gcc/omp-general.cc | 28 ++++++++++++++++++++++++---- gcc/omp-general.h | 2 +- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc index c7b8e17d1f7..2edc0a65abf 100644 --- a/gcc/omp-general.cc +++ b/gcc/omp-general.cc @@ -1735,13 +1735,19 @@ omp_construct_traits_match (tree selector_traits, tree context_traits, CONSTRUCT_CONTEXT is known to be complete and not missing constructs filled in later during compilation. + If DECLARE_VARIANT_ELISION_P is true, the function implements the test + for elision of preprocessed code in "begin declare variant" constructs, + and returns 0 only for failure to match traits in the device and + implementation sets. + Dynamic properties (which are evaluated at run-time) should always return 1. */ int omp_context_selector_matches (tree ctx, tree construct_context, - bool complete_p) + bool complete_p, + bool declare_variant_elision_p) { int ret = 1; bool maybe_offloaded = omp_maybe_offloaded (construct_context); @@ -1753,9 +1759,12 @@ omp_context_selector_matches (tree ctx, /* Immediately reject the match if there are any ignored selectors present. */ - for (tree ts = selectors; ts; ts = TREE_CHAIN (ts)) - if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID) - return 0; + if (!declare_variant_elision_p + || set == OMP_TRAIT_SET_DEVICE + || set == OMP_TRAIT_SET_IMPLEMENTATION) + for (tree ts = selectors; ts; ts = TREE_CHAIN (ts)) + if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID) + return 0; if (set == OMP_TRAIT_SET_CONSTRUCT) { @@ -2109,6 +2118,13 @@ omp_context_selector_matches (tree ctx, break; case OMP_TRAIT_USER_CONDITION: gcc_assert (set == OMP_TRAIT_SET_USER); + /* The spec does not include the "user" set in the things that + can trigger code elision in "begin declare variant". */ + if (declare_variant_elision_p) + { + ret = -1; + break; + } for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p)) if (OMP_TP_NAME (p) == NULL_TREE) { @@ -2124,6 +2140,10 @@ omp_context_selector_matches (tree ctx, ret = -1; } break; + case OMP_TRAIT_INVALID: + /* This is only for the declare_variant_elision_p case. */ + ret = -1; + break; default: break; } diff --git a/gcc/omp-general.h b/gcc/omp-general.h index 466a70c9485..ec5a40fe6fa 100644 --- a/gcc/omp-general.h +++ b/gcc/omp-general.h @@ -205,7 +205,7 @@ extern bool omp_check_for_duplicate_variant (location_t loc, tree base_decl, tree ctx); extern void omp_mark_declare_variant (location_t loc, tree variant, tree construct); -extern int omp_context_selector_matches (tree, tree, bool); +extern int omp_context_selector_matches (tree, tree, bool, bool = false); extern tree omp_merge_context_selectors (location_t, tree, tree, enum omp_ctx_directive); extern tree resolve_omp_target_device_matches (tree node); From patchwork Mon Feb 10 18:07:23 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandra Loosemore X-Patchwork-Id: 106300 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3A4573857838 for ; Mon, 10 Feb 2025 18:22:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3A4573857838 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=Nv1q2BMv X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-io1-xd31.google.com (mail-io1-xd31.google.com [IPv6:2607:f8b0:4864:20::d31]) by sourceware.org (Postfix) with ESMTPS id 943AC385772D for ; Mon, 10 Feb 2025 18:07:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 943AC385772D Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 943AC385772D Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::d31 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210871; cv=none; b=Q7nzjskwPLIwmcNgYkUBGgkbPybGngyeEa9GqMmV44tF+w6f/td2HM6xUgPRqw03mAwWHA7MGLb3O93axBnzeXBG9cnu3/lkepOcBkEJtQxyP1pCU2o+qGWQGXFDjkgE0e65tXKlZ2d786Q0zgCcIcCgAYVy7NwJOAEFg/HHfw4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210871; c=relaxed/simple; bh=x0aMNFg31ktuC2PDsaYtdhWi346Ybqa5G+S7hvUj6Eo=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=Gw/hfdasSGEwrqIw8n9b7yGZKlT8OVxX3d18b59EYmx6bJD21D0EFvk69rnmdeRiNGlIRymtYz7v8GHEKZHlnSA/TdCh8BUheGywAy3VHH7KzhGbFPfH3PbpBRumwA3beC6bq4tfWiptVr4Zpe+L8nRHdqTLdsZDIoO9Di+cick= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 943AC385772D Received: by mail-io1-xd31.google.com with SMTP id ca18e2360f4ac-85532c7220cso75696139f.1 for ; Mon, 10 Feb 2025 10:07:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1739210870; x=1739815670; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=g9OxPtdgipw3XF5nNnRyIHDobGFlp5ISPKsVWe3/jHg=; b=Nv1q2BMvz4tz1R/7N2XSsrC3q7JilZlPHkjE86sl98MzmfAaO4xLYj3lGs+LM28XRZ oMj0P8cAwBtMtY8BuwRIqDPZm81/et6WplSQO7ClmqjKRz5/213RxECy8u7idYOZFCmU NSz8mrJvR9q6NTx38vKHZdhJXPQIiSp42nJlyC9I8MnUyO9lnCWN4kFwIE//Wc9C21Xz FHHuGhCRKPTduBA8+cG1g0Ewybk9IPKH8qm1coZURi2lyKMpaMSK2HmUt8SqXn04jwms 7tS82pKjJVjtEKfDurjmWXZvxIjEP5yZXrVOH98wCziXM7IbunRdAddVIz9lldDdbf+w SjYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739210870; x=1739815670; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=g9OxPtdgipw3XF5nNnRyIHDobGFlp5ISPKsVWe3/jHg=; b=KE5niByG3XohOAZWxT8J/hkHS9Hax3wkOl/YOkdLcsCZjm+JbfO+mB7qg4qYx+uvn4 nkiYMNm3NiIbMLw1p51JVPiXNvPfTJIZQZ7nEkiLfam7pSnjGYDhhPpVnKHXSjD60bbq 5Xa+w9l32xkObxmBe+h126ujPh/COvl8YEgrowPl+zyIDJ0pkB9gJW7ilCXprkMoGcI8 72dol+3GSoyKCeUObvGt1mVrpfQrhrDaSVP2At5U5r14AEAQcafMVXvC1I62jEgwZ0fm RQt1LwxcWb9Q051SWfgg3IbSViK6rS9BfqRLC+nyipvB0EYe2qEKLYldtf0yhIjSwVCb ka4g== X-Gm-Message-State: AOJu0Ywa+j7UGXJnG6T0I6Kpj8cgsRNkdA1i75XJjhH8JBRSOfV/PxYC Zmkz1DlGn0Abg4zCaB46djPqG7A0dAbXJt2mqAn8F9Ay8h5T30wVhTgu1YjIrXrA+k3aeavZ73c K X-Gm-Gg: ASbGncu9uGrrogUI/gBrHDdI5NsZOuoR4rRpPLlYS/4wS+/3+U4UMMjaNchdb2ejbMM 7EvFr7AOuOsHq+vyyQjxoAbf/iKkQUQhQuqCVOzvLhyeL+HmhMAidc26eT9u2egkqZLX2OVjltO Ps11j4JUuAwBlGjqXwSmSf9uV1cAWzvzlhn8XAHhWdzlr77V1w/nqeS6wUUKGr/ac2GhsFtIMgA 4JMQZ8TH/jyiA2lmqyAdNY1AAg4fhUjXBDyaYm6I08hi0HRMqwwcnX37YJsDMJlg0sRzSehl+gJ 15YW78QRsBzmnAJrUYsNH/Bw65Y= X-Google-Smtp-Source: AGHT+IHntCRWBu0v/nyq2RWt95KQZYM85HRHyd8ikIm4V8x8zlVOqb2TiaRxKGHs7rhTOY8Q8DTxZw== X-Received: by 2002:a92:ca4d:0:b0:3d0:e52:7d33 with SMTP id e9e14a558f8ab-3d13df6ad24mr132467425ab.22.1739210869292; Mon, 10 Feb 2025 10:07:49 -0800 (PST) Received: from pondscum.hsd1.co.comcast.net ([2601:281:d901:97c0::af71]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-3d13d83c967sm19615365ab.45.2025.02.10.10.07.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2025 10:07:47 -0800 (PST) From: Sandra Loosemore To: gcc-patches@gcc.gnu.org Cc: jakub@redhat.com, tburnus@baylibre.com Subject: [PATCH 5/7] OpenMP: C++ front end support for "begin declare variant" Date: Mon, 10 Feb 2025 11:07:23 -0700 Message-Id: <20250210180725.2076678-6-sloosemore@baylibre.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250210180725.2076678-1-sloosemore@baylibre.com> References: <20250210180725.2076678-1-sloosemore@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org This patch implements C++ support for the "begin declare variant" construct. The OpenMP specification is hazy on interaction of this feature with C++ language features. Variant functions in classes are supported but must be defined as members in the class definition, using an unqualified name for the base function which also must be present in that class. Similarly variant functions in a namespace can only be defined in that namespace using an unqualified name for a base function already declared in that namespace. Variants for template functions or inside template classes seem to (mostly) work. gcc/cp/ChangeLog * cp-tree.h (struct cp_omp_declare_variant_attr): New. (struct saved_scope): Add omp_declare_variant_attribute field. * decl.cc (omp_declare_variant_finalize_one): Add logic to inject "this" parameter for method calls. * parser.cc (cp_parser_skip_to_pragma_omp_end_declare_variant): New. (omp_start_variant_function): New. (omp_finish_variant_function): New. (cp_parser_init_declarator): Handle variant functions. (cp_parser_class_specifier): Handle deferred lookup of base functions when the entire class has been seen. (cp_parser_member_declaration): Handle variant functions. (cp_finish_omp_declare_variant): Merge context selectors if in a "begin declare variant" block. (cp_parser_omp_begin): Match "omp begin declare variant". Adjust error messages. (cp_parser_omp_end): Match "omp end declare variant". * parser.h (struct cp_parser): Add omp_unregistered_variants field. * semantics.cc (finish_translation_unit): Detect unmatched "omp begin declare variant". gcc/testsuite/ChangeLog * g++.dg/gomp/delim-declare-variant-1.C: New. * g++.dg/gomp/delim-declare-variant-2.C: New. * g++.dg/gomp/delim-declare-variant-3.C: New. * g++.dg/gomp/delim-declare-variant-4.C: New. * g++.dg/gomp/delim-declare-variant-5.C: New. * g++.dg/gomp/delim-declare-variant-6.C: New. * g++.dg/gomp/delim-declare-variant-7.C: New. * g++.dg/gomp/delim-declare-variant-40.C: New. * g++.dg/gomp/delim-declare-variant-41.C: New. * g++.dg/gomp/delim-declare-variant-50.C: New. * g++.dg/gomp/delim-declare-variant-51.C: New. * g++.dg/gomp/delim-declare-variant-52.C: New. * g++.dg/gomp/delim-declare-variant-70.C: New. * g++.dg/gomp/delim-declare-variant-71.C: New. libgomp/ * testsuite/libgomp.c++/delim-declare-variant-1.C: New. * testsuite/libgomp.c++/delim-declare-variant-2.C: New. * libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C: New. Co-Authored-By: Julian Brown Co-Authored-By: waffl3x --- gcc/cp/cp-tree.h | 6 + gcc/cp/decl.cc | 15 + gcc/cp/parser.cc | 544 ++++++++++++++++-- gcc/cp/parser.h | 5 + gcc/cp/semantics.cc | 7 + .../g++.dg/gomp/delim-declare-variant-1.C | 39 ++ .../g++.dg/gomp/delim-declare-variant-2.C | 53 ++ .../g++.dg/gomp/delim-declare-variant-3.C | 37 ++ .../g++.dg/gomp/delim-declare-variant-4.C | 57 ++ .../g++.dg/gomp/delim-declare-variant-40.C | 51 ++ .../g++.dg/gomp/delim-declare-variant-41.C | 31 + .../g++.dg/gomp/delim-declare-variant-5.C | 53 ++ .../g++.dg/gomp/delim-declare-variant-50.C | 99 ++++ .../g++.dg/gomp/delim-declare-variant-51.C | 181 ++++++ .../g++.dg/gomp/delim-declare-variant-52.C | 24 + .../g++.dg/gomp/delim-declare-variant-6.C | 72 +++ .../g++.dg/gomp/delim-declare-variant-7.C | 57 ++ .../g++.dg/gomp/delim-declare-variant-70.C | 206 +++++++ .../g++.dg/gomp/delim-declare-variant-71.C | 157 +++++ .../libgomp.c++/delim-declare-variant-1.C | 29 + .../libgomp.c++/delim-declare-variant-2.C | 37 ++ .../libgomp.c++/delim-declare-variant-7.C | 39 ++ 22 files changed, 1766 insertions(+), 33 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-1.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-2.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-3.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-4.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-40.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-41.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-5.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-50.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-51.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-52.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-6.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-7.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-70.C create mode 100644 gcc/testsuite/g++.dg/gomp/delim-declare-variant-71.C create mode 100644 libgomp/testsuite/libgomp.c++/delim-declare-variant-1.C create mode 100644 libgomp/testsuite/libgomp.c++/delim-declare-variant-2.C create mode 100644 libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ec976928f5f..d5efca834f5 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1922,6 +1922,11 @@ struct GTY(()) cp_omp_begin_assumes_data { bool attr_syntax; }; +struct GTY(()) cp_omp_declare_variant_attr { + bool attr_syntax; + tree selector; +}; + /* Global state. */ struct GTY(()) saved_scope { @@ -1972,6 +1977,7 @@ struct GTY(()) saved_scope { hash_map *GTY((skip)) x_local_specializations; vec *omp_declare_target_attribute; vec *omp_begin_assumes; + vec *omp_declare_variant_attribute; struct saved_scope *prev; }; diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 84abc17ade0..63cd90de0f7 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8545,6 +8545,21 @@ omp_declare_variant_finalize_one (tree decl, tree attr) if (idk == CP_ID_KIND_QUALIFIED) variant = finish_call_expr (variant, &args, /*disallow_virtual=*/true, koenig_p, tf_warning_or_error); + else if (idk == CP_ID_KIND_NONE + && TREE_CODE (variant) == FUNCTION_DECL + && DECL_IOBJ_MEMBER_FUNCTION_P (variant) + && CLASS_TYPE_P (DECL_CONTEXT (decl))) + { + tree saved_ccp = current_class_ptr; + tree saved_ccr = current_class_ref; + current_class_ptr = NULL_TREE; + current_class_ref = NULL_TREE; + inject_this_parameter (DECL_CONTEXT (decl), TYPE_UNQUALIFIED); + variant = finish_call_expr (variant, &args, /*disallow_virtual=*/false, + koenig_p, tf_warning_or_error); + current_class_ptr = saved_ccp; + current_class_ref = saved_ccr; + } else variant = finish_call_expr (variant, &args, /*disallow_virtual=*/false, koenig_p, tf_warning_or_error); diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 9d0970b4d83..35a7b32789d 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -4524,6 +4524,54 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok) } } +/* Skip tokens up to and including "#pragma omp end declare variant". + Properly handle nested "#pragma omp begin declare variant" pragmas. */ +static void +cp_parser_skip_to_pragma_omp_end_declare_variant (cp_parser *parser) +{ + for (int depth = 0; depth >= 0; ) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + + switch (token->type) + { + case CPP_PRAGMA_EOL: + if (!parser->lexer->in_pragma) + break; + /* FALLTHRU */ + case CPP_EOF: + /* If we've run out of tokens, stop. */ + return; + + case CPP_PRAGMA: + if ((cp_parser_pragma_kind (token) == PRAGMA_OMP_BEGIN + || cp_parser_pragma_kind (token) == PRAGMA_OMP_END) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_NAME) + && cp_lexer_nth_token_is (parser->lexer, 3, CPP_NAME)) + { + tree id1 = cp_lexer_peek_nth_token (parser->lexer, 2)->u.value; + tree id2 = cp_lexer_peek_nth_token (parser->lexer, 3)->u.value; + if (strcmp (IDENTIFIER_POINTER (id1), "declare") == 0 + && strcmp (IDENTIFIER_POINTER (id2), "variant") == 0) + { + if (cp_parser_pragma_kind (token) == PRAGMA_OMP_BEGIN) + depth++; + else + depth--; + } + } + cp_parser_skip_to_pragma_eol (parser, token); + continue; + + default: + break; + } + + /* Consume the token. */ + cp_lexer_consume_token (parser->lexer); + } +} + /* This is a simple wrapper around make_typename_type. When the id is an unresolved identifier node, we can provide a superior diagnostic using cp_parser_diagnose_invalid_type_name. */ @@ -23770,6 +23818,226 @@ cp_parser_maybe_adjust_declarator_for_dguide (cp_parser *parser, } } +/* Helper function for OpenMP "begin declare variant" directives. + Function definitions inside the construct need to have their names + mangled according to the context selector CTX. The DECLARATOR is + modified in place to point to a new identifier; the original name of + the function is returned. */ +static tree +omp_start_variant_function (cp_declarator *declarator, tree ctx) +{ + cp_declarator *id = get_id_declarator (declarator); + tree name = id->u.id.unqualified_name; + tree scope = id->u.id.qualifying_scope; + enum special_function_kind sfk = id->u.id.sfk; + + /* There seems to be no reasonable interpretation of what the behavior + should be if the name is qualified. You cannot add the variant function + to a class or namespace from outside of that scope. */ + if (scope) + { + sorry_at (id->id_loc, + "cannot handle qualified name for variant function"); + return NULL_TREE; + } + + /* Catch disallowed constructors and destructors now. We can't mangle + destructor names (which are not IDENTIFIER_NODEs) in any case. */ + if (sfk == sfk_constructor) + { + error_at (id->id_loc, + "declare variant directives are not allowed on constructors"); + return NULL_TREE; + } + if (sfk == sfk_destructor) + { + error_at (id->id_loc, + "declare variant directives are not allowed on destructors"); + return NULL_TREE; + } + if (TREE_CODE (name) != IDENTIFIER_NODE) + { + sorry_at (id->id_loc, + "cannot handle %s identifier name", + get_tree_code_name (TREE_CODE (name))); + return NULL_TREE; + } + + /* Mangle the name in the declarator. */ + id->u.id.unqualified_name + = omp_mangle_variant_name (name, ctx, JOIN_STR); + + return name; +} + +/* Helper function for OpenMP "begin declare variant" directives. Now + that we have a DECL for the variant function, and BASE_NAME for the + base function, look up the decl for BASE_NAME in the same scope as + DECL, add an "omp declare variant base" attribute pointing at CTX + to the base decl, and an "omp declare variant variant" attribute to + the variant DECL. */ +static void +omp_finish_variant_function (cp_parser *parser, tree decl, tree base_name, + tree ctx) +{ + tree match = NULL_TREE; + bool is_template = false; + tree decl_context = CP_DECL_CONTEXT (decl); + + /* First find the base_decl. */ + tree base_decl = cp_parser_lookup_name_simple (parser, base_name, + DECL_SOURCE_LOCATION (decl)); + + if (base_decl == error_mark_node) + base_decl = NULL_TREE; + if (!base_decl) + { + error_at (DECL_SOURCE_LOCATION (decl), + "no previous declaration of base function in this scope"); + return; + } + + /* Find the right overloaded function. */ + if (TREE_CODE (base_decl) == OVERLOAD) + { + for (ovl_iterator iter (base_decl); iter; ++iter) + { + tree bb = *iter; + if (decls_match (decl, bb)) + { + match = bb; + break; + } + else if (TREE_CODE (bb) == TEMPLATE_DECL + && TREE_CODE (decl) == FUNCTION_DECL + && DECL_TEMPLATE_INFO (decl)) + { + tree decl_template = DECL_TI_TEMPLATE (decl); + if (decl_template + && PRIMARY_TEMPLATE_P (decl_template) + && decls_match (bb, decl_template)) + { + /* We want to put the attributes on the function rather + than on the TEMPLATE_DECL that points to it. */ + match = DECL_TEMPLATE_RESULT (bb); + is_template = true; + break; + } + } + } + } + else if (decls_match (decl, base_decl)) + match = base_decl; + else if (TREE_CODE (base_decl) == TEMPLATE_DECL) + /* Per comment in cp-tree.h, TEMPLATE_DECLs are always wrapped in an + OVERLOAD, so we should never see them here. */ + gcc_unreachable (); + else if (TREE_CODE (base_decl) == TREE_LIST) + { + error_at (DECL_SOURCE_LOCATION (decl), "base function is ambiguous"); + return; + } + else if (TREE_CODE (base_decl) == SCOPE_REF) + { + /* This shows up in some cases involving templates; it's apparently a + placeholder for names that can't be matched to a declaration + until template instantiation. */ + sorry_at (DECL_SOURCE_LOCATION (decl), + "base function cannot be resolved"); + return; + } + + if (!match) + { + error_at (DECL_SOURCE_LOCATION (decl), + "variant function definition does not match previous " + "declaration of %qE", base_decl); + return; + } + else if (CP_DECL_CONTEXT (match) != decl_context) + { + /* Reject inherited or using decls. */ + error_at (DECL_SOURCE_LOCATION (decl), + "variant function must be in the same scope as the " + "base function %qE", match); + return; + } + else if (DECL_VIRTUAL_P (decl) || DECL_VIRTUAL_P (match)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "declare variant directives are not allowed on " + "virtual functions"); + return; + } + else if (DECL_DEFAULTED_FN (decl) || DECL_DEFAULTED_FN (match)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "declare variant directives are not allowed on " + "defaulted functions"); + return; + } + else if (DECL_DELETED_FN (decl) || DECL_DELETED_FN (match)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "declare variant directives are not allowed on " + "deleted functions"); + return; + } + else if (DECL_IMMEDIATE_FUNCTION_P (decl) + || DECL_IMMEDIATE_FUNCTION_P (match)) + { + error_at (DECL_SOURCE_LOCATION (decl), + "declare variant directives are not allowed on " + "immediate functions"); + return; + } + + /* Inside a template, make the "omp declare variant base" attribute + point to the name of DECL rather than DECL itself. During template + instantiation, omp_declare_variant_finalize_one will handle this + using the same logic as for the non-delimited form of "declare variant", + causing template instantiation as needed. For the non-template case, + there is nothing that will trigger omp_declare_variant_finalize_one; + so we create the final form of the attribute here, which points + directly to DECL rather than its name. */ + tree decl_or_name = decl; + cp_id_kind idk = CP_ID_KIND_NONE; + if (processing_template_decl && is_template) + { + decl_or_name = DECL_NAME (decl); + idk = CP_ID_KIND_TEMPLATE_ID; + } + + omp_check_for_duplicate_variant (DECL_SOURCE_LOCATION (decl), + match, ctx); + tree construct + = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT); + omp_mark_declare_variant (DECL_SOURCE_LOCATION (decl), decl, construct); + + tree attrs = DECL_ATTRIBUTES (match); + tree match_loc_node + = maybe_wrap_with_location (integer_zero_node, + DECL_SOURCE_LOCATION (match)); + tree loc_node = tree_cons (match_loc_node, + build_int_cst (integer_type_node, idk), + build_tree_list (match_loc_node, + integer_zero_node)); + attrs = tree_cons (get_identifier ("omp declare variant base"), + tree_cons (decl_or_name, ctx, loc_node), attrs); + if (processing_template_decl) + ATTR_IS_DEPENDENT (attrs) = 1; + DECL_ATTRIBUTES (match) = attrs; + + /* Variant functions are essentially anonymous and cannot be + referenced by name, so make them have internal linkage. Note + that class methods in C++ normally have external linkage with + weak/comdat semantics; this prevents that. */ + TREE_PUBLIC (decl) = 0; + DECL_COMDAT (decl) = 0; + DECL_INTERFACE_KNOWN (decl) = 1; + DECL_NOT_REALLY_EXTERN (decl) = 1; +} + /* Declarators [gram.dcl.decl] */ /* Parse an init-declarator. @@ -23986,6 +24254,27 @@ cp_parser_init_declarator (cp_parser* parser, /* This is a function-definition. */ *function_definition_p = true; + /* If we're in an OpenMP "begin declare variant" block, the + name in the declarator refers to the base function. We need + to save that and modify the declarator to have the mangled + name for the variant function instead. */ + tree dv_base = NULL_TREE; + tree dv_ctx = NULL_TREE; + vec *dv_state + = scope_chain->omp_declare_variant_attribute; + + if (!vec_safe_is_empty (dv_state)) + { + cp_omp_declare_variant_attr a = dv_state->last (); + dv_ctx = copy_list (a.selector); + dv_base = omp_start_variant_function (declarator, dv_ctx); + if (dv_base == NULL_TREE) + { + cp_parser_skip_to_end_of_statement (parser); + return error_mark_node; + } + } + /* Parse the function definition. */ if (member_p) decl = cp_parser_save_member_function_body (parser, @@ -24004,6 +24293,11 @@ cp_parser_init_declarator (cp_parser* parser, = func_brace_location; } + /* If this function was in a "begin declare variant" block, + store the pointer back to the base function and fix up + the attributes for the middle end. */ + if (dv_base && decl != error_mark_node) + omp_finish_variant_function (parser, decl, dv_base, dv_ctx); return decl; } } @@ -24081,6 +24375,27 @@ cp_parser_init_declarator (cp_parser* parser, is_initialized = SD_DEFAULTED; else if (t2->keyword == RID_DELETE) is_initialized = SD_DELETED; + if (!vec_safe_is_empty (scope_chain->omp_declare_variant_attribute)) + { + /* We're in a "begin declare variant" construct. The parser + doesn't go through the normal function definition path for + these and hence doesn't invoke omp_finish_variant_function + where these errors would otherwise be caught. */ + if (is_initialized == SD_DEFAULTED) + { + error_at (declarator->init_loc, + "declare variant directives are not allowed on " + "defaulted functions"); + return error_mark_node; + } + else if (is_initialized == SD_DELETED) + { + error_at (declarator->init_loc, + "declare variant directives are not allowed on " + "deleted functions"); + return error_mark_node; + } + } } } else @@ -27536,6 +27851,10 @@ cp_parser_class_specifier (cp_parser* parser) tree saved_ccr = current_class_ref; current_class_ptr = NULL_TREE; current_class_ref = NULL_TREE; + /* Set up for deferred lookup of "omp begin declare variant" base functions + in the class. */ + tree save_unregistered_variants = parser->omp_unregistered_variants; + parser->omp_unregistered_variants = NULL_TREE; /* Start the class. */ if (nested_name_specifier_p) @@ -27557,6 +27876,19 @@ cp_parser_class_specifier (cp_parser* parser) /* Parse the member-specification. */ cp_parser_member_specification_opt (parser); + /* Register any "begin declare variant" functions in this class, since + references to the base function can only be resolved after the + entire class is seen. */ + for (tree bdv = parser->omp_unregistered_variants; bdv; + bdv = TREE_CHAIN (bdv)) + { + tree dv_base = TREE_PURPOSE (TREE_PURPOSE (bdv)); + tree dv_ctx = TREE_VALUE (TREE_PURPOSE (bdv)); + tree dv_decl = TREE_VALUE (bdv); + omp_finish_variant_function (parser, dv_decl, dv_base, dv_ctx); + } + parser->omp_unregistered_variants = save_unregistered_variants; + /* Look for the trailing `}'. */ closing_brace = braces.require_close (parser); /* Look for trailing attributes to apply to this class. */ @@ -29216,6 +29548,28 @@ cp_parser_member_declaration (cp_parser* parser) if (initializer && initializer_token_start) error_at (initializer_token_start->location, "pure-specifier on function-definition"); + + /* If we're in an OpenMP "begin declare variant" block, + the name in the declarator refers to the base function. + We need to save that and modify the declarator to have + the mangled name for the variant function instead. */ + tree dv_base = NULL_TREE; + tree dv_ctx = NULL_TREE; + vec *dv_state + = scope_chain->omp_declare_variant_attribute; + if (!vec_safe_is_empty (dv_state)) + { + cp_omp_declare_variant_attr a = dv_state->last (); + dv_ctx = copy_list (a.selector); + dv_base = omp_start_variant_function (declarator, + dv_ctx); + if (dv_base == NULL_TREE) + { + cp_parser_skip_to_end_of_statement (parser); + goto out; + } + } + decl = cp_parser_save_member_function_body (parser, &decl_specifiers, declarator, @@ -29226,6 +29580,19 @@ cp_parser_member_declaration (cp_parser* parser) /* If the member was not a friend, declare it here. */ if (!friend_p) finish_member_declaration (decl); + + /* If this function was in a "begin declare variant" + block, record the information we need to find the + base function and fix it up later. At this point in + parsing, we may not have seen the base function yet + so we defer looking it up and registering the variant + until the class is complete. */ + if (dv_base && decl != error_mark_node) + parser->omp_unregistered_variants + = tree_cons (tree_cons (dv_base, dv_ctx, NULL_TREE), + decl, + parser->omp_unregistered_variants); + /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If the next token is a semicolon, consume it. */ @@ -50439,6 +50806,20 @@ cp_finish_omp_declare_variant (cp_parser *parser, cp_token *pragma_tok, goto fail; ctx = omp_check_context_selector (match_loc, ctx, OMP_CTX_DECLARE_VARIANT); + + /* The OpenMP spec says the merging rules for enclosing + "begin declare variant" contexts apply to "declare variant + directives" -- the term it uses to refer to both directive + forms. */ + if (ctx != error_mark_node + && !vec_safe_is_empty (scope_chain->omp_declare_variant_attribute)) + { + cp_omp_declare_variant_attr a + = scope_chain->omp_declare_variant_attribute->last (); + tree outer_ctx = a.selector; + ctx = omp_merge_context_selectors (match_loc, outer_ctx, ctx, + OMP_CTX_DECLARE_VARIANT); + } if (ctx != error_mark_node && variant != error_mark_node) { tree match_loc_node @@ -51096,7 +51477,9 @@ cp_parser_omp_declare_target (cp_parser *parser, cp_token *pragma_tok) /* OpenMP 5.1 # pragma omp begin assumes clauses[optseq] new-line - # pragma omp begin declare target clauses[optseq] new-line */ + # pragma omp begin declare target clauses[optseq] new-line + + # pragma omp begin declare variant (match context-selector) new-line */ #define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \ @@ -51142,9 +51525,73 @@ cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok) = { in_omp_attribute_pragma, device_type, indirect }; vec_safe_push (scope_chain->omp_declare_target_attribute, a); } + else if (strcmp (p, "variant") == 0) + { + cp_lexer_consume_token (parser->lexer); + const char *clause = ""; + matching_parens parens; + location_t match_loc = cp_lexer_peek_token (parser->lexer)->location; + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + clause = IDENTIFIER_POINTER (id); + } + if (strcmp (clause, "match") != 0) + { + cp_parser_error (parser, "expected %"); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return; + } + + cp_lexer_consume_token (parser->lexer); + + if (!parens.require_open (parser)) + { + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return; + } + + tree ctx = cp_parser_omp_context_selector_specification (parser, + true); + if (ctx != error_mark_node) + ctx = omp_check_context_selector (match_loc, ctx, + OMP_CTX_BEGIN_DECLARE_VARIANT); + + if (ctx != error_mark_node + && !vec_safe_is_empty (scope_chain->omp_declare_variant_attribute)) + { + cp_omp_declare_variant_attr a + = scope_chain->omp_declare_variant_attribute->last (); + tree outer_ctx = a.selector; + ctx = omp_merge_context_selectors (match_loc, outer_ctx, ctx, + OMP_CTX_BEGIN_DECLARE_VARIANT); + } + + if (ctx == error_mark_node + || !omp_context_selector_matches (ctx, NULL_TREE, false, true)) + { + /* The context is either invalid or cannot possibly match. + In the latter case the spec says all code in the begin/end + sequence will be elided. In the former case we'll get bogus + errors from trying to parse it without a valid context to + use for name-mangling, so elide that too. */ + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + cp_parser_skip_to_pragma_omp_end_declare_variant (parser); + return; + } + else + { + cp_omp_declare_variant_attr a + = { parser->lexer->in_omp_attribute_pragma, ctx }; + vec_safe_push (scope_chain->omp_declare_variant_attribute, a); + } + + parens.require_close (parser); + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + } else { - cp_parser_error (parser, "expected %"); + cp_parser_error (parser, "expected % or %"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); } } @@ -51157,7 +51604,8 @@ cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok) } else { - cp_parser_error (parser, "expected % or %"); + cp_parser_error (parser, "expected %, " + "%, or %"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); } } @@ -51166,7 +51614,8 @@ cp_parser_omp_begin (cp_parser *parser, cp_token *pragma_tok) # pragma omp end declare target new-line OpenMP 5.1: - # pragma omp end assumes new-line */ + # pragma omp end assumes new-line + # pragma omp end declare variant new-line */ static void cp_parser_omp_end (cp_parser *parser, cp_token *pragma_tok) @@ -51188,41 +51637,70 @@ cp_parser_omp_end (cp_parser *parser, cp_token *pragma_tok) p = IDENTIFIER_POINTER (id); } if (strcmp (p, "target") == 0) - cp_lexer_consume_token (parser->lexer); + { + cp_lexer_consume_token (parser->lexer); + cp_parser_require_pragma_eol (parser, pragma_tok); + if (!vec_safe_length (scope_chain->omp_declare_target_attribute)) + error_at (pragma_tok->location, + "%<#pragma omp end declare target%> without " + "corresponding %<#pragma omp declare target%> or " + "%<#pragma omp begin declare target%>"); + else + { + cp_omp_declare_target_attr + a = scope_chain->omp_declare_target_attribute->pop (); + if (a.attr_syntax != in_omp_attribute_pragma) + { + if (a.attr_syntax) + error_at (pragma_tok->location, + "%qs in attribute syntax terminated " + "with %qs in pragma syntax", + a.device_type >= 0 ? "begin declare target" + : "declare target", + "end declare target"); + else + error_at (pragma_tok->location, + "%qs in pragma syntax terminated " + "with %qs in attribute syntax", + a.device_type >= 0 ? "begin declare target" + : "declare target", + "end declare target"); + } + } + } + else if (strcmp (p, "variant") == 0) + { + cp_lexer_consume_token (parser->lexer); + cp_parser_require_pragma_eol (parser, pragma_tok); + if (!vec_safe_length (scope_chain->omp_declare_variant_attribute)) + error_at (pragma_tok->location, + "%<#pragma omp end declare variant%> without " + "corresponding %<#pragma omp begin declare variant%>"); + else + { + cp_omp_declare_variant_attr + a = scope_chain->omp_declare_variant_attribute->pop (); + if (a.attr_syntax != in_omp_attribute_pragma) + { + if (a.attr_syntax) + error_at (pragma_tok->location, + "% in attribute syntax " + "terminated with % in " + "pragma syntax"); + else + error_at (pragma_tok->location, + "% in pragma syntax " + "terminated with % in " + "attribute syntax"); + } + } + } else { cp_parser_error (parser, "expected %"); cp_parser_skip_to_pragma_eol (parser, pragma_tok); return; } - cp_parser_require_pragma_eol (parser, pragma_tok); - if (!vec_safe_length (scope_chain->omp_declare_target_attribute)) - error_at (pragma_tok->location, - "%<#pragma omp end declare target%> without corresponding " - "%<#pragma omp declare target%> or " - "%<#pragma omp begin declare target%>"); - else - { - cp_omp_declare_target_attr - a = scope_chain->omp_declare_target_attribute->pop (); - if (a.attr_syntax != in_omp_attribute_pragma) - { - if (a.attr_syntax) - error_at (pragma_tok->location, - "%qs in attribute syntax terminated " - "with %qs in pragma syntax", - a.device_type >= 0 ? "begin declare target" - : "declare target", - "end declare target"); - else - error_at (pragma_tok->location, - "%qs in pragma syntax terminated " - "with %qs in attribute syntax", - a.device_type >= 0 ? "begin declare target" - : "declare target", - "end declare target"); - } - } } else if (strcmp (p, "assumes") == 0) { diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index f9ed80123c4..d998f7e9af7 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -456,6 +456,11 @@ struct GTY(()) cp_parser { outside that file. */ struct omp_metadirective_parse_data * GTY((skip)) omp_metadirective_state; + + /* TREE_LIST of "omp begin declare variant" functions when the base + function has not been seen "elsewhere" (per the OpenMP spec) yet; + used only when these functions are seen in a class definition. */ + tree omp_unregistered_variants; }; /* In parser.cc */ diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index a2ee3a34caa..7a38dfb76e3 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -3963,6 +3963,13 @@ finish_translation_unit (void) "#pragma omp end declare target"); vec_safe_truncate (scope_chain->omp_declare_target_attribute, 0); } + if (vec_safe_length (scope_chain->omp_declare_variant_attribute)) + { + if (!errorcount) + error ("% without corresponding " + "%"); + vec_safe_truncate (scope_chain->omp_declare_variant_attribute, 0); + } if (vec_safe_length (scope_chain->omp_begin_assumes)) { if (!errorcount) diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-1.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-1.C new file mode 100644 index 00000000000..dfeb7c42d08 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-1.C @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-foffload=disable -fdump-tree-gimple" } */ + +/* Check that variants within a "begin declare variant" directive + are attached to the correct overloaded function. */ + +int f (int x) { return x; } + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +int f (int x) { return -1; } +#pragma omp end declare variant + +int f (int x, int y) { return x * y; } + +#pragma omp begin declare variant match (construct={target}) +int f (int x, int y) { return -2; } +#pragma omp end declare variant + +int f (int x, int y, int z) { return x * y * z; } + +#pragma omp begin declare variant match (device={kind("host")}) +int f (int x, int y, int z) { return -3; } +#pragma omp end declare variant + +int main (void) +{ + if (f (10) != -1) __builtin_abort (); + if (f (10, 20) != 200) __builtin_abort (); /* no match on this one */ + if (f (10, 20, 30) != -3) __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "f\\.ompvariant. \\(10\\)" "gimple" } } */ +/* { dg-final { scan-tree-dump "f \\(10, 20\\)" "gimple" } } */ +/* { dg-final { scan-tree-dump "f\\.ompvariant. \\(10, 20, 30\\)" "gimple" } } */ + + + + + diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-2.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-2.C new file mode 100644 index 00000000000..1784e14dfc3 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-2.C @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-gimple" } */ + +/* Check that "omp begin declare variant" works on methods in a + class declaration. */ + +class test1 { + + private: + int n; + static int m; + + public: + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + int get_n (void) { return n * 2; } + static int get_m (void) { return m * 2; } + #pragma omp end declare variant + + #pragma omp begin declare variant match (construct={target}) + int get_n (void) { return this->n * 2; } + #pragma omp end declare variant + + /* The base methods are deliberately declared after the variants in order + to check that the lookup can still find them. */ + void set_n (int x) { n = x; } + int get_n (void) { return n; } + + static void set_m (int x) { m = x; } + static int get_m (void) { return m; } +}; + +int test1::m; + +int main (void) +{ + test1 t1; + t1.set_n (10); + if (t1.get_n () != 20) __builtin_abort (); + test1::set_m (1); + if (test1::get_m () != 2) __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "test1::get_n\\.ompvariant. \\(&t1\\)" "gimple" } } */ +/* { dg-final { scan-tree-dump "test1::get_m\\.ompvariant. \\(\\)" "gimple" } } */ + +/* The variants must have internal linkage, not .globl or .weak. */ +/* { dg-final { scan-assembler-not "\\.globl\[ \t\]*_?_ZN5test117get_n\\.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.globl\[ \t\]*_?_ZN5test117get_m\\.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.weak\[ \t\]*_?_ZN5test117get_n\\.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.weak\[ \t\]*_?_ZN5test117get_m\\.ompvariant" } } */ + + diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-3.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-3.C new file mode 100644 index 00000000000..ccbb01ce794 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-3.C @@ -0,0 +1,37 @@ +/* { dg-do compile } */ + +/* Check that "omp begin declare variant" for class methods outside of the + class declaration gives a sorry. C++ generally does not allow injection + of additional methods into a class outside of its declaration so it is + not clear what this is supposed to do. */ + +class test1 { + + private: + int n; + static int m; + + public: + + void set_n (int x) { n = x; } + int get_n (void) { return n; } + + static void set_m (int x) { m = x; } + static int get_m (void) { return m; } + +}; + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +int test1::get_n (void) { return n * 2; } /* { dg-message "sorry, unimplemented: cannot handle qualified name for variant function" } */ +static int test1::get_m (void) { return m * 2; } /* { dg-message "sorry, unimplemented: cannot handle qualified name for variant function" } */ +#pragma omp end declare variant + +int main (void) +{ + test1 t1; + t1.set_n (10); + if (t1.get_n () != 20) __builtin_abort (); + test1::set_m (1); + if (test1::get_m () != 2) __builtin_abort (); +} + diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-4.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-4.C new file mode 100644 index 00000000000..567cf9c4f8c --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-4.C @@ -0,0 +1,57 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-gimple" } */ + +/* Like c-c++-common/delim-declare-variant-1.c, but with namespaces. */ + +namespace n1 { + +int foo (int a) +{ + return a; +} + +int bar (int x) +{ + return x; +} + +#pragma omp begin declare variant match (construct={target}) +int foo (int a) +{ + return a + 1; +} + +int bar (int x) +{ + return x * 2; +} +#pragma omp end declare variant + +/* Because of the high score value, this variant for "bar" should always be + selected even when the one above also matches. */ +#pragma omp begin declare variant match (implementation={vendor(score(10000):"gnu")}) +int bar (int x) +{ + return x * 4; +} +#pragma omp end declare variant + +} /* namespace n1 */ + +int main (void) +{ + if (n1::foo (42) != 42) __builtin_abort (); + if (n1::bar (3) != 12) __builtin_abort (); +#pragma omp target + { + if (n1::foo (42) != 43) __builtin_abort (); + if (n1::bar (3) != 12) __builtin_abort (); + } +} + +/* { dg-final { scan-tree-dump-times "omp declare variant base \\(foo.ompvariant." 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "omp declare variant base \\(bar.ompvariant." 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "foo \\(42\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "foo\\.ompvariant. \\(42\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "bar \\(3\\)" 0 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "bar\\.ompvariant. \\(3\\)" 2 "gimple" } } */ diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-40.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-40.C new file mode 100644 index 00000000000..4f35d209d25 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-40.C @@ -0,0 +1,51 @@ +// { dg-do compile } + +// Check that variants for a template function are instantiated correctly. +// FIXME: Fails due to PR118530. + +template +void f_default_param (T = 42) {} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void f_default_param (T = 42) {} +#pragma omp end declare variant + +template +void f_no_param () {} // { dg-bogus "no matching function for call" "PR118530" { xfail *-*-* } } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void f_no_param () {} +#pragma omp end declare variant + +void instantiate_f() +{ + f_default_param(); + f_no_param(); +} + +template +void nttp () {} // { dg-bogus "no matching function for call" "PR118530" { xfail *-*-* } } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void nttp () {} +#pragma omp end declare variant + +void instantiate_nttp() +{ + nttp<42>(); +} + +template +struct S {}; + +template class Templ> +void templ_templ () {} // { dg-bogus "no matching function for call" "PR118530" { xfail *-*-* } } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template class Templ> +void templ_templ () {} +#pragma omp end declare variant + +void instantiate_templ_templ() +{ + templ_templ(); +} diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-41.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-41.C new file mode 100644 index 00000000000..38e41e7847b --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-41.C @@ -0,0 +1,31 @@ +/* { dg-do compile { target c++11 } } */ + +/* This test case fails in omp_finish_variant_function because base_decl + is a SCOPE_REF and it cannot be resolved to an actual base function decl + to hang the variant attribute on. */ + +template + class is_same { + static constexpr bool value = false; +}; + +template +class is_same { + static constexpr bool value = true; +}; + +template +void fn (T&&) { } + +#pragma omp begin declare variant match(implementation={vendor("gnu")}) +template +void fn(T&&) { // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } + static_assert(is_same::value); +} +#pragma omp end declare variant + +int main() +{ + int lvalue = 42; + fn(0); +} diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-5.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-5.C new file mode 100644 index 00000000000..e8db369a67d --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-5.C @@ -0,0 +1,53 @@ +/* { dg-do compile } */ + +/* Check that "omp begin declare variant" for a namespace function outside of + the namespace gives an error. C++ generally does not allow injection of + additional function into a namespace outside of its scope so this is just a + generic error. */ + +namespace n1 { + +int foo (int a) +{ + return a; +} + +int bar (int x) +{ + return x; +} + +} /* namespace n1 */ + + +#pragma omp begin declare variant match (construct={target}) +int n1::foo (int a) /* { dg-message "sorry, unimplemented: cannot handle qualified name for variant function" } */ +{ + return a + 1; +} + +int n1::bar (int x) /* { dg-message "sorry, unimplemented: cannot handle qualified name for variant function" } */ +{ + return x * 2; +} +#pragma omp end declare variant + +/* Because of the high score value, this variant for "bar" should always be + selected even when the one above also matches. */ +#pragma omp begin declare variant match (implementation={vendor(score(10000):"gnu")}) +int n1::bar (int x) /* { dg-message "sorry, unimplemented: cannot handle qualified name for variant function" } */ +{ + return x * 4; +} +#pragma omp end declare variant + +int main (void) +{ + if (n1::foo (42) != 42) __builtin_abort (); + if (n1::bar (3) != 12) __builtin_abort (); +#pragma omp target + { + if (n1::foo (42) != 43) __builtin_abort (); + if (n1::bar (3) != 12) __builtin_abort (); + } +} diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-50.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-50.C new file mode 100644 index 00000000000..a958b52d01e --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-50.C @@ -0,0 +1,99 @@ +/* { dg-do compile } */ + +/* Test for restrictions on declare variant functions on virtual functions, + constructors, and destructors. */ + +struct S0 +{ + virtual void f_virtual_before0 () {} + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + virtual void f_virtual_before0 () {} // { dg-error "declare variant directives are not allowed on virtual functions" } + #pragma omp end declare variant + + virtual void f_virtual_before1 () {} + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + void f_virtual_before1 () {} // { dg-error "declare variant directives are not allowed on virtual functions" } + #pragma omp end declare variant + + void f_virtual_before2 () {} + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + virtual void f_virtual_before2 () {} // { dg-error "declare variant directives are not allowed on virtual functions" } + #pragma omp end declare variant + + void f_virtual_before3 () {} + // code elision, no error + #pragma omp begin declare variant match (implementation={vendor("cray")}) + virtual void f_virtual_before3 () {} + #pragma omp end declare variant + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + virtual void f_virtual_after0 () {} // { dg-error "declare variant directives are not allowed on virtual functions" } + #pragma omp end declare variant + virtual void f_virtual_after0 () {} + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + void f_virtual_after1 () {} // { dg-error "declare variant directives are not allowed on virtual functions" } + #pragma omp end declare variant + virtual void f_virtual_after1 () {} + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + virtual void f_virtual_after2 () {} // { dg-error "declare variant directives are not allowed on virtual functions" } + #pragma omp end declare variant + void f_virtual_after2 () {} +}; + +struct S_before { + S_before() {} + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_before() {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + + S_before(int) {} + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_before(int) {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + + S_before(double) {} + // code elision, no error + #pragma omp begin declare variant match (implementation={vendor("cray")}) + S_before(double) {} + #pragma omp end declare variant + + template + S_before(T) {} + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + template + S_before(T) {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + + ~S_before() {} + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + ~S_before() {} // { dg-error "declare variant directives are not allowed on destructors" } + #pragma omp end declare variant +}; + +struct S_after { + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_after() {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + S_after() {} + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_after(int) {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + S_after(int) {} + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + template + S_after(T) {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + template + S_after(T) {} + + // code elision, no error + #pragma omp begin declare variant match (implementation={vendor("cray")}) + ~S_after() {} + #pragma omp end declare variant + ~S_after() {} +}; + diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-51.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-51.C new file mode 100644 index 00000000000..9e65309b0df --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-51.C @@ -0,0 +1,181 @@ +/* { dg-do compile { target c++11 } } */ + +/* Test delimited declare variant on constexpr, deleted, and defaulted + functions. */ +/* C++11 */ + +/* TODO: add templates cases for constexpr/delete free functions */ + +/* Do we warn for the mismatch? + TBH we probably warn whenever a variant function is constexpr in general. + I can't imagine that we are going to support constant evaluation of a + variant function, realistically the only choice is to always use the base + function if a constant-expression is required. */ +constexpr int freefn_mismatched_constexpr_before0 () { return 0; } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +int freefn_mismatched_constexpr_before0 () { return 1; } +#pragma omp end declare variant + +int freefn_mismatched_constexpr_before1 () { return 0; } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +constexpr int freefn_mismatched_constexpr_before1 () { return 1; } +#pragma omp end declare variant + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +constexpr int freefn_mismatched_constexpr_after0 () { return 1; } // { dg-error "no previous declaration of base function" } +#pragma omp end declare variant +int freefn_mismatched_constexpr_after0 () { return 0; } + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +int freefn_mismatched_constexpr_after1 () { return 1; } // { dg-error "no previous declaration of base function" } +#pragma omp end declare variant +constexpr int freefn_mismatched_constexpr_after1 () { return 0; } + + + +void freefn_deleted_before () = delete; +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +void freefn_deleted_before () {} // { dg-error "declare variant directives are not allowed on deleted functions" } +#pragma omp end declare variant + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +void freefn_deleted_after () {} // { dg-error "no previous declaration of base function" } +#pragma omp end declare variant +void freefn_deleted_after () = delete; + +/* TECHNICALLY allowed by the spec, but obviously conflicts with the intention. */ +void freefn_variant_deleted_base_before () {} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +void freefn_variant_deleted_base_before () = delete; // { dg-error "declare variant directives are not allowed on deleted functions" } +#pragma omp end declare variant + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +void freefn_variant_deleted_base_after () = delete; // { dg-error "declare variant directives are not allowed on deleted functions" } +#pragma omp end declare variant +void freefn_variant_deleted_base_after () {}; + + +/* For now, obviously error, not sure if we error on just the base or on + both though. + In the future, I think if the base and all variants are deleted, we can + treat a call to the function as deleted before we determine a variant. */ +void freefn_both_deleted_base_before () = delete; +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +void freefn_both_deleted_base_before () = delete; // { dg-error "declare variant directives are not allowed on deleted functions" } +#pragma omp end declare variant + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +void freefn_both_deleted_base_after () = delete; // { dg-error "declare variant directives are not allowed on deleted functions" } +#pragma omp end declare variant +void freefn_both_deleted_base_after () = delete; + + + + +struct S0 +{ + void f_deleted_before () = delete; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + void f_deleted_before () {} // { dg-error "declare variant directives are not allowed on deleted functions" } + #pragma omp end declare variant + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + void f_deleted_after () {} // { dg-error "declare variant directives are not allowed on deleted functions" } + #pragma omp end declare variant + void f_deleted_after () = delete; +}; + + +/* These should error for constructor/destructor, not default. */ +struct S_default_before { + S_default_before() = default; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_before() {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + + S_default_before(S_default_before const&) = default; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_before(S_default_before const&) {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + + S_default_before(S_default_before&&) = default; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_before(S_default_before&&) {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + + ~S_default_before() = default; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + ~S_default_before() {} // { dg-error "declare variant directives are not allowed on destructors" } + #pragma omp end declare variant +}; + +struct S_default_after { + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_after() {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + S_default_after() = default; + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_after(S_default_after const&) {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + S_default_after(S_default_after const&) = default; + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_after(S_default_after&&) {} // { dg-error "declare variant directives are not allowed on constructors" } + #pragma omp end declare variant + S_default_after(S_default_after&&) = default; + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + ~S_default_after() {} // { dg-error "declare variant directives are not allowed on destructors" } + #pragma omp end declare variant + ~S_default_after() = default; +}; + +/* These should error for default/delete. */ +struct S_default_assignment_before { + S_default_assignment_before& operator=(S_default_assignment_before const&) = default; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_assignment_before& operator=(S_default_assignment_before const&) { return *this; } // { dg-error "declare variant directives are not allowed on defaulted functions" } + #pragma omp end declare variant + + S_default_assignment_before& operator=(S_default_assignment_before&&) = default; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_assignment_before& operator=(S_default_assignment_before&&) { return *this; } // { dg-error "declare variant directives are not allowed on defaulted functions" } + #pragma omp end declare variant +}; + +struct S_default_assignment_after { + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_assignment_after& operator=(S_default_assignment_after const&) { return *this; } // { dg-error "declare variant directives are not allowed on defaulted functions" } + #pragma omp end declare variant + S_default_assignment_after& operator=(S_default_assignment_after const&) = default; + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_default_assignment_after& operator=(S_default_assignment_after&&) { return *this; } // { dg-error "declare variant directives are not allowed on defaulted functions" } + #pragma omp end declare variant + S_default_assignment_after& operator=(S_default_assignment_after&&) = default; +}; + +struct S_deleted_assignment_before { + S_deleted_assignment_before& operator=(S_deleted_assignment_before const&) = delete; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_deleted_assignment_before& operator=(S_deleted_assignment_before const&) { return *this; } // { dg-error "declare variant directives are not allowed on deleted functions" } + #pragma omp end declare variant + + S_deleted_assignment_before& operator=(S_deleted_assignment_before&&) = delete; + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_deleted_assignment_before& operator=(S_deleted_assignment_before&&) { return *this; } // { dg-error "declare variant directives are not allowed on deleted functions" } + #pragma omp end declare variant +}; + +struct S_deleted_assignment_after { + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_deleted_assignment_after& operator=(S_deleted_assignment_after const&) { return *this; } // { dg-error "declare variant directives are not allowed on deleted functions" } + #pragma omp end declare variant + S_deleted_assignment_after& operator=(S_deleted_assignment_after const&) = delete; + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + S_deleted_assignment_after& operator=(S_deleted_assignment_after&&) { return *this; } // { dg-error "declare variant directives are not allowed on deleted functions" } + #pragma omp end declare variant + S_deleted_assignment_after& operator=(S_deleted_assignment_after&&) = delete; +}; diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-52.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-52.C new file mode 100644 index 00000000000..4f4a005c6c7 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-52.C @@ -0,0 +1,24 @@ +/* { dg-do compile { target c++20 } } */ + +/* The procedure that a declare variant directive determined to be a function + variant may not be an immediate function + Declare variant directives may + not be specified for immediate functions. */ +consteval void freefn_consteval_before0 () {} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +consteval void freefn_consteval_before0 () {} // { dg-error "declare variant directives are not allowed on immediate functions" } +#pragma omp end declare variant + +/* Declare variant directives may not be specified for immediate functions. */ +consteval void freefn_consteval_before1 () {} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +void freefn_consteval_before1 () {} // { dg-error "declare variant directives are not allowed on immediate functions" } +#pragma omp end declare variant + +/* The procedure that a declare variant directive determined to be a function + variant may not be an immediate function. */ +void freefn_consteval_before2 () {} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +consteval void freefn_consteval_before2 () {} // { dg-error "declare variant directives are not allowed on immediate functions" } +#pragma omp end declare variant + + diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-6.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-6.C new file mode 100644 index 00000000000..30dee4cc607 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-6.C @@ -0,0 +1,72 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-gimple" } */ + +/* Check "begin declare variant" on template functions. */ + +template +T foo (T a) +{ + return a; +} + +template +T bar (T x) +{ + return x; +} + +#pragma omp begin declare variant match (construct={target}) +template +T1 foo (T1 a) +{ + return a + 1; +} + +template +T1 bar (T1 x) +{ + return x * 2; +} +#pragma omp end declare variant + +/* Because of the high score value, this variant for "bar" should always be + selected even when the one above also matches. */ +#pragma omp begin declare variant match (implementation={vendor(score(10000):"gnu")}) +template +T2 bar (T2 x) +{ + return x * 4; +} +#pragma omp end declare variant + +int main (void) +{ + if (foo (42) != 42) __builtin_abort (); + if (bar (3) != 12) __builtin_abort (); +#pragma omp target + { + if (foo (42) != 43) __builtin_abort (); + if (bar (3) != 12) __builtin_abort (); + } +} + +/* Make sure all the template functions are instantiated. */ +/* { dg-final { scan-tree-dump "int foo.ompvariant. \\(.*\\)" "gimple" } } +/* { dg-final { scan-tree-dump "int foo \\(.*\\)" "gimple" } } +/* { dg-final { scan-tree-dump "int bar.ompvariant. \\(.*\\)" "gimple" } } + +/* Make sure the calls are resolved correctly. */ +/* { dg-final { scan-tree-dump-times "foo \\(42\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "foo\\.ompvariant. \\(42\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "bar \\(3\\)" 0 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "bar\\.ompvariant. \\(3\\)" 2 "gimple" } } */ + +/* The variants must have internal linkage, not .globl or .weak. */ +/* { dg-final { scan-assembler-not "\\.globl\[ \t\]*_?_Z15foo.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.globl\[ \t\]*_?_Z15bar.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.weak\[ \t\]*_?_Z15foo.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.weak\[ \t\]*_?_Z15bar.ompvariant" } } */ + + + + diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-7.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-7.C new file mode 100644 index 00000000000..b24e6c0cb3b --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-7.C @@ -0,0 +1,57 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-gimple" } */ + +/* Check that "omp begin declare variant" works on methods in a template + class declaration. */ + +template +class test1 { + + private: + T n; + static T m; + + public: + + void set_n (T x) { n = x; } + T get_n (void) { return n; } + + static void set_m (T x) { m = x; } + static T get_m (void) { return m; } + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + T get_n (void) { return n * 2; } + static T get_m (void) { return m * 2; } + #pragma omp end declare variant + + #pragma omp begin declare variant match (construct={target}) + T get_n (void) { return this->n * 2; } + #pragma omp end declare variant +}; + +template +T test1::m; + +int main (void) +{ + test1 t1; + t1.set_n (10); + if (t1.get_n () != 20) __builtin_abort (); + test1::set_m (1); + if (test1::get_m () != 2) __builtin_abort (); +} + +/* Make sure the "declare variant" replacement happens. */ +/* { dg-final { scan-tree-dump "test1::get_n\\.ompvariant. \\(&t1\\)" "gimple" } } */ +/* { dg-final { scan-tree-dump "test1::get_m\\.ompvariant. \\(\\)" "gimple" } } */ + +/* Make sure the variant methods are instantiated. */ +/* { dg-final { scan-tree-dump "int test1::get_n\\.ompvariant. \\(.*\\)" "gimple" } } */ +/* { dg-final { scan-tree-dump "int test1::get_m\\.ompvariant. \\(.*\\)" "gimple" } } */ + +/* The variants must have internal linkage, not .globl or .weak. */ +/* { dg-final { scan-assembler-not "\\.globl\[ \t\]*_?_ZN5test1IiE17get_n.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.globl\[ \t\]*_?_ZN5test1IiE17get_m.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.weak\[ \t\]*_?_ZN5test1IiE17get_n.ompvariant" } } */ +/* { dg-final { scan-assembler-not "\\.weak\[ \t\]*_?_ZN5test1IiE17get_m.ompvariant" } } */ + diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-70.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-70.C new file mode 100644 index 00000000000..ed1e1ae2ddd --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-70.C @@ -0,0 +1,206 @@ +/* { dg-do compile { target c++11 } } */ + +/* Check that the substituted type in variant is the same as the one in the + base. */ + +template +struct is_same { + static constexpr bool value = false; +}; + +template +struct is_same { + static constexpr bool value = true; +}; + +/* Using static_assert directly in a variant triggers the SCOPE_REF bug noted + in delim-declare-variant-41.C. We'll avoid that by outsourcing the checks + to this function. PR118791 is a different bug that affects also the + non-delimited form of "declare variant". */ +template +void fail_if_not_same() { + static_assert(is_same::value); // { dg-bogus "static assertion failed" "PR118791" { xfail *-*-* } } +} + +/* Sanity checks are included in the base function just to be absolutely + certain there were no mistakes made in the tests. They should match the + cases in the variant function exactly. */ + +template +void fwdref_passed_lvalue_int (T&& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void fwdref_passed_lvalue_int (T&& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +template +void fwdref_passed_lvalue_const_int (T&& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void fwdref_passed_lvalue_const_int (T&& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +template +void fwdref_passed_rvalue_int (T&& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void fwdref_passed_rvalue_int (T&& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +template +void fwdref_passed_rvalue_const_int (T&& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void fwdref_passed_rvalue_const_int (T&& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +void instantiate_fwdref() +{ + int lvalue = 0; + fwdref_passed_lvalue_int(lvalue); + fwdref_passed_lvalue_const_int(static_cast(lvalue)); + fwdref_passed_rvalue_int(0); + fwdref_passed_rvalue_const_int(static_cast(0)); +} + + + +template +void explicit_instantiate_fwdref_with_lvalue_int (T&& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void explicit_instantiate_fwdref_with_lvalue_int (T&& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +template +void explicit_instantiate_fwdref_with_lvalue_const_int (T&& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void explicit_instantiate_fwdref_with_lvalue_const_int (T&& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +template +void explicit_instantiate_fwdref_with_rvalue_int (T&& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void explicit_instantiate_fwdref_with_rvalue_int (T&& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +template +void explicit_instantiate_fwdref_with_rvalue_const_int (T&& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void explicit_instantiate_fwdref_with_rvalue_const_int (T&& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +/* Technically a missuse of a forwarding reference */ +void explicit_instantiate_fwdref() +{ + int lvalue = 0; + explicit_instantiate_fwdref_with_lvalue_int(lvalue); + explicit_instantiate_fwdref_with_lvalue_const_int(static_cast(lvalue)); + explicit_instantiate_fwdref_with_rvalue_int(0); // { dg-bogus "required from here" "PR118791" { xfail *-*-* } } + explicit_instantiate_fwdref_with_rvalue_const_int(static_cast(0)); // { dg-bogus "required from here" "PR118791" { xfail *-*-* } } +} + + +template +void const_lref_passed_lvalue_int (T const& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void const_lref_passed_lvalue_int (T const& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +template +void const_lref_passed_lvalue_const_int (T const& p) { + static_assert(is_same::value); + static_assert(is_same::value); + static_assert(is_same::value); +} +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void const_lref_passed_lvalue_const_int (T const& p) { + fail_if_not_same(); + fail_if_not_same(); + fail_if_not_same(); +} +#pragma omp end declare variant + +void instantiate_const_lref() +{ + int lvalue = 0; + const_lref_passed_lvalue_int(lvalue); + const_lref_passed_lvalue_const_int(static_cast(lvalue)); +} diff --git a/gcc/testsuite/g++.dg/gomp/delim-declare-variant-71.C b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-71.C new file mode 100644 index 00000000000..7bd59d07c32 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/delim-declare-variant-71.C @@ -0,0 +1,157 @@ +/* { dg-do compile { target c++11 } } */ + +/* Test static_assert in variants. */ +/* Most of the tests in this file are broken and xfailed. + See also delim-declare-variant-41.C for a simpler test case for + the "base function cannot be resolved" sorry. */ + +struct has_value_true { static constexpr bool value = true; }; + +template +struct always_true { + static constexpr bool value = true; +}; + +template +void static_assert_in_variant_static_member_uninstantiated (T) { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_static_member_uninstantiated (T) // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(T::value); +} +#pragma omp end declare variant + +template +void static_assert_in_variant_static_member_no_param_uninstantiated () { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_static_member_no_param_uninstantiated () // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(T::value); +} +#pragma omp end declare variant + +template +void static_assert_in_variant_static_member (T) { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_static_member (T) // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(T::value); +} +#pragma omp end declare variant + +template +void static_assert_in_variant_static_member_no_param () { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_static_member_no_param () // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(T::value); +} +#pragma omp end declare variant + +void instantiate_static_assert_in_variant_static_member() +{ + static_assert_in_variant_static_member(has_value_true{}); + static_assert_in_variant_static_member_no_param(); +} + + +template +void static_assert_in_variant_templ_member_uninstantiated (T) { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_templ_member_uninstantiated (T) // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(always_true::value); +} +#pragma omp end declare variant + +template +void static_assert_in_variant_templ_member_no_param_uninstantiated () { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_templ_member_no_param_uninstantiated () // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(always_true::value); +} +#pragma omp end declare variant + +template +void static_assert_in_variant_templ_member (T) { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_templ_member (T) // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(always_true::value); +} +#pragma omp end declare variant + +template +void static_assert_in_variant_templ_member_no_param () { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_templ_member_no_param () // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(always_true::value); +} +#pragma omp end declare variant + +void instantiate_static_assert_in_variant_templ_member() +{ + static_assert_in_variant_templ_member(0); + static_assert_in_variant_templ_member_no_param(); +} + + +/* PR118530 affects also the non-delimited form of "declare variant". */ +template +void static_assert_in_variant_nttp_uninstantiated () { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_nttp_uninstantiated () { + static_assert(B); +} +#pragma omp end declare variant + +template +void static_assert_in_variant_nttp () { } // { dg-bogus "no matching function for call" "PR118530" { xfail *-*-* } } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template +void static_assert_in_variant_nttp () { + static_assert(B); +} +#pragma omp end declare variant + +void instantiate_static_assert_in_variant_nttp() +{ + static_assert_in_variant_nttp(); +} + + +template class Templ> +void static_assert_in_variant_template_template_uninstantiated () { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template class Templ> +void static_assert_in_variant_template_template_uninstantiated () // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(Templ::value); +} +#pragma omp end declare variant + +template class Templ> +void static_assert_in_variant_template_template () { } +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +template class Templ> +void static_assert_in_variant_template_template () // { dg-bogus "base function cannot be resolved" "" { xfail *-*-* } } +{ + static_assert(Templ::value); +} +#pragma omp end declare variant + +void instantiate_static_assert_in_variant_template_template() +{ + static_assert_in_variant_template_template(); +} diff --git a/libgomp/testsuite/libgomp.c++/delim-declare-variant-1.C b/libgomp/testsuite/libgomp.c++/delim-declare-variant-1.C new file mode 100644 index 00000000000..bf146dd2365 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/delim-declare-variant-1.C @@ -0,0 +1,29 @@ +/* { dg-additional-options "-foffload=disable" } */ + +/* Check that variants within a "begin declare variant" directive + are attached to the correct overloaded function. */ + +int f (int x) { return x; } + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +int f (int x) { return -1; } +#pragma omp end declare variant + +int f (int x, int y) { return x * y; } + +#pragma omp begin declare variant match (construct={target}) +int f (int x, int y) { return -2; } +#pragma omp end declare variant + +int f (int x, int y, int z) { return x * y * z; } + +#pragma omp begin declare variant match (device={kind("host")}) +int f (int x, int y, int z) { return -3; } +#pragma omp end declare variant + +int main (void) +{ + if (f (10) != -1) __builtin_abort (); + if (f (10, 20) != 200) __builtin_abort (); /* no match on this one */ + if (f (10, 20, 30) != -3) __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c++/delim-declare-variant-2.C b/libgomp/testsuite/libgomp.c++/delim-declare-variant-2.C new file mode 100644 index 00000000000..6641768c1ef --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/delim-declare-variant-2.C @@ -0,0 +1,37 @@ +/* Check that "omp begin declare variant" works on methods in a + class declaration. */ + +class test1 { + + private: + int n; + static int m; + + public: + + void set_n (int x) { n = x; } + int get_n (void) { return n; } + + static void set_m (int x) { m = x; } + static int get_m (void) { return m; } + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + int get_n (void) { return n * 2; } + static int get_m (void) { return m * 2; } + #pragma omp end declare variant + + #pragma omp begin declare variant match (construct={target}) + int get_n (void) { return this->n * 2; } + #pragma omp end declare variant +}; + +int test1::m; + +int main (void) +{ + test1 t1; + t1.set_n (10); + if (t1.get_n () != 20) __builtin_abort (); + test1::set_m (1); + if (test1::get_m () != 2) __builtin_abort (); +} diff --git a/libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C b/libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C new file mode 100644 index 00000000000..60cc5d8a55b --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/delim-declare-variant-7.C @@ -0,0 +1,39 @@ +/* Check that "omp begin declare variant" works on methods in a template + class declaration. */ + +template +class test1 { + + private: + T n; + static T m; + + public: + + void set_n (T x) { n = x; } + T get_n (void) { return n; } + + static void set_m (T x) { m = x; } + static T get_m (void) { return m; } + + #pragma omp begin declare variant match (implementation={vendor("gnu")}) + T get_n (void) { return n * 2; } + static T get_m (void) { return m * 2; } + #pragma omp end declare variant + + #pragma omp begin declare variant match (construct={target}) + T get_n (void) { return this->n * 2; } + #pragma omp end declare variant +}; + +template +T test1::m; + +int main (void) +{ + test1 t1; + t1.set_n (10); + if (t1.get_n () != 20) __builtin_abort (); + test1::set_m (1); + if (test1::get_m () != 2) __builtin_abort (); +} From patchwork Mon Feb 10 18:07:24 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandra Loosemore X-Patchwork-Id: 106297 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DD0DA385735B for ; Mon, 10 Feb 2025 18:16:06 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DD0DA385735B Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=0JT7SbaB X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-il1-x12e.google.com (mail-il1-x12e.google.com [IPv6:2607:f8b0:4864:20::12e]) by sourceware.org (Postfix) with ESMTPS id E10C63857034 for ; Mon, 10 Feb 2025 18:07:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E10C63857034 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E10C63857034 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::12e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210874; cv=none; b=oi1dFQat7NMqShHizZ7RCveGtx8Bnf5H0kMQL2AKVCmXnAV6UZq534xHkU5g4K0ChAZ2HJ/sWRydut1B5syImLiyUo/jjCvt3Km78nMBbJYg1D/gHR5Xz0YodJylfxG+g8LEZe1Q3duHEv0iLqWVpVyFJavxQ/bIhSb2Z/PXg/w= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210874; c=relaxed/simple; bh=EoqDuWNb7ubDhOk2H5sgELlB0C80Kt0F+LVdXisHtkc=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=u/RbjLCpnKMYcUAG9oemrf6U3jhJmb74sqbI/80+WFDwN2ZZ2JtlEwzDlWYgpTsRWuDAuHRsQlW8mHbYQF/eSop5mZi4lcSWBNP+4Tfe0hQKcbN1/C4tqdxZIcCEz5fvUsR/MK3cnpB2CU4a8efX1SkJFrwRX/iCgUiiAsOaJLI= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E10C63857034 Received: by mail-il1-x12e.google.com with SMTP id e9e14a558f8ab-3d03ac846a7so15444705ab.2 for ; Mon, 10 Feb 2025 10:07:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1739210873; x=1739815673; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zXggaeKUSAKSK+mZFsQJOIH1j+80hsBBRYKYoeUTDK0=; b=0JT7SbaBQk85/xBeucfivn3mShTWaiAHOtXqf761v7pmYMpKcaP5CTYCMmM2sDkKKy ZqxVpBRU7nV8i6ilYnxEZb2p/hVRKh5GCVYcHrjDl2+bSuWO6isM97lVfL1ISbznYPvS 7Z9xeh9117MbGx1T3oKplNFw8rSca01eB9B9nlTiYbZfb69hHod1NO/UyDCyn4/N7/Ir qMPmSk4fBiqjbLLMKyzCeWf5Ak3O0k6abKNkVlSto36PzpsUB9syj2cFeFoU3fw6ERyx Lo4vQkn4EZcqslPx4S67IYWEjBmoFk3hbJrjuSvxJqQEMsHcCeSQFIPZda/pokNOrQqe rV3g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739210873; x=1739815673; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zXggaeKUSAKSK+mZFsQJOIH1j+80hsBBRYKYoeUTDK0=; b=dOJv2sfeLkId1QFvwNMECtYShpbKpnpnTvCZDEpQ7V0Y7qvxJnPJ/hFwMhVqbB0qex JPdwyWiDjOp6TuWWUUjYw5JjVVD8kWk8rCwWg5GbS/Sgugy9G1Nzbtehoj392xp6RQHB ++svLAhiO/wmKnBXdz6eLo990vkb2PvxgQO1tsYeQDVdUs9+rSwpndAtJxEw7iY0OwVX enMMMvA0RxnUyJA+ifi+WPodAbaI76HiVh5zalvLXrApUGPcyRUol6gEPzM4h542DsKL VmgmC5oeT2R2BTuy45QEssp38+4sud/Y1xfOTJFUsK+MW2HCTzugun8S6C/Z/UMPPkk7 v4xA== X-Gm-Message-State: AOJu0YziCwru+8I3TSkk80LZKKvpnTNafliA4r3dS1ND3+pq1F36L+UZ 4nRsxk+fmlpxCHarzhQfSVP69DDl36ecWms/hNfi/XEhaJeWumH7FC3aI3obGHqBrgfLKCA+JNL m X-Gm-Gg: ASbGncuipmtNi7hIOHQAvnNOvVZ6d7rNVo8jlDn31qEkTAD59lat4pX++NKJtx78+wX CtuaO56eAX30tDiwzQxL3vn7dCuY0KveFcJBrMOw1gs+je93paN+HBj8VYVKLuPLl2OpHGBxJrO s7Z5b30RO7NGcpItyKuMT5GQn9x18ytBnfCXWu320xh/LBtOXKRLGYmtbRaD9EiiRddQXUFlLOf RNKLVASLg2Hp7hxeeNKTPN/LcYSpmbV4cTDH6KEfPW6RJbK01ur05AJf8qbR9ZOb0hOjwWHL0W3 aY6RkaaZsNilatBlSDPceNdwSAg= X-Google-Smtp-Source: AGHT+IHfYJQl+GGXMnCPVDAd4FV2BdmztzEVuu+iBajCrrjg5E15kbvyJKXpIbwcEuYdteGmibKlrw== X-Received: by 2002:a05:6e02:1a01:b0:3d0:443d:a5c3 with SMTP id e9e14a558f8ab-3d13dcee694mr98674075ab.3.1739210872510; Mon, 10 Feb 2025 10:07:52 -0800 (PST) Received: from pondscum.hsd1.co.comcast.net ([2601:281:d901:97c0::af71]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-3d13d83c967sm19615365ab.45.2025.02.10.10.07.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2025 10:07:51 -0800 (PST) From: Sandra Loosemore To: gcc-patches@gcc.gnu.org Cc: jakub@redhat.com, tburnus@baylibre.com Subject: [PATCH 6/7] OpenMP: C front end support for "begin declare variant" Date: Mon, 10 Feb 2025 11:07:24 -0700 Message-Id: <20250210180725.2076678-7-sloosemore@baylibre.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250210180725.2076678-1-sloosemore@baylibre.com> References: <20250210180725.2076678-1-sloosemore@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org gcc/c/ChangeLog * c-decl.cc (current_omp_declare_variant_attribute): Define. * c-lang.h (struct c_omp_declare_variant_attr): Declare. (current_omp_declare_variant_attribute): Declare. * c-parser.cc (c_parser_skip_to_pragma_omp_end_declare_variant): New. (c_parser_translation_unit): Check for "omp begin declare variant" with no matching "end". (c_parser_declaration_or_fndef): Handle functions in "omp begin declare variant" block. (c_finish_omp_declare_variant): Merge context selectors with surrounding "omp begin declare variant". (JOIN_STR): Define. (omp_start_variant_function): New. (omp_finish_variant_function): New. (c_parser_omp_begin): Handle "omp begin declare variant". (c_parser_omp_end): Likewise. Co-Authored-By: Julian Brown --- gcc/c/c-decl.cc | 3 + gcc/c/c-lang.h | 8 ++ gcc/c/c-parser.cc | 347 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 320 insertions(+), 38 deletions(-) diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 0dcbae9b26f..8b778c16e2d 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -163,6 +163,9 @@ vec *current_omp_declare_target_attribute; we are in. */ vec *current_omp_begin_assumes; +/* Vector of "omp begin/end declare variant" blocks we are in. */ +vec *current_omp_declare_variant_attribute; + /* Vector of loop names with C_DECL_LOOP_NAME or C_DECL_SWITCH_NAME marked LABEL_DECL as the last and canonical for each loop or switch. */ static vec loop_names; diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h index 4b93d184dbc..cd68fc00e45 100644 --- a/gcc/c/c-lang.h +++ b/gcc/c/c-lang.h @@ -72,6 +72,11 @@ struct GTY(()) c_omp_begin_assumes_data { bool attr_syntax; }; +struct GTY(()) c_omp_declare_variant_attr { + bool attr_syntax; + tree selector; +}; + /* If non-empty, implicit "omp declare target" attribute is added into the attribute lists. */ extern GTY(()) vec @@ -80,5 +85,8 @@ extern GTY(()) vec #pragma omp end assumes (and how many times when nested). */ extern GTY(()) vec *current_omp_begin_assumes; +/* And similarly for #pragma omp begin/end declare variant. */ +extern GTY(()) vec + *current_omp_declare_variant_attribute; #endif /* ! GCC_C_LANG_H */ diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 62c6bc031d6..97f7da4a2ed 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -1456,6 +1456,55 @@ c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true) parser->error = false; } +/* Skip tokens up to and including "#pragma omp end declare variant". + Properly handle nested "#pragma omp begin declare variant" pragmas. */ +static void +c_parser_skip_to_pragma_omp_end_declare_variant (c_parser *parser) +{ + for (int depth = 0; depth >= 0; ) + { + c_token *token = c_parser_peek_token (parser); + + switch (token->type) + { + case CPP_PRAGMA_EOL: + if (!parser->in_pragma) + break; + /* FALLTHRU */ + case CPP_EOF: + /* If we've run out of tokens, stop. */ + return; + + case CPP_PRAGMA: + if ((token->pragma_kind == PRAGMA_OMP_BEGIN + || token->pragma_kind == PRAGMA_OMP_END) + && c_parser_peek_nth_token (parser, 2)->type == CPP_NAME + && c_parser_peek_nth_token (parser, 3)->type == CPP_NAME) + { + tree id1 = c_parser_peek_nth_token (parser, 2)->value; + tree id2 = c_parser_peek_nth_token (parser, 3)->value; + if (strcmp (IDENTIFIER_POINTER (id1), "declare") == 0 + && strcmp (IDENTIFIER_POINTER (id2), "variant") == 0) + { + if (token->pragma_kind == PRAGMA_OMP_BEGIN) + depth++; + else + depth--; + } + } + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser, false); + continue; + + default: + break; + } + + /* Consume the token. */ + c_parser_consume_token (parser); + } +} + /* Skip tokens until we have consumed an entire block, or until we have consumed a non-nested ';'. */ @@ -1978,6 +2027,13 @@ c_parser_translation_unit (c_parser *parser) "#pragma omp end declare target"); vec_safe_truncate (current_omp_declare_target_attribute, 0); } + if (vec_safe_length (current_omp_declare_variant_attribute)) + { + if (!errorcount) + error ("% without corresponding " + "%"); + vec_safe_truncate (current_omp_declare_variant_attribute, 0); + } if (vec_safe_length (current_omp_begin_assumes)) { if (!errorcount) @@ -2111,6 +2167,8 @@ static void c_parser_handle_directive_omp_attributes (tree &, vec *&, vec *); static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec *); static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool); +static tree omp_start_variant_function (c_declarator *, tree); +static void omp_finish_variant_function (tree, tree, tree); /* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */ @@ -3037,6 +3095,21 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions"); c_push_function_context (); } + + /* If we're in an OpenMP "begin declare variant" block, the + name in the declarator refers to the base function. We need + to save that and modify the declarator to have the mangled + name for the variant function instead. */ + tree dv_base = NULL_TREE; + tree dv_ctx = NULL_TREE; + if (!vec_safe_is_empty (current_omp_declare_variant_attribute)) + { + c_omp_declare_variant_attr a + = current_omp_declare_variant_attribute->last (); + dv_ctx = copy_list (a.selector); + dv_base = omp_start_variant_function (declarator, dv_ctx); + } + if (!start_function (specs, declarator, all_prefix_attrs)) { /* At this point we've consumed: @@ -3114,6 +3187,11 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus = startloc; location_t endloc = startloc; + /* If this function was in a "begin declare variant" block, + store the pointer back to the base function and fix up + the attributes for the middle end. */ + if (dv_base && current_function_decl != error_mark_node) + omp_finish_variant_function (current_function_decl, dv_base, dv_ctx); /* If the definition was marked with __RTL, use the RTL parser now, consuming the function body. */ @@ -26984,6 +27062,20 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) goto fail; ctx = omp_check_context_selector (match_loc, ctx, OMP_CTX_DECLARE_VARIANT); + + /* The OpenMP spec says the merging rules for enclosing + "begin declare variant" contexts apply to "declare variant + directives" -- the term it uses to refer to both directive + forms. */ + if (ctx != error_mark_node + && !vec_safe_is_empty (current_omp_declare_variant_attribute)) + { + c_omp_declare_variant_attr a + = current_omp_declare_variant_attribute->last (); + tree outer_ctx = a.selector; + ctx = omp_merge_context_selectors (match_loc, outer_ctx, ctx, + OMP_CTX_DECLARE_VARIANT); + } if (ctx != error_mark_node && variant != error_mark_node) { if (TREE_CODE (variant) != FUNCTION_DECL) @@ -27384,6 +27476,87 @@ c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, clauses[0].type = CPP_PRAGMA; } +/* This is consistent with the C++ front end. */ + +#if !defined (NO_DOT_IN_LABEL) +#define JOIN_STR "." +#elif !defined (NO_DOLLAR_IN_LABEL) +#define JOIN_STR "$" +#else +#define JOIN_STR "_" +#endif + +/* Helper function for OpenMP "begin declare variant" directives. + Function definitions inside the construct need to have their names + mangled according to the context selector CTX. The DECLARATOR is + modified in place to point to a new identifier; the original name of + the function is returned. */ +static tree +omp_start_variant_function (c_declarator *declarator, tree ctx) +{ + c_declarator *id = declarator; + while (id->kind != cdk_id) + { + id = id->declarator; + gcc_assert (id); + } + tree name = id->u.id.id; + id->u.id.id = omp_mangle_variant_name (name, ctx, JOIN_STR); + return name; +} + +/* Helper function for OpenMP "begin declare variant" directives. Now + that we have a DECL for the variant function, and BASE_NAME for the + base function, add an "omp declare variant base" attribute pointing + at CTX to the base decl, and an "omp declare variant variant" + attribute to the variant DECL. */ +static void +omp_finish_variant_function (tree decl, tree base_name, tree ctx) +{ + /* First look up BASE_NAME and ensure it matches DECL. */ + tree base_decl = lookup_name (base_name); + if (base_decl == error_mark_node) + base_decl = NULL_TREE; + if (!base_decl) + { + error_at (DECL_SOURCE_LOCATION (decl), + "no previous declaration of base function"); + return; + } + + if (!comptypes (TREE_TYPE (decl), TREE_TYPE (base_decl))) + { + error_at (DECL_SOURCE_LOCATION (decl), + "variant function definition does not match previous " + "declaration of %qE", base_decl); + return; + } + + /* Now set the attributes on the base and variant decls for the middle + end. */ + omp_check_for_duplicate_variant (DECL_SOURCE_LOCATION (decl), + base_decl, ctx); + tree construct + = omp_get_context_selector_list (ctx, OMP_TRAIT_SET_CONSTRUCT); + omp_mark_declare_variant (DECL_SOURCE_LOCATION (decl), decl, construct); + tree attrs = DECL_ATTRIBUTES (base_decl); + tree match_loc_node + = maybe_wrap_with_location (integer_zero_node, + DECL_SOURCE_LOCATION (base_decl)); + tree loc_node = tree_cons (match_loc_node, integer_zero_node, + build_tree_list (match_loc_node, + integer_zero_node)); + attrs = tree_cons (get_identifier ("omp declare variant base"), + tree_cons (decl, ctx, loc_node), attrs); + DECL_ATTRIBUTES (base_decl) = attrs; + + /* Variant functions are essentially anonymous and cannot be referenced + outside the compilation unit. */ + TREE_PUBLIC (decl) = 0; + DECL_COMDAT (decl) = 0; +} + + /* D should be C_TOKEN_VEC from omp::decl attribute. If it contains a threadprivate, groupprivate, allocate or declare target directive, return true and parse it for DECL. */ @@ -27616,7 +27789,9 @@ c_parser_omp_declare_target (c_parser *parser) /* OpenMP 5.1 #pragma omp begin assumes clauses[optseq] new-line - #pragma omp begin declare target clauses[optseq] new-line */ + #pragma omp begin declare target clauses[optseq] new-line + + #pragma omp begin declare variant (match context-selector) new-line */ #define OMP_BEGIN_DECLARE_TARGET_CLAUSE_MASK \ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE) \ @@ -27656,10 +27831,74 @@ c_parser_omp_begin (c_parser *parser) indirect }; vec_safe_push (current_omp_declare_target_attribute, attr); } + else if (strcmp (p, "variant") == 0) + { + c_parser_consume_token (parser); + const char *clause = ""; + matching_parens parens; + location_t match_loc = c_parser_peek_token (parser)->location; + if (c_parser_next_token_is (parser, CPP_NAME)) + { + tree id = c_parser_peek_token (parser)->value; + clause = IDENTIFIER_POINTER (id); + } + if (strcmp (clause, "match") != 0) + { + c_parser_error (parser, "expected %"); + c_parser_skip_to_pragma_eol (parser); + return; + } + + c_parser_consume_token (parser); + + if (!parens.require_open (parser)) + { + c_parser_skip_to_pragma_eol (parser, false); + return; + } + + tree ctx = + c_parser_omp_context_selector_specification (parser, NULL_TREE); + if (ctx != error_mark_node) + ctx = omp_check_context_selector (match_loc, ctx, + OMP_CTX_BEGIN_DECLARE_VARIANT); + + if (ctx != error_mark_node + && !vec_safe_is_empty (current_omp_declare_variant_attribute)) + { + c_omp_declare_variant_attr a + = current_omp_declare_variant_attribute->last (); + tree outer_ctx = a.selector; + ctx = omp_merge_context_selectors (match_loc, outer_ctx, ctx, + OMP_CTX_BEGIN_DECLARE_VARIANT); + } + + if (ctx == error_mark_node + || !omp_context_selector_matches (ctx, NULL_TREE, false, true)) + { + /* The context is either invalid or cannot possibly match. + In the latter case the spec says all code in the begin/end + sequence will be elided. In the former case we'll get bogus + errors from trying to parse it without a valid context to + use for name-mangling, so elide that too. */ + c_parser_skip_to_pragma_eol (parser, false); + c_parser_skip_to_pragma_omp_end_declare_variant (parser); + return; + } + else + { + bool attr_syntax = parser->in_omp_attribute_pragma != NULL; + c_omp_declare_variant_attr a = { attr_syntax, ctx }; + vec_safe_push (current_omp_declare_variant_attribute, a); + } + + parens.require_close (parser); + c_parser_skip_to_pragma_eol (parser); + } else { - c_parser_error (parser, "expected %"); - c_parser_skip_to_pragma_eol (parser); + c_parser_error (parser, "expected % or %"); + c_parser_skip_to_pragma_eol (parser, false); } } else if (strcmp (p, "assumes") == 0) @@ -27672,7 +27911,8 @@ c_parser_omp_begin (c_parser *parser) } else { - c_parser_error (parser, "expected % or %"); + c_parser_error (parser, "expected %, " + "%, or %"); c_parser_skip_to_pragma_eol (parser); } } @@ -27681,7 +27921,8 @@ c_parser_omp_begin (c_parser *parser) #pragma omp end declare target OpenMP 5.1 - #pragma omp end assumes */ + #pragma omp end assumes + #pragma omp end declare variant new-line */ static void c_parser_omp_end (c_parser *parser) @@ -27694,44 +27935,74 @@ c_parser_omp_end (c_parser *parser) if (strcmp (p, "declare") == 0) { c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_NAME) - && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value), - "target") == 0) - c_parser_consume_token (parser); + p = ""; + if (c_parser_next_token_is (parser, CPP_NAME)) + p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "target") == 0) + { + c_parser_consume_token (parser); + bool attr_syntax = parser->in_omp_attribute_pragma != NULL; + c_parser_skip_to_pragma_eol (parser); + if (!vec_safe_length (current_omp_declare_target_attribute)) + error_at (loc, "%<#pragma omp end declare target%> without " + "corresponding %<#pragma omp declare target%> or " + "%<#pragma omp begin declare target%>"); + else + { + c_omp_declare_target_attr + a = current_omp_declare_target_attribute->pop (); + if (a.attr_syntax != attr_syntax) + { + if (a.attr_syntax) + error_at (loc, + "%qs in attribute syntax terminated " + "with %qs in pragma syntax", + a.device_type >= 0 ? "begin declare target" + : "declare target", + "end declare target"); + else + error_at (loc, + "%qs in pragma syntax terminated " + "with %qs in attribute syntax", + a.device_type >= 0 ? "begin declare target" + : "declare target", + "end declare target"); + } + } + } + else if (strcmp (p, "variant") == 0) + { + c_parser_consume_token (parser); + bool attr_syntax = parser->in_omp_attribute_pragma != NULL; + c_parser_skip_to_pragma_eol (parser); + if (!vec_safe_length (current_omp_declare_variant_attribute)) + error_at (loc, "%<#pragma omp end declare variant%> without " + "corresponding %<#pragma omp begin declare variant%>"); + else + { + c_omp_declare_variant_attr + a = current_omp_declare_variant_attribute->pop (); + if (a.attr_syntax != attr_syntax) + { + if (a.attr_syntax) + error_at (loc, + "% in attribute syntax " + "terminated with " + "% in pragma syntax"); + else + error_at (loc, + "% in pragma syntax " + "terminated with " + "% in attribute syntax"); + } + } + } else { - c_parser_error (parser, "expected %"); + c_parser_error (parser, "expected % or %"); c_parser_skip_to_pragma_eol (parser); return; } - bool attr_syntax = parser->in_omp_attribute_pragma != NULL; - c_parser_skip_to_pragma_eol (parser); - if (!vec_safe_length (current_omp_declare_target_attribute)) - error_at (loc, "%<#pragma omp end declare target%> without " - "corresponding %<#pragma omp declare target%> or " - "%<#pragma omp begin declare target%>"); - else - { - c_omp_declare_target_attr - a = current_omp_declare_target_attribute->pop (); - if (a.attr_syntax != attr_syntax) - { - if (a.attr_syntax) - error_at (loc, - "%qs in attribute syntax terminated " - "with %qs in pragma syntax", - a.device_type >= 0 ? "begin declare target" - : "declare target", - "end declare target"); - else - error_at (loc, - "%qs in pragma syntax terminated " - "with %qs in attribute syntax", - a.device_type >= 0 ? "begin declare target" - : "declare target", - "end declare target"); - } - } } else if (strcmp (p, "assumes") == 0) { From patchwork Mon Feb 10 18:07:25 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sandra Loosemore X-Patchwork-Id: 106293 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5A3D73857349 for ; Mon, 10 Feb 2025 18:10:28 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5A3D73857349 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.a=rsa-sha256 header.s=20230601 header.b=TI4YS0+Q X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-io1-xd2b.google.com (mail-io1-xd2b.google.com [IPv6:2607:f8b0:4864:20::d2b]) by sourceware.org (Postfix) with ESMTPS id 100CF385AC1D for ; Mon, 10 Feb 2025 18:07:57 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 100CF385AC1D Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=baylibre.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 100CF385AC1D Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::d2b ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210877; cv=none; b=u659l/okF1xJ6l0/lH/G8B7S93IAyqmZutRQNAurjQ2Uc995E1xpVayTjutrgAIQ+50aQvpr+47+DPSjMUoqjYR0XWYGU54OxwtU/ZO4bb35FGbEKDw/vitImcD7GhpXE+sS89AJ6oxRLLguVJMxHPzWBqOidMxy7B+lH0QaHGQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1739210877; c=relaxed/simple; bh=YTlhbjPXnNOTcu6sCTBf+/EiNUyViO3z1yq/L5Mdzd0=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=l5EwyAKFp0eLVZM0OhyZIDUn+AuAoTcSiPbQaM31ljkwO0FwowjftgPPMirxiuVd9mW53eM7esVAwR6c0PJDxFohBCQBFNTw1/QE7kbCqtmtu2ioAZEvj3dXDNHJosdAHAGaEKmlhG/k+VzDElREE86XqXGABINyQrjJywrtUSo= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 100CF385AC1D Received: by mail-io1-xd2b.google.com with SMTP id ca18e2360f4ac-855183fdcafso45783639f.1 for ; Mon, 10 Feb 2025 10:07:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1739210876; x=1739815676; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=YEFVLNKByccJ0dCRybwJclhTwkOjlg28ypCiyOlZQ4w=; b=TI4YS0+Qz1HG3guEKitFet8QDiqavi91Vl2rqfQapw5zOjRK/JB3Bd4lkk92NtXypB d/fUc/kMmXvEcuO1s8awMwUfev516RYoA5q/im+4CpSEcPjLX0z1/hqg0ecnp+j3/x3L J6C9oaO/3LK9OlFcVDajcKPGuKUkBWZEir8D3Ac61ExlnCfHwxVAPM7K+qBO/S1cCxHo D4SyRMFRtPfyfg9GFMCXywAg1BV17BSyIhysVVRfoNosWsNGdnSd17rF6jrdEqD7yXmG DcLv7m0sGVBMz2TGEjcqOJzmIEKR8JYoi5iSOvs3KD6Do8Y7gieAvblaq5uzFLSNbIaz knqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739210876; x=1739815676; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=YEFVLNKByccJ0dCRybwJclhTwkOjlg28ypCiyOlZQ4w=; b=VOzjWb0avedHL/0xb3zQgJsZVHUwcxHpfcPcnnSaj6wxYw2kuY58w1eXGPi7wa9sml AZwrB0ZE3ObamUb8NrIH1YwqyVJws4go8A/bNFUL0NsetFNVRYdTQNc2c8b2tT22OUN2 LP05FyiEKdbzIWgdA9iljUGAirrNzVZkjk9WPkATwjrfuprRlBsgQxmYFbsirl6rUaCK sxDIxVs3jGyRPtg47i08+/VBRU3SWpTqfAztpfVA3D6H/56n2LB3qOb9ka/krPLDLfeB saL8IXJa7Ymcn+i8fT2T5Cim4zbCMRjIilxpKi4fv+lBeGpFjbaAsSE9M7vUR0kr51Sg o5FA== X-Gm-Message-State: AOJu0YwkMMHejGvUiJOW3TpR32Pp9xd0Fxw7jb+zLZSHU5EsdpxzZ32B maPexVmVVR7lZIPGdb5Wp2A1UiODdawJqEr5nIGp6dTCW3lNGuO6lmvDS4OXgg+lmKNArvXqkHQ v X-Gm-Gg: ASbGncvkPksF95RH1/oAg78bSMETIlFky5BpmuW3MvTYDqS4l2+duqN6cAcLxUdcnbs +bzaXzC0Ns3syPmJZ/mzdecu3VfD8LznPCt+Jy+qS1wDjnUScQUNiUM0CDc+k6pdcAR/zHIgziT Gm+g6sqYjI9PM8GnQGd+4P1nZ6+pt7RE/KHPYdo+P2n1Hnqakm7UNtPjkN4sLpvSx5vw4p6OVJf R/g82kqqY78z5BP5xpNkMsAMhStSVeu+3NaNwaxjNEVgg+EntZ6tv3f6kjQWkXX0AahANdLDLJ2 0pVnPIoSP8MyfdVKWRGb/aeLUCE= X-Google-Smtp-Source: AGHT+IFsuHSN7jBlAyRBq6UWYziMqmtP2Ni8oWQcGdaGXrrqxMwyR07PrJ587dxqI+TzQmUJs/oBnQ== X-Received: by 2002:a05:6e02:3a08:b0:3cf:c7bc:4523 with SMTP id e9e14a558f8ab-3d16f41ed9amr2453835ab.6.1739210875559; Mon, 10 Feb 2025 10:07:55 -0800 (PST) Received: from pondscum.hsd1.co.comcast.net ([2601:281:d901:97c0::af71]) by smtp.gmail.com with ESMTPSA id e9e14a558f8ab-3d13d83c967sm19615365ab.45.2025.02.10.10.07.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 10 Feb 2025 10:07:54 -0800 (PST) From: Sandra Loosemore To: gcc-patches@gcc.gnu.org Cc: jakub@redhat.com, tburnus@baylibre.com Subject: [PATCH 7/7] OpenMP: C/C++ common testcases for "omp begin declare variant" Date: Mon, 10 Feb 2025 11:07:25 -0700 Message-Id: <20250210180725.2076678-8-sloosemore@baylibre.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250210180725.2076678-1-sloosemore@baylibre.com> References: <20250210180725.2076678-1-sloosemore@baylibre.com> MIME-Version: 1.0 X-Spam-Status: No, score=-12.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org gcc/testsuite/ChangeLog * c-c++-common/gomp/delim-declare-variant-1.c: New. * c-c++-common/gomp/delim-declare-variant-2.c: New. * c-c++-common/gomp/delim-declare-variant-3.c: New. * c-c++-common/gomp/delim-declare-variant-4.c: New. * c-c++-common/gomp/delim-declare-variant-5.c: New. * c-c++-common/gomp/delim-declare-variant-6.c: New. * c-c++-common/gomp/delim-declare-variant-7.c: New. libgomp/ChangeLog * testsuite/libgomp.c-c++-common/delim-declare-variant-1.c: New. --- .../gomp/delim-declare-variant-1.c | 55 ++++++++++++++ .../gomp/delim-declare-variant-2.c | 66 +++++++++++++++++ .../gomp/delim-declare-variant-3.c | 50 +++++++++++++ .../gomp/delim-declare-variant-4.c | 31 ++++++++ .../gomp/delim-declare-variant-5.c | 26 +++++++ .../gomp/delim-declare-variant-6.c | 71 +++++++++++++++++++ .../gomp/delim-declare-variant-7.c | 27 +++++++ .../delim-declare-variant-1.c | 45 ++++++++++++ 8 files changed, 371 insertions(+) create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-1.c create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-2.c create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-4.c create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-5.c create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c create mode 100644 gcc/testsuite/c-c++-common/gomp/delim-declare-variant-7.c create mode 100644 libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-1.c b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-1.c new file mode 100644 index 00000000000..28cac0d6550 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-1.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-gimple" } */ + +/* Check basic functionality for the delimited form of "declare variant" + - no error re duplicate definitions + - variants are registered and correctly resolved at call site. */ + +int foo (int a) +{ + return a; +} + +int bar (int x) +{ + return x; +} + +#pragma omp begin declare variant match (construct={target}) +int foo (int a) +{ + return a + 1; +} + +int bar (int x) +{ + return x * 2; +} +#pragma omp end declare variant + +/* Because of the high score value, this variant for "bar" should always be + selected even when the one above also matches. */ +#pragma omp begin declare variant match (implementation={vendor(score(10000):"gnu")}) +int bar (int x) +{ + return x * 4; +} +#pragma omp end declare variant + +int main (void) +{ + if (foo (42) != 42) __builtin_abort (); + if (bar (3) != 12) __builtin_abort (); +#pragma omp target + { + if (foo (42) != 43) __builtin_abort (); + if (bar (3) != 12) __builtin_abort (); + } +} + +/* { dg-final { scan-tree-dump-times "omp declare variant base \\(foo.ompvariant." 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "omp declare variant base \\(bar.ompvariant." 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "foo \\(42\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "foo\\.ompvariant. \\(42\\)" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "bar \\(3\\)" 0 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "bar\\.ompvariant. \\(3\\)" 2 "gimple" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-2.c b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-2.c new file mode 100644 index 00000000000..03bfe274626 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-2.c @@ -0,0 +1,66 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-foffload=disable -fdump-tree-original" } */ + +/* Check for elision of preprocessed code in a begin/end declare variant + construct when it can be determined at parse time that the selector + can never match. */ + +int foobar (int x, int y) +{ + return x * y; +} + +int baz (int x) +{ + return x; +} + +#pragma omp begin declare variant match (implementation={vendor("acme")}) /* { dg-warning "unknown property" } */ +int foobar (int x, int y) +{ + random junk that would ordinarily cause a parse error; + return x + y; +} +#pragma omp end declare variant + +#pragma omp begin declare variant match (device={kind(fpga)}) +int foobar (int x, int y) +{ + random junk that would ordinarily cause a parse error; + return x + y; +} +#pragma omp end declare variant + +/* Per the OpenMP specification, elision only happens when the implementation + or device selectors cannot match; the user/condition selector doesn't + matter for this. */ +#pragma omp begin declare variant match (user={condition (0)}) +int foobar (int x, int y) +{ + return x + y; +} +#pragma omp end declare variant + +/* Check that we're finding the right "omp end declare variant" when + constructs are nested. */ +#pragma omp begin declare variant match (implementation={vendor("acme")}) /* { dg-warning "unknown property" } */ + #pragma omp begin declare variant match (device={kind(fpga)}) + int baz (int x) + { + random junk that would ordinarily cause a parse error; + return x + 1; + } + #pragma omp end declare variant + #pragma omp begin declare variant match (device={kind(host)}) + int baz (int x) + { + random junk that would ordinarily cause a parse error; + return x + 2; + } + #pragma omp end declare variant +#pragma omp end declare variant + +/* { dg-final { scan-tree-dump-times "foobar.ompvariant" 1 "original" } } */ +/* { dg-final { scan-tree-dump-not "baz.ompvariant" "original" } } */ + + diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c new file mode 100644 index 00000000000..63d10d72ea9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-3.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ + +/* Check that an error is diagnosed when a function defined in a + "begin declare variant" construct doesn't have a visible declaration + at that point. + + The spec is not completely clear on this; it says the base function must be + "declared elsewhere without an associated declare variant directive", + without defining what "elsewhere" means. Particularly in C++ it would be + incorrect to inject such a declaration at the point of the variant + definition (think of a variant for a class method that is defined with a + qualified name outside of the class declaration, for instance). The C++ + front end could differentiate between cases where base declaration injection + is allowed vs not, but for now it seems simplest just to require that a + definition always be visible. */ + +/* This declaration of baz is incompatible with the variant below. */ +extern double baz (double, double); + +/* This is not a function at all. */ +extern int quux; + +#pragma omp begin declare variant match (construct={target}) +int foo (int a) /* { dg-error "no previous declaration of base function" } */ +{ + return a + 1; +} + +int bar (int x) /* { dg-error "no previous declaration of base function" } */ +{ + return x * 2; +} + +int baz (int x) /* { dg-error "variant function definition does not match previous declaration of .baz." } */ +{ + return x * 2; +} + +int quux (int x, int y) /* { dg-error "variant function definition does not match previous declaration of .quux." } */ +{ + return x + y; +} +#pragma omp end declare variant + +/* This later definition of foo doesn't count for resolving the variant + above. */ +int foo (int a) +{ + return a; +} diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-4.c b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-4.c new file mode 100644 index 00000000000..f6726abefd6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-4.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ + +/* Check that a proper error is diagnosed if an "omp begin declare variant" + construct has an invalid selector, and that this causes the whole variant + to be skipped over rather than a duplicate definition error. */ + +int foo (int a) +{ + return a; +} + +#pragma omp begin declare variant match (construct=target) /* { dg-error "expected '\{' before 'target'" } */ +int foo (int a) +{ + return a + 1; +} + +#pragma omp end declare variant + +int bar (int x) +{ + return x; +} + +#pragma omp begin declare variant match (gibberish = {blah(1)}) /* { dg-error "expected context selector set name" } */ +int bar (int x) +{ + return x + 2; +} + +#pragma omp end declare variant diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-5.c b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-5.c new file mode 100644 index 00000000000..4e1645bbca8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-5.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ + +/* Check that the simd trait is rejected in the match clause for + "begin declare variant". */ + +int foo (int a) +{ + return a; +} + +int bar (int x) +{ + return x; +} + +#pragma omp begin declare variant match (construct={target, simd}) /* { dg-error "the 'simd' selector is not permitted" } */ +int foo (int a) +{ + return a + 1; +} + +int bar (int x) +{ + return x * 2; +} +#pragma omp end declare variant diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c new file mode 100644 index 00000000000..9b03b00fde9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-6.c @@ -0,0 +1,71 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-additional-options "-fdump-tree-gimple -foffload=disable" } */ + +/* Test merging of context selectors for nested "begin declare variant" + directives. + + The spec (TR12) says: "the effective context selectors of the outer + directive are appended do the context selector of the inner directive to + form the effective context selector of the inner directive. If a + trait-set-selector is present on both directives, the trait-selector list of + the outer directive is appended to the trait-selector list of the inner + directive after equivalent trait-selectors have been removed from the outer + list." */ + +int f1 (int x) { return x; } +int f2 (int x) { return x; } +int f3 (int x) { return x; } +int f4 (int x) { return x; } +int f5 (int x) { return x; } + +/* Check that duplicate traits can be detected, even when the properties + use different forms. (If these were considered different, it would + trigger an error instead.) */ +#pragma omp begin declare variant match (implementation={vendor(gnu)}) +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +int f1 (int x) { return -x; } +#pragma omp end declare variant +#pragma omp end declare variant + +#pragma omp begin declare variant match (implementation={vendor("gnu")}) +#pragma omp begin declare variant match (implementation={vendor(gnu)}) +int f2 (int x) { return -x; } +#pragma omp end declare variant +#pragma omp end declare variant + +/* Check that non-duplicate traits are collected from both inner and outer. */ + +#pragma omp begin declare variant match (device={kind("host")}) +#pragma omp begin declare variant match (device={arch("x86_64")}) +int f3 (int x) { return -x; } +#pragma omp end declare variant +#pragma omp end declare variant +/* { dg-final { scan-tree-dump "f3\\.ompvariant.*kind \\(.host.\\)" "gimple" } } */ +/* { dg-final { scan-tree-dump "f3\\.ompvariant.*arch \\(.x86_64.\\)" "gimple" } } */ + +/* Check that traits for construct selectors merge as expected. */ + +#pragma omp begin declare variant match (construct={parallel, for}) +#pragma omp begin declare variant match (construct={teams}) +int f4 (int x) { return -x; } +#pragma omp end declare variant +#pragma omp end declare variant +/* { dg-final { scan-tree-dump "f4\\.ompvariant.*teams, parallel, for" "gimple" } } */ + +/* Check that multiple trait sets are collected. */ + +extern int flag; + +#pragma omp begin declare variant match (construct={parallel, for}) +#pragma omp begin declare variant match (construct={teams}) +#pragma omp begin declare variant match (user={condition(flag)}) +#pragma omp begin declare variant match (device={kind("host")}) +int f5 (int x) { return -x; } +#pragma omp end declare variant +#pragma omp end declare variant +#pragma omp end declare variant +#pragma omp end declare variant +/* { dg-final { scan-tree-dump "f5\\.ompvariant.*teams, parallel, for" "gimple" } } */ +/* { dg-final { scan-tree-dump "f5\\.ompvariant.*flag" "gimple" } } */ +/* { dg-final { scan-tree-dump "f5\\.ompvariant.*kind \\(.host.\\)" "gimple" } } */ + diff --git a/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-7.c b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-7.c new file mode 100644 index 00000000000..49a1d530cca --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/delim-declare-variant-7.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-fdump-tree-gimple" } */ + +/* Test that merging of context selectors from an enclosing "begin declare + variant" directive applies to nested regular "declare variant" directives + (not just nested "begin declare variant", which is tested elsewhere). */ + +extern int foo1 (int); +extern int foo2 (int); + +#pragma omp begin declare variant match (implementation={vendor(gnu)}) + +#pragma omp declare variant (foo1) \ + match (construct={parallel,for}) +#pragma omp declare variant (foo2) \ + match (device={kind(any)}) +extern int foo (int); + +#pragma omp end declare variant + +int foo (int x) +{ + return x + 42; +} + +/* { dg-final { scan-tree-dump-times "omp declare variant base" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "vendor \\(.gnu.\\)" 2 "gimple" } } */ diff --git a/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c b/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c new file mode 100644 index 00000000000..916f8a6510f --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/delim-declare-variant-1.c @@ -0,0 +1,45 @@ +/* Check basic functionality for the delimited form of "declare variant" + - no error re duplicate definitions + - variants are registered and correctly resolved at call site. */ + +int foo (int a) +{ + return a; +} + +int bar (int x) +{ + return x; +} + +#pragma omp begin declare variant match (construct={target}) +int foo (int a) +{ + return a + 1; +} + +int bar (int x) +{ + return x * 2; +} +#pragma omp end declare variant + +/* Because of the high score value, this variant for "bar" should always be + selected even when the one above also matches. */ +#pragma omp begin declare variant match (implementation={vendor(score(10000):"gnu")}) +int bar (int x) +{ + return x * 4; +} +#pragma omp end declare variant + +int main (void) +{ + if (foo (42) != 42) __builtin_abort (); + if (bar (3) != 12) __builtin_abort (); +#pragma omp target + { + if (foo (42) != 43) __builtin_abort (); + if (bar (3) != 12) __builtin_abort (); + } +}