//===- llvm/unittests/Frontend/OpenMPDecompositionTest.cpp ----------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Frontend/OpenMP/ClauseT.h" #include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" #include "llvm/Frontend/OpenMP/OMP.h" #include "gtest/gtest.h" #include <iterator> #include <optional> #include <sstream> #include <string> #include <tuple> #include <type_traits> #include <utility> // The actual tests start at comment "--- Test" below. // Create simple instantiations of all clauses to allow manual construction // of clauses, and implement emitting of a directive with clauses to a string. // // The tests then follow the pattern // 1. Create a list of clauses. // 2. Pass them, together with a construct, to the decomposition class. // 3. Extract individual resulting leaf constructs with clauses applied // to them. // 4. Convert them to strings and compare with expected outputs. namespace omp { struct TypeTy { … }; // placeholder struct ExprTy { … }; // placeholder IdTy; } // namespace omp namespace tomp::type { template <> struct ObjectT<omp::IdTy, omp::ExprTy> { … }; } // namespace tomp::type namespace omp { List; Object; namespace clause { DefinedOperator; ProcedureDesignator; ReductionOperator; AcqRel; Acquire; AdjustArgs; Affinity; Aligned; Align; Allocate; Allocator; AppendArgs; AtomicDefaultMemOrder; At; Bind; Capture; Collapse; Compare; Copyin; Copyprivate; Defaultmap; Default; Depend; Destroy; Detach; Device; DeviceType; DistSchedule; Doacross; DynamicAllocators; Enter; Exclusive; Fail; Filter; Final; Firstprivate; From; Full; Grainsize; HasDeviceAddr; Hint; If; Inbranch; Inclusive; Indirect; Init; InReduction; IsDevicePtr; Lastprivate; Linear; Link; Map; Match; Mergeable; Message; Nocontext; Nogroup; Nontemporal; Notinbranch; Novariants; Nowait; NumTasks; NumTeams; NumThreads; OmpxAttribute; OmpxBare; OmpxDynCgroupMem; Ordered; Order; Partial; Priority; Private; ProcBind; Read; Reduction; Relaxed; Release; ReverseOffload; Safelen; Schedule; SeqCst; Severity; Shared; Simdlen; Simd; Sizes; TaskReduction; ThreadLimit; Threads; To; UnifiedAddress; UnifiedSharedMemory; Uniform; Unknown; Untied; Update; UseDeviceAddr; UseDevicePtr; UsesAllocators; Use; Weak; When; Write; } // namespace clause struct Helper { … }; Clause; ConstructDecomposition; DirectiveWithClauses; } // namespace omp struct StringifyClause { … }; std::string stringify(const omp::DirectiveWithClauses &DWC) { … } // --- Tests ---------------------------------------------------------- namespace red { // Make it easier to construct reduction operators from built-in intrinsics. omp::clause::ReductionOperator makeOp(omp::clause::DefinedOperator::IntrinsicOperator Op) { … } } // namespace red namespace { usingnamespacellvm::omp; class OpenMPDecompositionTest : public testing::Test { … }; // PRIVATE // [5.2:111:5-7] // Directives: distribute, do, for, loop, parallel, scope, sections, simd, // single, target, task, taskloop, teams // // [5.2:340:1-2] // (1) The effect of the 1 private clause is as if it is applied only to the // innermost leaf construct that permits it. TEST_F(OpenMPDecompositionTest, Private1) { … } TEST_F(OpenMPDecompositionTest, Private2) { … } // FIRSTPRIVATE // [5.2:112:5-7] // Directives: distribute, do, for, parallel, scope, sections, single, target, // task, taskloop, teams // // [5.2:340:3-20] // (3) The effect of the firstprivate clause is as if it is applied to one or // more leaf constructs as follows: // (5) To the distribute construct if it is among the constituent constructs; // (6) To the teams construct if it is among the constituent constructs and the // distribute construct is not; // (8) To a worksharing construct that accepts the clause if one is among the // constituent constructs; // (9) To the taskloop construct if it is among the constituent constructs; // (10) To the parallel construct if it is among the constituent constructs and // neither a taskloop construct nor a worksharing construct that accepts // the clause is among them; // (12) To the target construct if it is among the constituent constructs and // the same list item neither appears in a lastprivate clause nor is the // base variable or base pointer of a list item that appears in a map // clause. // // (15) If the parallel construct is among the constituent constructs and the // effect is not as if the firstprivate clause is applied to it by the above // rules, then the effect is as if the shared clause with the same list item is // applied to the parallel construct. // (17) If the teams construct is among the constituent constructs and the // effect is not as if the firstprivate clause is applied to it by the above // rules, then the effect is as if the shared clause with the same list item is // applied to the teams construct. TEST_F(OpenMPDecompositionTest, Firstprivate1) { … } TEST_F(OpenMPDecompositionTest, Firstprivate2) { … } TEST_F(OpenMPDecompositionTest, Firstprivate3) { … } TEST_F(OpenMPDecompositionTest, Firstprivate4) { … } TEST_F(OpenMPDecompositionTest, Firstprivate5) { … } TEST_F(OpenMPDecompositionTest, Firstprivate6) { … } TEST_F(OpenMPDecompositionTest, Firstprivate7) { … } // LASTPRIVATE // [5.2:115:7-8] // Directives: distribute, do, for, loop, sections, simd, taskloop // // [5.2:340:21-30] // (21) The effect of the lastprivate clause is as if it is applied to all leaf // constructs that permit the clause. // (22) If the parallel construct is among the constituent constructs and the // list item is not also specified in the firstprivate clause, then the effect // of the lastprivate clause is as if the shared clause with the same list item // is applied to the parallel construct. // (24) If the teams construct is among the constituent constructs and the list // item is not also specified in the firstprivate clause, then the effect of the // lastprivate clause is as if the shared clause with the same list item is // applied to the teams construct. // (27) If the target construct is among the constituent constructs and the list // item is not the base variable or base pointer of a list item that appears in // a map clause, the effect of the lastprivate clause is as if the same list // item appears in a map clause with a map-type of tofrom. TEST_F(OpenMPDecompositionTest, Lastprivate1) { … } TEST_F(OpenMPDecompositionTest, Lastprivate2) { … } TEST_F(OpenMPDecompositionTest, Lastprivate3) { … } // SHARED // [5.2:110:5-6] // Directives: parallel, task, taskloop, teams // // [5.2:340:31-32] // (31) The effect of the shared, default, thread_limit, or order clause is as // if it is applied to all leaf constructs that permit the clause. TEST_F(OpenMPDecompositionTest, Shared1) { … } // DEFAULT // [5.2:109:5-6] // Directives: parallel, task, taskloop, teams // // [5.2:340:31-32] // (31) The effect of the shared, default, thread_limit, or order clause is as // if it is applied to all leaf constructs that permit the clause. TEST_F(OpenMPDecompositionTest, Default1) { … } // THREAD_LIMIT // [5.2:277:14-15] // Directives: target, teams // // [5.2:340:31-32] // (31) The effect of the shared, default, thread_limit, or order clause is as // if it is applied to all leaf constructs that permit the clause. TEST_F(OpenMPDecompositionTest, ThreadLimit1) { … } // ORDER // [5.2:234:3-4] // Directives: distribute, do, for, loop, simd // // [5.2:340:31-32] // (31) The effect of the shared, default, thread_limit, or order clause is as // if it is applied to all leaf constructs that permit the clause. TEST_F(OpenMPDecompositionTest, Order1) { … } // ALLOCATE // [5.2:178:7-9] // Directives: allocators, distribute, do, for, parallel, scope, sections, // single, target, task, taskgroup, taskloop, teams // // [5.2:340:33-35] // (33) The effect of the allocate clause is as if it is applied to all leaf // constructs that permit the clause and to which a data-sharing attribute // clause that may create a private copy of the same list item is applied. TEST_F(OpenMPDecompositionTest, Allocate1) { … } TEST_F(OpenMPDecompositionTest, Allocate2) { … } TEST_F(OpenMPDecompositionTest, Allocate3) { … } TEST_F(OpenMPDecompositionTest, Allocate4) { … } TEST_F(OpenMPDecompositionTest, Allocate5) { … } TEST_F(OpenMPDecompositionTest, Allocate6) { … } // REDUCTION // [5.2:134:17-18] // Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams // // [5.2:340-341:36-13] // (36) The effect of the reduction clause is as if it is applied to all leaf // constructs that permit the clause, except for the following constructs: // (1) The parallel construct, when combined with the sections, // worksharing-loop, loop, or taskloop construct; and // (3) The teams construct, when combined with the loop construct. // (4) For the parallel and teams constructs above, the effect of the reduction // clause instead is as if each list item or, for any list item that is an array // item, its corresponding base array or base pointer appears in a shared clause // for the construct. // (6) If the task reduction-modifier is specified, the effect is as if it only // modifies the behavior of the reduction clause on the innermost leaf construct // that accepts the modifier (see Section 5.5.8). // (8) If the inscan reduction-modifier is specified, the effect is as if it // modifies the behavior of the reduction clause on all constructs of the // combined construct to which the clause is applied and that accept the // modifier. // (10) If a list item in a reduction clause on a combined target construct does // not have the same base variable or base pointer as a list item in a map // clause on the construct, then the effect is as if the list item in the // reduction clause appears as a list item in a map clause with a map-type of // tofrom. TEST_F(OpenMPDecompositionTest, Reduction1) { … } TEST_F(OpenMPDecompositionTest, Reduction2) { … } TEST_F(OpenMPDecompositionTest, Reduction3) { … } TEST_F(OpenMPDecompositionTest, Reduction4) { … } TEST_F(OpenMPDecompositionTest, Reduction5) { … } TEST_F(OpenMPDecompositionTest, Reduction6) { … } TEST_F(OpenMPDecompositionTest, Reduction7) { … } // IF // [5.2:72:7-9] // Directives: cancel, parallel, simd, target, target data, target enter data, // target exit data, target update, task, taskloop // // [5.2:72:15-18] // (15) For combined or composite constructs, the if clause only applies to the // semantics of the construct named in the directive-name-modifier. // (16) For a combined or composite construct, if no directive-name-modifier is // specified then the if clause applies to all constituent constructs to which // an if clause can apply. TEST_F(OpenMPDecompositionTest, If1) { … } TEST_F(OpenMPDecompositionTest, If2) { … } // LINEAR // [5.2:118:1-2] // Directives: declare simd, do, for, simd // // [5.2:341:15-22] // (15.1) The effect of the linear clause is as if it is applied to the // innermost leaf construct. // (15.2) Additionally, if the list item is not the iteration variable of a simd // or worksharing-loop SIMD construct, the effect on the outer leaf constructs // is as if the list item was specified in firstprivate and lastprivate clauses // on the combined or composite construct, with the rules specified above // applied. // (19) If a list item of the linear clause is the iteration variable of a simd // or worksharing-loop SIMD construct and it is not declared in the construct, // the effect on the outer leaf constructs is as if the list item was specified // in a lastprivate clause on the combined or composite construct with the rules // specified above applied. TEST_F(OpenMPDecompositionTest, Linear1) { … } // NOWAIT // [5.2:308:11-13] // Directives: dispatch, do, for, interop, scope, sections, single, target, // target enter data, target exit data, target update, taskwait, workshare // // [5.2:341:23] // (23) The effect of the nowait clause is as if it is applied to the outermost // leaf construct that permits it. TEST_F(OpenMPDecompositionTest, Nowait1) { … } // --- // Check that "simd linear(x)" does not fail despite the implied "firstprivate" // (which "simd" does not allow). TEST_F(OpenMPDecompositionTest, Misc1) { … } } // namespace