From patchwork Tue Feb 15 10:26:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tobias Burnus X-Patchwork-Id: 1593044 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Jychb43vsz9s0B for ; Tue, 15 Feb 2022 21:26:55 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3098C3857C6B for ; Tue, 15 Feb 2022 10:26:53 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa2.mentor.iphmx.com (esa2.mentor.iphmx.com [68.232.141.98]) by sourceware.org (Postfix) with ESMTPS id 8F6013858D20; Tue, 15 Feb 2022 10:26:19 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8F6013858D20 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com IronPort-SDR: txPIMUois6VHc3okde1ndcuPfzd7eGGinxzE/fQAQJ3gDFaTWdrhkyPNh1ve2lbwPhPoaK+er9 z2rS/YK47mDej2wu8oyCmqATpTVHPBVm0ULsYw/T6gfdiy0jURgL7Tqfz+IEKEU8zR6p9E4ntt zbCCWx5eieyrixW9qwX3vAsC3SL3lxll3JP24oGj1TJNetT7mrcBA74y62uV4zSIlQS48Sk23g lBIADx47/A7CSWUs2iuPxHRB08UhDCfMRDX8ccBLoMMOZsHdS2SGb1DmRL0rzE0UY+ywIZYoY7 YXyDQI1lImq8aJWc3lcV3HVv X-IronPort-AV: E=Sophos;i="5.88,370,1635235200"; d="diff'?scan'208";a="72014807" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 15 Feb 2022 02:26:17 -0800 IronPort-SDR: A7S3031AzQcm7rxeRoDqVFxYpEMSF5fL2aZZ1g0+3sbmnvGCBVhH12/zFFkpi8jTZyKSddCdpI lLLwx0kpSTafRS9gXFW211YHGq+M50QH+tIkjBerr4PrY/1tau05nxrdPY4+yM4xP7CkccdrYB A30Ltv2tqR/Qlb0V39bLtxg1yrQEcXXY4g2RX91Xk4EXDAYpnsQwtH7TfynmMI5ItkgnUdsavc 97oFo/Ie1BKX9Yl1aJ75glsm3Hv4kg6bYOEEFGSakocpGSkLu8w+IktuFs0x7puiUEhjTV9YG1 tX8= Message-ID: <5c942a0f-cc45-1919-af0b-57aa0fff8733@codesourcery.com> Date: Tue, 15 Feb 2022 11:26:12 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.6.0 Content-Language: en-US To: gcc-patches , fortran , Jakub Jelinek From: Tobias Burnus Subject: [Patch] Fortran/OpenMP: Fix depend-clause handling X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: SVR-IES-MBX-08.mgc.mentorg.com (139.181.222.8) To svr-ies-mbx-01.mgc.mentorg.com (139.181.222.1) X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Vollweiler, Marcel" Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" As found by Marcel, the 'depend' clause was differently handled in 'omp depobj(...) depend(...)' and in 'omp task depend(...)'. The problem was that for a scalar pointer, depobj depended on the pointer address - while task depended on the pointer-target address. If one now combines depobj and direct var dependency, the dependency is on different addresses, such that the dependency is not honored. Marcel's example is testsuite/libgomp.fortran/depend-4.f90. (Thanks for the report!) I think in the real world, the problem is not that big as most code either uses depobj or a variable and does not mix them. Likewise, using the address of a temporary variable (cf. below) will also usually work in terms of dependency. The attached patch does: - depend clause (as used by task etc): For scalar allocatable/pointer, add another dereference - For depobj (which handles the depend clause by itself) - Fix array(element) handling by coping the depend-clause. Before the result was 'D.123 = var; depobj = &D.123;' which is really not intended. - Several issues related to optional and allocatable/pointer. OK for mainline? Does backporting to GCC 11 make sense? Thanks, Tobias PS: * I use the address of the pointer target (and not of the internal pointer) variable, which requires that the address to which the pointer points makes sense. (Technically, NULL and random value should be also okay, I think.) * Likewise for 'allocatable' - which also requires that the memory is allocated. * OpenMP uses the word 'storage location', which is defined according to the last F2F meeting as: "A data storage block in memory." (OpenMP Spec Pull Req. #3228) * On the OpenMP side, there is the discussion to have a dependency on an integer value instead of an address. (Motivated by the question whether ptr = NULL; (void*)0x123; etc. should be valid or not.) → OpenMP Spec Issue #3226 ----------------- Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht München, HRB 106955 Fortran/OpenMP: Fix depend-clause handling gcc/fortran/ChangeLog: * trans-openmp.cc (gfc_trans_omp_clauses, gfc_trans_omp_depobj): Depend on the proper addr, for ptr/alloc depend on pointee. libgomp/ChangeLog: * testsuite/libgomp.fortran/depend-4.f90: New test. gcc/testsuite/ChangeLog: * gfortran.dg/gomp/depend-4.f90: New test. gcc/fortran/trans-openmp.cc | 45 ++++- gcc/testsuite/gfortran.dg/gomp/depend-4.f90 | 240 +++++++++++++++++++++++++ libgomp/testsuite/libgomp.fortran/depend-4.f90 | 107 +++++++++++ 3 files changed, 386 insertions(+), 6 deletions(-) diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 0eba0b3c3e1..a85f11e52d4 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -2890,7 +2890,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses, gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl))); decl = build_fold_indirect_ref (decl); } - else if (DECL_P (decl)) + else if (n->sym->attr.allocatable || n->sym->attr.pointer) + decl = build_fold_indirect_ref (decl); + if (DECL_P (decl)) TREE_ADDRESSABLE (decl) = 1; OMP_CLAUSE_DECL (node) = decl; } @@ -5508,12 +5510,43 @@ gfc_trans_omp_depobj (gfc_code *code) if (n) { tree var; - if (n->expr) - var = gfc_convert_expr_to_tree (&block, n->expr); + if (n->expr && n->expr->ref->u.ar.type != AR_FULL) + { + gfc_init_se (&se, NULL); + if (n->expr->ref->u.ar.type == AR_ELEMENT) + { + gfc_conv_expr_reference (&se, n->expr); + var = se.expr; + } + else + { + gfc_conv_expr_descriptor (&se, n->expr); + var = gfc_conv_array_data (se.expr); + } + gfc_add_block_to_block (&block, &se.pre); + gfc_add_block_to_block (&block, &se.post); + gcc_assert (POINTER_TYPE_P (TREE_TYPE (var))); + } else - var = gfc_get_symbol_decl (n->sym); - if (!POINTER_TYPE_P (TREE_TYPE (var))) - var = gfc_build_addr_expr (NULL, var); + { + var = gfc_get_symbol_decl (n->sym); + if (POINTER_TYPE_P (TREE_TYPE (var)) + && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (var)))) + var = build_fold_indirect_ref (var); + if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (var))) + { + var = gfc_conv_descriptor_data_get (var); + gcc_assert (POINTER_TYPE_P (TREE_TYPE (var))); + } + else if ((n->sym->attr.allocatable || n->sym->attr.pointer) + && n->sym->attr.optional) + var = build_fold_indirect_ref (var); + else if (!POINTER_TYPE_P (TREE_TYPE (var))) + { + TREE_ADDRESSABLE (var) = 1; + var = gfc_build_addr_expr (NULL, var); + } + } depobj = save_expr (depobj); tree r = build_fold_indirect_ref_loc (loc, depobj); gfc_add_expr_to_block (&block, diff --git a/gcc/testsuite/gfortran.dg/gomp/depend-4.f90 b/gcc/testsuite/gfortran.dg/gomp/depend-4.f90 new file mode 100644 index 00000000000..d6686c1e48f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/depend-4.f90 @@ -0,0 +1,240 @@ +! { dg-do compile } +! { dg-additional-options "-fdump-tree-gimple -fdump-tree-original" } + +! Check that 'omp depobj's depend and 'omp task/... depend' depend on +! the same variable + +! For pointers, it depends on the address of the pointer target +! For allocatable, on the allocated memory address + +subroutine foo(dss, dsp, dsa, daa, daaa, daap, doss, dosp, dosa, doaa, doaaa, doaap) + !use omp_lib + use iso_c_binding, only: c_intptr_t + implicit none (type, external) + integer, parameter :: omp_depend_kind = 2*c_intptr_t + integer :: ss, sp, sa, aa(4), aaa(:), aap(:) + integer :: dss, dsp, dsa, daa(4), daaa(:), daap(:) + integer :: doss, dosp, dosa, doaa(4), doaaa(:), doaap(:) + optional :: doss, dosp, dosa, doaa, doaaa, doaap + allocatable :: sa, aaa, dsa, daaa, dosa, doaaa + pointer :: sp, aap, dsp, daap, dosp, doaap + + integer(omp_depend_kind) :: object(18) + integer(omp_depend_kind) :: elem(9) + + !$omp depobj(object(1)) depend(in: ss) + !$omp depobj(object(2)) depend(in: sp) + !$omp depobj(object(3)) depend(in: sa) + !$omp depobj(object(4)) depend(in: aa) + !$omp depobj(object(5)) depend(in: aaa) + !$omp depobj(object(6)) depend(in: aap) + !$omp depobj(object(7)) depend(in: dss) + !$omp depobj(object(8)) depend(in: dsp) + !$omp depobj(object(9)) depend(in: dsa) + !$omp depobj(object(10)) depend(in: daa) + !$omp depobj(object(11)) depend(in: daaa) + !$omp depobj(object(12)) depend(in: daap) + !$omp depobj(object(13)) depend(in: doss) + !$omp depobj(object(14)) depend(in: dosp) + !$omp depobj(object(15)) depend(in: dosa) + !$omp depobj(object(16)) depend(in: doaa) + !$omp depobj(object(17)) depend(in: doaaa) + !$omp depobj(object(18)) depend(in: doaap) + + !$omp depobj(elem(1)) depend(in: aa(2)) + !$omp depobj(elem(2)) depend(in: aaa(2)) + !$omp depobj(elem(3)) depend(in: aap(2)) + !$omp depobj(elem(4)) depend(in: daa(2)) + !$omp depobj(elem(5)) depend(in: daaa(2)) + !$omp depobj(elem(6)) depend(in: daap(2)) + !$omp depobj(elem(6)) depend(in: doaa(2)) + !$omp depobj(elem(8)) depend(in: doaaa(2)) + !$omp depobj(elem(9)) depend(in: doaap(2)) + + !$omp parallel + !$omp single + !$omp task depend(out: ss) + ss = 4 + !$omp end task + !$omp task depend(out: sp) + sp = 4 + !$omp end task + !$omp task depend(out: sa) + sa = 4 + !$omp end task + !$omp task depend(out: aa) + aa = 4 + !$omp end task + !$omp task depend(out: aaa) + aaa = 4 + !$omp end task + !$omp task depend(out: aap) + aap = 4 + !$omp end task + !$omp task depend(out: dss) + dss = 4 + !$omp end task + !$omp task depend(out: dsp) + dsp = 4 + !$omp end task + !$omp task depend(out: dsa) + dsa = 4 + !$omp end task + !$omp task depend(out: daa) + daa = 4 + !$omp end task + !$omp task depend(out: daaa) + daaa = 4 + !$omp end task + !$omp task depend(out: daap) + daap = 4 + !$omp end task + !$omp task depend(out: doss) + doss = 4 + !$omp end task + !$omp task depend(out: dosp) + dosp = 4 + !$omp end task + !$omp task depend(out: dosa) + dosa = 4 + !$omp end task + !$omp task depend(out: doaa) + doaa = 4 + !$omp end task + !$omp task depend(out: doaaa) + doaaa = 4 + !$omp end task + !$omp task depend(out: doaap) + doaap = 4 + !$omp end task + + !$omp task depend(out: aa(2)) + aa(2) = 4 + !$omp end task + !$omp task depend(out: aaa(2)) + aaa(2) = 4 + !$omp end task + !$omp task depend(out: aap(2)) + aap(2) = 4 + !$omp end task + !$omp task depend(out: daa(2)) + daa(2) = 4 + !$omp end task + !$omp task depend(out: daaa(2)) + daaa(2) = 4 + !$omp end task + !$omp task depend(out: daap(2)) + daap(2) = 4 + !$omp end task + !$omp task depend(out: doaa(2)) + doaa(2) = 4 + !$omp end task + !$omp task depend(out: doaaa(2)) + doaaa(2) = 4 + !$omp end task + !$omp task depend(out: doaap(2)) + doaap(2) = 4 + !$omp end task + !$omp end single + !$omp end parallel +end + +subroutine bar + implicit none (type, external) + integer :: depvar, x + + x = 7 + !$omp parallel + !$omp single + !$omp task depend(out: depvar) + x =5 + !$omp end task + !$omp task depend(in: depvar) + if (x /= 5) stop + !$omp end task + !$omp end single + !$omp end parallel +end + +! depvar - only used for dependency, but should still be used in depend: + +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:depvar\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(in:depvar\\)" 1 "original" } } + +! { dg-final { scan-tree-dump-times "&object\\\[0\\\] = &ss;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[1\\\] = sp;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[2\\\] = sa;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[3\\\] = &aa;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[4\\\] = .integer.kind=4.\\\[0:\\\] \\* restrict\\) aaa.data;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[5\\\] = .integer.kind=4.\\\[0:\\\] \\*\\) aap.data;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[6\\\] = dss;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[7\\\] = dsp;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[8\\\] = dsa;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[9\\\] = daa;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[10\\\] = .integer.kind=4.\\\[0:\\\] \\* restrict\\) daaa->data;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[11\\\] = .integer.kind=4.\\\[0:\\\] \\*\\) daap->data;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[12\\\] = doss;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[13\\\] = \\*dosp;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[14\\\] = \\*dosa;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[15\\\] = doaa;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[16\\\] = .integer.kind=4.\\\[0:\\\] \\* restrict\\) doaaa->data;" 1 "original" } } +! { dg-final { scan-tree-dump-times "&object\\\[17\\\] = .integer.kind=4.\\\[0:\\\] \\*\\) doaap->data;" 1 "original" } } + +! { dg-final { scan-tree-dump-times "&elem\\\[0\\\] = &aa\\\[1\\\];" 1 "original" } } +! { dg-final { scan-tree-dump-times "&elem\\\[1\\\] = &\\(\\*\\(integer.kind=4.\\\[0:\\\] \\* restrict\\) aaa.data\\)\\\[aaa.offset \\+ 2\\\];" 1 "original" } } +! { dg-final { scan-tree-dump-times "&elem\\\[2\\\] = \\(integer.kind=4. \\*\\) \\(aap.data \\+ .sizetype. \\(\\(aap.offset \\+ aap.dim\\\[0\\\].stride \\* 2\\) \\* aap.span\\)\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times "&elem\\\[3\\\] = &\\(\\*daa\\)\\\[1\\\];" 1 "original" } } +! { dg-final { scan-tree-dump-times "&elem\\\[4\\\] = &\\(\\*\\(integer.kind=4.\\\[0:\\\] \\* restrict\\) daaa->data\\)\\\[daaa->offset \\+ 2\\\];" 1 "original" } } +! { dg-final { scan-tree-dump-times "&elem\\\[5\\\] = \\(integer.kind=4. \\*\\) \\(daap->data \\+ .sizetype. \\(\\(daap->offset \\+ daap->dim\\\[0\\\].stride \\* 2\\) \\* daap->span\\)\\);" 1 "original" } } +! { dg-final { scan-tree-dump-times "&elem\\\[5\\\] = &\\(\\*doaa\\)\\\[1\\\];" 1 "original" } } +! { dg-final { scan-tree-dump-times "&elem\\\[7\\\] = &\\(\\*\\(integer.kind=4.\\\[0:\\\] \\* restrict\\) doaaa->data\\)\\\[doaaa->offset \\+ 2\\\];" 1 "original" } } +! { dg-final { scan-tree-dump-times "&elem\\\[8\\\] = \\(integer.kind=4. \\*\\) \\(doaap->data \\+ .sizetype. \\(\\(doaap->offset \\+ doaap->dim\\\[0\\\].stride \\* 2\\) \\* doaap->span\\)\\);" 1 "original" } } + +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:ss\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*sp\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*sa\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:aa\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aaa.data\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) aap.data\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*dss\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dsp\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dsa\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*daa\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) daaa->data\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) daap->data\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*doss\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dosp\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\*dosa\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*doaa\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) doaaa->data\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\*\\) doaap->data\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:aa\\\[1\\\]\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) aaa.data\\)\\\[aaa.offset \\+ 2\\\]\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\) \\*\\) \\(aap.data \\+ \\(sizetype\\) \\(\\(aap.offset \\+ aap.dim\\\[0\\\].stride \\* 2\\) \\* aap.span\\)\\)\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*daa\\)\\\[1\\\]\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) daaa->data\\)\\\[daaa->offset \\+ 2\\\]\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\) \\*\\) \\(daap->data \\+ \\(sizetype\\) \\(\\(daap->offset \\+ daap->dim\\\[0\\\].stride \\* 2\\) \\* daap->span\\)\\)\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*doaa\\)\\\[1\\\]\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\(\\*\\(integer\\(kind=4\\)\\\[0:\\\] \\* restrict\\) doaaa->data\\)\\\[doaaa->offset \\+ 2\\\]\\)" 1 "original" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:\\*\\(integer\\(kind=4\\) \\*\\) \\(doaap->data \\+ \\(sizetype\\) \\(\\(doaap->offset \\+ doaap->dim\\\[0\\\].stride \\* 2\\) \\* doaap->span\\)\\)\\)" 1 "original" } } + + +! gimple dump - check only those which are simple one-line checkable: + +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&ss\\) shared\\(ss\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:sp\\) shared\\(sp\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:sa\\) shared\\(sa\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&aa\\) shared\\(aa\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:dss\\) shared\\(dss\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:daa\\) shared\\(daa\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:doss\\) shared\\(doss\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:doaa\\) shared\\(doaa\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&aa\\\[1\\\]\\) shared\\(aa\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dsp;" 2 "gimple" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dsa;" 3 "gimple" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dosp;" 2 "gimple" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = \\*dosa;" 3 "gimple" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = doaaa->data;" 4 "gimple" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = doaap->data;" 4 "gimple" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = &\\(\\*daa\\)\\\[1\\\];" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = &\\(\\*doaa\\)\\\[1\\\];" 1 "gimple" } } diff --git a/libgomp/testsuite/libgomp.fortran/depend-4.f90 b/libgomp/testsuite/libgomp.fortran/depend-4.f90 new file mode 100644 index 00000000000..0dee2c6faf1 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/depend-4.f90 @@ -0,0 +1,107 @@ +! { dg-additional-options "-fdump-tree-gimple" } +! +! { dg-additional-sources my-usleep.c } +! { dg-prune-output "command-line option '-fintrinsic-modules-path=.*' is valid for Fortran but not for C" } +! +! Ensure that 'depend(...: var)' and 'depobj(...) depend(...: var)' +! depend on the same variable when 'var' is a pointer +! +program main + use omp_lib + use iso_c_binding + implicit none (external, type) + + interface + subroutine usleep(t) bind(C, name="my_usleep") + use iso_c_binding + integer(c_int), value :: t + end subroutine + end interface + + integer :: bbb + integer, target :: c + integer(omp_depend_kind) :: obj(2) + integer, pointer :: ppp + + integer :: x1, x2, x3 + + c = 42 + ppp => c + + if (.not. associated (ppp)) & + stop 0; + + x1 = 43 + x2 = 44 + x3 = 45 + !$omp depobj(obj(1)) depend(inout: ppp) + !$omp depobj(obj(2)) depend(in: bbb) + + !$omp parallel num_threads(5) + !$omp single + + !$omp task depend (out: ppp) + write (*,*) "task 1 (start)" + call usleep(40) + if (x1 /= 43) stop 11 + if (x2 /= 44) stop 12 + x1 = 11 + write (*,*) "task 1 (end)" + !$omp end task + + !$omp task depend(inout: ppp) + write (*,*) "task 2 (start)" + call usleep(30) + if (x1 /= 11) stop 21 + if (x2 /= 44) stop 22 + x1 = 111 + x2 = 222 + write (*,*) "task 2 (end)" + !$omp end task + + !$omp task depend(out: bbb) + write (*,*) "task 3 (start)" + call usleep(40) + if (x3 /= 45) stop 3 + x3 = 33 + write (*,*) "task 3 (end)" + !$omp end task + + !$omp task depend(depobj: obj(1), obj(2)) + write (*,*) "task 4 (start)" + if (x1 /= 111) stop 41 + if (x2 /= 222) stop 42 + if (x3 /= 33) stop 43 + call usleep(10) + x1 = 411 + x2 = 422 + x3 = 433 + write (*,*) "task 4 (end)" + !$omp end task + + !$omp task depend(in: ppp) + if (x1 /= 411) stop 51 + if (x2 /= 422) stop 52 + if (x3 /= 433) stop 53 + write (*,*) "task 5" + !$omp end task + + !$omp end single + !$omp end parallel + + ! expectation (task dependencies): + ! 1 - 2 \ + ! 4 - 5 + ! 3 ----/ + +end program main + +! Ensure that the pointer target address for ppp is taken +! but the address of bbb itself: + +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:ppp.\[0-9\]+\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(inout:ppp.\[0-9\]+\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(in:ppp.\[0-9\]+\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "#pragma omp task depend\\(out:&bbb\\)" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "MEM\\\[\[^\r\n]+\\\] = ppp.\[0-9_\]+;" 1 "gimple" } } +! { dg-final { scan-tree-dump-times "MEM\\\[\[^\r\n]+\\\] = &bbb;" 1 "gimple" } }