1be7c9e39SKrzysztof Parzyszek //===- llvm/unittests/Frontend/OpenMPDecompositionTest.cpp ----------------===// 2be7c9e39SKrzysztof Parzyszek // 3be7c9e39SKrzysztof Parzyszek // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4be7c9e39SKrzysztof Parzyszek // See https://llvm.org/LICENSE.txt for license information. 5be7c9e39SKrzysztof Parzyszek // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6be7c9e39SKrzysztof Parzyszek // 7be7c9e39SKrzysztof Parzyszek //===----------------------------------------------------------------------===// 8be7c9e39SKrzysztof Parzyszek 9be7c9e39SKrzysztof Parzyszek #include "llvm/ADT/ArrayRef.h" 10be7c9e39SKrzysztof Parzyszek #include "llvm/ADT/STLExtras.h" 11be7c9e39SKrzysztof Parzyszek #include "llvm/ADT/SmallVector.h" 12be7c9e39SKrzysztof Parzyszek #include "llvm/Frontend/OpenMP/ClauseT.h" 13be7c9e39SKrzysztof Parzyszek #include "llvm/Frontend/OpenMP/ConstructDecompositionT.h" 14be7c9e39SKrzysztof Parzyszek #include "llvm/Frontend/OpenMP/OMP.h" 15be7c9e39SKrzysztof Parzyszek #include "gtest/gtest.h" 16be7c9e39SKrzysztof Parzyszek 17be7c9e39SKrzysztof Parzyszek #include <iterator> 18be7c9e39SKrzysztof Parzyszek #include <optional> 19be7c9e39SKrzysztof Parzyszek #include <sstream> 20be7c9e39SKrzysztof Parzyszek #include <string> 21be7c9e39SKrzysztof Parzyszek #include <tuple> 22be7c9e39SKrzysztof Parzyszek #include <type_traits> 23be7c9e39SKrzysztof Parzyszek #include <utility> 24be7c9e39SKrzysztof Parzyszek 25be7c9e39SKrzysztof Parzyszek // The actual tests start at comment "--- Test" below. 26be7c9e39SKrzysztof Parzyszek 27be7c9e39SKrzysztof Parzyszek // Create simple instantiations of all clauses to allow manual construction 28be7c9e39SKrzysztof Parzyszek // of clauses, and implement emitting of a directive with clauses to a string. 29be7c9e39SKrzysztof Parzyszek // 30be7c9e39SKrzysztof Parzyszek // The tests then follow the pattern 31be7c9e39SKrzysztof Parzyszek // 1. Create a list of clauses. 32be7c9e39SKrzysztof Parzyszek // 2. Pass them, together with a construct, to the decomposition class. 33be7c9e39SKrzysztof Parzyszek // 3. Extract individual resulting leaf constructs with clauses applied 34be7c9e39SKrzysztof Parzyszek // to them. 35be7c9e39SKrzysztof Parzyszek // 4. Convert them to strings and compare with expected outputs. 36be7c9e39SKrzysztof Parzyszek 37be7c9e39SKrzysztof Parzyszek namespace omp { 38be7c9e39SKrzysztof Parzyszek struct TypeTy {}; // placeholder 39be7c9e39SKrzysztof Parzyszek struct ExprTy {}; // placeholder 40be7c9e39SKrzysztof Parzyszek using IdTy = std::string; 41be7c9e39SKrzysztof Parzyszek } // namespace omp 42be7c9e39SKrzysztof Parzyszek 43be7c9e39SKrzysztof Parzyszek namespace tomp::type { 44be7c9e39SKrzysztof Parzyszek template <> struct ObjectT<omp::IdTy, omp::ExprTy> { 45be7c9e39SKrzysztof Parzyszek const omp::IdTy &id() const { return name; } 46be7c9e39SKrzysztof Parzyszek const std::optional<omp::ExprTy> ref() const { return omp::ExprTy{}; } 47be7c9e39SKrzysztof Parzyszek 48be7c9e39SKrzysztof Parzyszek omp::IdTy name; 49be7c9e39SKrzysztof Parzyszek }; 50be7c9e39SKrzysztof Parzyszek } // namespace tomp::type 51be7c9e39SKrzysztof Parzyszek 52be7c9e39SKrzysztof Parzyszek namespace omp { 53be7c9e39SKrzysztof Parzyszek template <typename ElemTy> using List = tomp::type::ListT<ElemTy>; 54be7c9e39SKrzysztof Parzyszek 55be7c9e39SKrzysztof Parzyszek using Object = tomp::ObjectT<IdTy, ExprTy>; 56be7c9e39SKrzysztof Parzyszek 57be7c9e39SKrzysztof Parzyszek namespace clause { 58be7c9e39SKrzysztof Parzyszek using DefinedOperator = tomp::type::DefinedOperatorT<IdTy, ExprTy>; 59be7c9e39SKrzysztof Parzyszek using ProcedureDesignator = tomp::type::ProcedureDesignatorT<IdTy, ExprTy>; 60be7c9e39SKrzysztof Parzyszek using ReductionOperator = tomp::type::ReductionIdentifierT<IdTy, ExprTy>; 61be7c9e39SKrzysztof Parzyszek 62be7c9e39SKrzysztof Parzyszek using AcqRel = tomp::clause::AcqRelT<TypeTy, IdTy, ExprTy>; 63be7c9e39SKrzysztof Parzyszek using Acquire = tomp::clause::AcquireT<TypeTy, IdTy, ExprTy>; 64be7c9e39SKrzysztof Parzyszek using AdjustArgs = tomp::clause::AdjustArgsT<TypeTy, IdTy, ExprTy>; 65be7c9e39SKrzysztof Parzyszek using Affinity = tomp::clause::AffinityT<TypeTy, IdTy, ExprTy>; 66be7c9e39SKrzysztof Parzyszek using Aligned = tomp::clause::AlignedT<TypeTy, IdTy, ExprTy>; 67be7c9e39SKrzysztof Parzyszek using Align = tomp::clause::AlignT<TypeTy, IdTy, ExprTy>; 68be7c9e39SKrzysztof Parzyszek using Allocate = tomp::clause::AllocateT<TypeTy, IdTy, ExprTy>; 69be7c9e39SKrzysztof Parzyszek using Allocator = tomp::clause::AllocatorT<TypeTy, IdTy, ExprTy>; 70be7c9e39SKrzysztof Parzyszek using AppendArgs = tomp::clause::AppendArgsT<TypeTy, IdTy, ExprTy>; 71be7c9e39SKrzysztof Parzyszek using AtomicDefaultMemOrder = 72be7c9e39SKrzysztof Parzyszek tomp::clause::AtomicDefaultMemOrderT<TypeTy, IdTy, ExprTy>; 73be7c9e39SKrzysztof Parzyszek using At = tomp::clause::AtT<TypeTy, IdTy, ExprTy>; 74be7c9e39SKrzysztof Parzyszek using Bind = tomp::clause::BindT<TypeTy, IdTy, ExprTy>; 75be7c9e39SKrzysztof Parzyszek using Capture = tomp::clause::CaptureT<TypeTy, IdTy, ExprTy>; 76be7c9e39SKrzysztof Parzyszek using Collapse = tomp::clause::CollapseT<TypeTy, IdTy, ExprTy>; 77be7c9e39SKrzysztof Parzyszek using Compare = tomp::clause::CompareT<TypeTy, IdTy, ExprTy>; 78be7c9e39SKrzysztof Parzyszek using Copyin = tomp::clause::CopyinT<TypeTy, IdTy, ExprTy>; 79be7c9e39SKrzysztof Parzyszek using Copyprivate = tomp::clause::CopyprivateT<TypeTy, IdTy, ExprTy>; 80be7c9e39SKrzysztof Parzyszek using Defaultmap = tomp::clause::DefaultmapT<TypeTy, IdTy, ExprTy>; 81be7c9e39SKrzysztof Parzyszek using Default = tomp::clause::DefaultT<TypeTy, IdTy, ExprTy>; 82be7c9e39SKrzysztof Parzyszek using Depend = tomp::clause::DependT<TypeTy, IdTy, ExprTy>; 83be7c9e39SKrzysztof Parzyszek using Destroy = tomp::clause::DestroyT<TypeTy, IdTy, ExprTy>; 84be7c9e39SKrzysztof Parzyszek using Detach = tomp::clause::DetachT<TypeTy, IdTy, ExprTy>; 85be7c9e39SKrzysztof Parzyszek using Device = tomp::clause::DeviceT<TypeTy, IdTy, ExprTy>; 86be7c9e39SKrzysztof Parzyszek using DeviceType = tomp::clause::DeviceTypeT<TypeTy, IdTy, ExprTy>; 87be7c9e39SKrzysztof Parzyszek using DistSchedule = tomp::clause::DistScheduleT<TypeTy, IdTy, ExprTy>; 88be7c9e39SKrzysztof Parzyszek using Doacross = tomp::clause::DoacrossT<TypeTy, IdTy, ExprTy>; 89be7c9e39SKrzysztof Parzyszek using DynamicAllocators = 90be7c9e39SKrzysztof Parzyszek tomp::clause::DynamicAllocatorsT<TypeTy, IdTy, ExprTy>; 91be7c9e39SKrzysztof Parzyszek using Enter = tomp::clause::EnterT<TypeTy, IdTy, ExprTy>; 92be7c9e39SKrzysztof Parzyszek using Exclusive = tomp::clause::ExclusiveT<TypeTy, IdTy, ExprTy>; 93be7c9e39SKrzysztof Parzyszek using Fail = tomp::clause::FailT<TypeTy, IdTy, ExprTy>; 94be7c9e39SKrzysztof Parzyszek using Filter = tomp::clause::FilterT<TypeTy, IdTy, ExprTy>; 95be7c9e39SKrzysztof Parzyszek using Final = tomp::clause::FinalT<TypeTy, IdTy, ExprTy>; 96be7c9e39SKrzysztof Parzyszek using Firstprivate = tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>; 97be7c9e39SKrzysztof Parzyszek using From = tomp::clause::FromT<TypeTy, IdTy, ExprTy>; 98be7c9e39SKrzysztof Parzyszek using Full = tomp::clause::FullT<TypeTy, IdTy, ExprTy>; 99be7c9e39SKrzysztof Parzyszek using Grainsize = tomp::clause::GrainsizeT<TypeTy, IdTy, ExprTy>; 100be7c9e39SKrzysztof Parzyszek using HasDeviceAddr = tomp::clause::HasDeviceAddrT<TypeTy, IdTy, ExprTy>; 101be7c9e39SKrzysztof Parzyszek using Hint = tomp::clause::HintT<TypeTy, IdTy, ExprTy>; 102be7c9e39SKrzysztof Parzyszek using If = tomp::clause::IfT<TypeTy, IdTy, ExprTy>; 103be7c9e39SKrzysztof Parzyszek using Inbranch = tomp::clause::InbranchT<TypeTy, IdTy, ExprTy>; 104be7c9e39SKrzysztof Parzyszek using Inclusive = tomp::clause::InclusiveT<TypeTy, IdTy, ExprTy>; 105be7c9e39SKrzysztof Parzyszek using Indirect = tomp::clause::IndirectT<TypeTy, IdTy, ExprTy>; 106be7c9e39SKrzysztof Parzyszek using Init = tomp::clause::InitT<TypeTy, IdTy, ExprTy>; 107be7c9e39SKrzysztof Parzyszek using InReduction = tomp::clause::InReductionT<TypeTy, IdTy, ExprTy>; 108be7c9e39SKrzysztof Parzyszek using IsDevicePtr = tomp::clause::IsDevicePtrT<TypeTy, IdTy, ExprTy>; 109be7c9e39SKrzysztof Parzyszek using Lastprivate = tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>; 110be7c9e39SKrzysztof Parzyszek using Linear = tomp::clause::LinearT<TypeTy, IdTy, ExprTy>; 111be7c9e39SKrzysztof Parzyszek using Link = tomp::clause::LinkT<TypeTy, IdTy, ExprTy>; 112be7c9e39SKrzysztof Parzyszek using Map = tomp::clause::MapT<TypeTy, IdTy, ExprTy>; 113be7c9e39SKrzysztof Parzyszek using Match = tomp::clause::MatchT<TypeTy, IdTy, ExprTy>; 114be7c9e39SKrzysztof Parzyszek using Mergeable = tomp::clause::MergeableT<TypeTy, IdTy, ExprTy>; 115be7c9e39SKrzysztof Parzyszek using Message = tomp::clause::MessageT<TypeTy, IdTy, ExprTy>; 116be7c9e39SKrzysztof Parzyszek using Nocontext = tomp::clause::NocontextT<TypeTy, IdTy, ExprTy>; 117be7c9e39SKrzysztof Parzyszek using Nogroup = tomp::clause::NogroupT<TypeTy, IdTy, ExprTy>; 118be7c9e39SKrzysztof Parzyszek using Nontemporal = tomp::clause::NontemporalT<TypeTy, IdTy, ExprTy>; 119be7c9e39SKrzysztof Parzyszek using Notinbranch = tomp::clause::NotinbranchT<TypeTy, IdTy, ExprTy>; 120be7c9e39SKrzysztof Parzyszek using Novariants = tomp::clause::NovariantsT<TypeTy, IdTy, ExprTy>; 121be7c9e39SKrzysztof Parzyszek using Nowait = tomp::clause::NowaitT<TypeTy, IdTy, ExprTy>; 122be7c9e39SKrzysztof Parzyszek using NumTasks = tomp::clause::NumTasksT<TypeTy, IdTy, ExprTy>; 123be7c9e39SKrzysztof Parzyszek using NumTeams = tomp::clause::NumTeamsT<TypeTy, IdTy, ExprTy>; 124be7c9e39SKrzysztof Parzyszek using NumThreads = tomp::clause::NumThreadsT<TypeTy, IdTy, ExprTy>; 125be7c9e39SKrzysztof Parzyszek using OmpxAttribute = tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy>; 126be7c9e39SKrzysztof Parzyszek using OmpxBare = tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy>; 127be7c9e39SKrzysztof Parzyszek using OmpxDynCgroupMem = tomp::clause::OmpxDynCgroupMemT<TypeTy, IdTy, ExprTy>; 128be7c9e39SKrzysztof Parzyszek using Ordered = tomp::clause::OrderedT<TypeTy, IdTy, ExprTy>; 129be7c9e39SKrzysztof Parzyszek using Order = tomp::clause::OrderT<TypeTy, IdTy, ExprTy>; 130be7c9e39SKrzysztof Parzyszek using Partial = tomp::clause::PartialT<TypeTy, IdTy, ExprTy>; 131be7c9e39SKrzysztof Parzyszek using Priority = tomp::clause::PriorityT<TypeTy, IdTy, ExprTy>; 132be7c9e39SKrzysztof Parzyszek using Private = tomp::clause::PrivateT<TypeTy, IdTy, ExprTy>; 133be7c9e39SKrzysztof Parzyszek using ProcBind = tomp::clause::ProcBindT<TypeTy, IdTy, ExprTy>; 134be7c9e39SKrzysztof Parzyszek using Read = tomp::clause::ReadT<TypeTy, IdTy, ExprTy>; 135be7c9e39SKrzysztof Parzyszek using Reduction = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>; 136be7c9e39SKrzysztof Parzyszek using Relaxed = tomp::clause::RelaxedT<TypeTy, IdTy, ExprTy>; 137be7c9e39SKrzysztof Parzyszek using Release = tomp::clause::ReleaseT<TypeTy, IdTy, ExprTy>; 138be7c9e39SKrzysztof Parzyszek using ReverseOffload = tomp::clause::ReverseOffloadT<TypeTy, IdTy, ExprTy>; 139be7c9e39SKrzysztof Parzyszek using Safelen = tomp::clause::SafelenT<TypeTy, IdTy, ExprTy>; 140be7c9e39SKrzysztof Parzyszek using Schedule = tomp::clause::ScheduleT<TypeTy, IdTy, ExprTy>; 141be7c9e39SKrzysztof Parzyszek using SeqCst = tomp::clause::SeqCstT<TypeTy, IdTy, ExprTy>; 142be7c9e39SKrzysztof Parzyszek using Severity = tomp::clause::SeverityT<TypeTy, IdTy, ExprTy>; 143be7c9e39SKrzysztof Parzyszek using Shared = tomp::clause::SharedT<TypeTy, IdTy, ExprTy>; 144be7c9e39SKrzysztof Parzyszek using Simdlen = tomp::clause::SimdlenT<TypeTy, IdTy, ExprTy>; 145be7c9e39SKrzysztof Parzyszek using Simd = tomp::clause::SimdT<TypeTy, IdTy, ExprTy>; 146be7c9e39SKrzysztof Parzyszek using Sizes = tomp::clause::SizesT<TypeTy, IdTy, ExprTy>; 147be7c9e39SKrzysztof Parzyszek using TaskReduction = tomp::clause::TaskReductionT<TypeTy, IdTy, ExprTy>; 148be7c9e39SKrzysztof Parzyszek using ThreadLimit = tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy>; 149be7c9e39SKrzysztof Parzyszek using Threads = tomp::clause::ThreadsT<TypeTy, IdTy, ExprTy>; 150be7c9e39SKrzysztof Parzyszek using To = tomp::clause::ToT<TypeTy, IdTy, ExprTy>; 151be7c9e39SKrzysztof Parzyszek using UnifiedAddress = tomp::clause::UnifiedAddressT<TypeTy, IdTy, ExprTy>; 152be7c9e39SKrzysztof Parzyszek using UnifiedSharedMemory = 153be7c9e39SKrzysztof Parzyszek tomp::clause::UnifiedSharedMemoryT<TypeTy, IdTy, ExprTy>; 154be7c9e39SKrzysztof Parzyszek using Uniform = tomp::clause::UniformT<TypeTy, IdTy, ExprTy>; 155be7c9e39SKrzysztof Parzyszek using Unknown = tomp::clause::UnknownT<TypeTy, IdTy, ExprTy>; 156be7c9e39SKrzysztof Parzyszek using Untied = tomp::clause::UntiedT<TypeTy, IdTy, ExprTy>; 157be7c9e39SKrzysztof Parzyszek using Update = tomp::clause::UpdateT<TypeTy, IdTy, ExprTy>; 158be7c9e39SKrzysztof Parzyszek using UseDeviceAddr = tomp::clause::UseDeviceAddrT<TypeTy, IdTy, ExprTy>; 159be7c9e39SKrzysztof Parzyszek using UseDevicePtr = tomp::clause::UseDevicePtrT<TypeTy, IdTy, ExprTy>; 160be7c9e39SKrzysztof Parzyszek using UsesAllocators = tomp::clause::UsesAllocatorsT<TypeTy, IdTy, ExprTy>; 161be7c9e39SKrzysztof Parzyszek using Use = tomp::clause::UseT<TypeTy, IdTy, ExprTy>; 162be7c9e39SKrzysztof Parzyszek using Weak = tomp::clause::WeakT<TypeTy, IdTy, ExprTy>; 163be7c9e39SKrzysztof Parzyszek using When = tomp::clause::WhenT<TypeTy, IdTy, ExprTy>; 164be7c9e39SKrzysztof Parzyszek using Write = tomp::clause::WriteT<TypeTy, IdTy, ExprTy>; 165be7c9e39SKrzysztof Parzyszek } // namespace clause 166be7c9e39SKrzysztof Parzyszek 167be7c9e39SKrzysztof Parzyszek struct Helper { 168be7c9e39SKrzysztof Parzyszek std::optional<Object> getBaseObject(const Object &object) { 169be7c9e39SKrzysztof Parzyszek return std::nullopt; 170be7c9e39SKrzysztof Parzyszek } 171be7c9e39SKrzysztof Parzyszek std::optional<Object> getLoopIterVar() { return std::nullopt; } 172be7c9e39SKrzysztof Parzyszek }; 173be7c9e39SKrzysztof Parzyszek 174be7c9e39SKrzysztof Parzyszek using Clause = tomp::ClauseT<TypeTy, IdTy, ExprTy>; 175be7c9e39SKrzysztof Parzyszek using ConstructDecomposition = tomp::ConstructDecompositionT<Clause, Helper>; 176be7c9e39SKrzysztof Parzyszek using DirectiveWithClauses = tomp::DirectiveWithClauses<Clause>; 177be7c9e39SKrzysztof Parzyszek } // namespace omp 178be7c9e39SKrzysztof Parzyszek 179be7c9e39SKrzysztof Parzyszek struct StringifyClause { 180be7c9e39SKrzysztof Parzyszek static std::string join(const omp::List<std::string> &Strings) { 181be7c9e39SKrzysztof Parzyszek std::stringstream Stream; 182be7c9e39SKrzysztof Parzyszek for (const auto &[Index, String] : llvm::enumerate(Strings)) { 183be7c9e39SKrzysztof Parzyszek if (Index != 0) 184be7c9e39SKrzysztof Parzyszek Stream << ", "; 185be7c9e39SKrzysztof Parzyszek Stream << String; 186be7c9e39SKrzysztof Parzyszek } 187be7c9e39SKrzysztof Parzyszek return Stream.str(); 188be7c9e39SKrzysztof Parzyszek } 189be7c9e39SKrzysztof Parzyszek 190be7c9e39SKrzysztof Parzyszek static std::string to_str(llvm::omp::Directive D) { 191be7c9e39SKrzysztof Parzyszek return getOpenMPDirectiveName(D).str(); 192be7c9e39SKrzysztof Parzyszek } 193be7c9e39SKrzysztof Parzyszek static std::string to_str(llvm::omp::Clause C) { 194be7c9e39SKrzysztof Parzyszek return getOpenMPClauseName(C).str(); 195be7c9e39SKrzysztof Parzyszek } 196be7c9e39SKrzysztof Parzyszek static std::string to_str(const omp::TypeTy &Type) { return "type"; } 197be7c9e39SKrzysztof Parzyszek static std::string to_str(const omp::ExprTy &Expr) { return "expr"; } 198be7c9e39SKrzysztof Parzyszek static std::string to_str(const omp::Object &Obj) { return Obj.id(); } 199be7c9e39SKrzysztof Parzyszek 200be7c9e39SKrzysztof Parzyszek template <typename U> 201be7c9e39SKrzysztof Parzyszek static std::enable_if_t<std::is_enum_v<llvm::remove_cvref_t<U>>, std::string> 202be7c9e39SKrzysztof Parzyszek to_str(U &&Item) { 203be7c9e39SKrzysztof Parzyszek return std::to_string(llvm::to_underlying(Item)); 204be7c9e39SKrzysztof Parzyszek } 205be7c9e39SKrzysztof Parzyszek 206be7c9e39SKrzysztof Parzyszek template <typename U> static std::string to_str(const omp::List<U> &Items) { 207be7c9e39SKrzysztof Parzyszek omp::List<std::string> Names; 208be7c9e39SKrzysztof Parzyszek llvm::transform(Items, std::back_inserter(Names), 209be7c9e39SKrzysztof Parzyszek [](auto &&S) { return to_str(S); }); 210be7c9e39SKrzysztof Parzyszek return "(" + join(Names) + ")"; 211be7c9e39SKrzysztof Parzyszek } 212be7c9e39SKrzysztof Parzyszek 213be7c9e39SKrzysztof Parzyszek template <typename U> 214be7c9e39SKrzysztof Parzyszek static std::string to_str(const std::optional<U> &Item) { 215be7c9e39SKrzysztof Parzyszek if (Item) 216be7c9e39SKrzysztof Parzyszek return to_str(*Item); 217be7c9e39SKrzysztof Parzyszek return ""; 218be7c9e39SKrzysztof Parzyszek } 219be7c9e39SKrzysztof Parzyszek 220be7c9e39SKrzysztof Parzyszek template <typename... Us, size_t... Is> 221be7c9e39SKrzysztof Parzyszek static std::string to_str(const std::tuple<Us...> &Tuple, 222be7c9e39SKrzysztof Parzyszek std::index_sequence<Is...>) { 223be7c9e39SKrzysztof Parzyszek omp::List<std::string> Strings; 224be7c9e39SKrzysztof Parzyszek (Strings.push_back(to_str(std::get<Is>(Tuple))), ...); 225be7c9e39SKrzysztof Parzyszek return "(" + join(Strings) + ")"; 226be7c9e39SKrzysztof Parzyszek } 227be7c9e39SKrzysztof Parzyszek 228be7c9e39SKrzysztof Parzyszek template <typename U> 229be7c9e39SKrzysztof Parzyszek static std::enable_if_t<llvm::remove_cvref_t<U>::EmptyTrait::value, 230be7c9e39SKrzysztof Parzyszek std::string> 231be7c9e39SKrzysztof Parzyszek to_str(U &&Item) { 232be7c9e39SKrzysztof Parzyszek return ""; 233be7c9e39SKrzysztof Parzyszek } 234be7c9e39SKrzysztof Parzyszek 235be7c9e39SKrzysztof Parzyszek template <typename U> 236be7c9e39SKrzysztof Parzyszek static std::enable_if_t<llvm::remove_cvref_t<U>::IncompleteTrait::value, 237be7c9e39SKrzysztof Parzyszek std::string> 238be7c9e39SKrzysztof Parzyszek to_str(U &&Item) { 239be7c9e39SKrzysztof Parzyszek return ""; 240be7c9e39SKrzysztof Parzyszek } 241be7c9e39SKrzysztof Parzyszek 242be7c9e39SKrzysztof Parzyszek template <typename U> 243be7c9e39SKrzysztof Parzyszek static std::enable_if_t<llvm::remove_cvref_t<U>::WrapperTrait::value, 244be7c9e39SKrzysztof Parzyszek std::string> 245be7c9e39SKrzysztof Parzyszek to_str(U &&Item) { 246be7c9e39SKrzysztof Parzyszek // For a wrapper, stringify the wrappee, and only add parentheses if 247be7c9e39SKrzysztof Parzyszek // there aren't any already. 248be7c9e39SKrzysztof Parzyszek std::string Str = to_str(Item.v); 249be7c9e39SKrzysztof Parzyszek if (!Str.empty()) { 250be7c9e39SKrzysztof Parzyszek if (Str.front() == '(' && Str.back() == ')') 251be7c9e39SKrzysztof Parzyszek return Str; 252be7c9e39SKrzysztof Parzyszek } 253be7c9e39SKrzysztof Parzyszek return "(" + to_str(Item.v) + ")"; 254be7c9e39SKrzysztof Parzyszek } 255be7c9e39SKrzysztof Parzyszek 256be7c9e39SKrzysztof Parzyszek template <typename U> 257be7c9e39SKrzysztof Parzyszek static std::enable_if_t<llvm::remove_cvref_t<U>::TupleTrait::value, 258be7c9e39SKrzysztof Parzyszek std::string> 259be7c9e39SKrzysztof Parzyszek to_str(U &&Item) { 260be7c9e39SKrzysztof Parzyszek constexpr size_t TupleSize = 261be7c9e39SKrzysztof Parzyszek std::tuple_size_v<llvm::remove_cvref_t<decltype(Item.t)>>; 262be7c9e39SKrzysztof Parzyszek return to_str(Item.t, std::make_index_sequence<TupleSize>{}); 263be7c9e39SKrzysztof Parzyszek } 264be7c9e39SKrzysztof Parzyszek 265be7c9e39SKrzysztof Parzyszek template <typename U> 266be7c9e39SKrzysztof Parzyszek static std::enable_if_t<llvm::remove_cvref_t<U>::UnionTrait::value, 267be7c9e39SKrzysztof Parzyszek std::string> 268be7c9e39SKrzysztof Parzyszek to_str(U &&Item) { 269be7c9e39SKrzysztof Parzyszek return std::visit([](auto &&S) { return to_str(S); }, Item.u); 270be7c9e39SKrzysztof Parzyszek } 271be7c9e39SKrzysztof Parzyszek 272be7c9e39SKrzysztof Parzyszek StringifyClause(const omp::Clause &C) 273be7c9e39SKrzysztof Parzyszek // Rely on content stringification to emit enclosing parentheses. 274be7c9e39SKrzysztof Parzyszek : Str(to_str(C.id) + to_str(C)) {} 275be7c9e39SKrzysztof Parzyszek 276be7c9e39SKrzysztof Parzyszek std::string Str; 277be7c9e39SKrzysztof Parzyszek }; 278be7c9e39SKrzysztof Parzyszek 279be7c9e39SKrzysztof Parzyszek std::string stringify(const omp::DirectiveWithClauses &DWC) { 280be7c9e39SKrzysztof Parzyszek std::stringstream Stream; 281be7c9e39SKrzysztof Parzyszek 282be7c9e39SKrzysztof Parzyszek Stream << getOpenMPDirectiveName(DWC.id).str(); 283be7c9e39SKrzysztof Parzyszek for (const omp::Clause &C : DWC.clauses) 284be7c9e39SKrzysztof Parzyszek Stream << ' ' << StringifyClause(C).Str; 285be7c9e39SKrzysztof Parzyszek 286be7c9e39SKrzysztof Parzyszek return Stream.str(); 287be7c9e39SKrzysztof Parzyszek } 288be7c9e39SKrzysztof Parzyszek 289be7c9e39SKrzysztof Parzyszek // --- Tests ---------------------------------------------------------- 290be7c9e39SKrzysztof Parzyszek 2914ec4a8e7SKrzysztof Parzyszek namespace red { 2924ec4a8e7SKrzysztof Parzyszek // Make it easier to construct reduction operators from built-in intrinsics. 2934ec4a8e7SKrzysztof Parzyszek omp::clause::ReductionOperator 2944ec4a8e7SKrzysztof Parzyszek makeOp(omp::clause::DefinedOperator::IntrinsicOperator Op) { 2954ec4a8e7SKrzysztof Parzyszek return omp::clause::ReductionOperator{omp::clause::DefinedOperator{Op}}; 2964ec4a8e7SKrzysztof Parzyszek } 2974ec4a8e7SKrzysztof Parzyszek } // namespace red 2984ec4a8e7SKrzysztof Parzyszek 299be7c9e39SKrzysztof Parzyszek namespace { 300be7c9e39SKrzysztof Parzyszek using namespace llvm::omp; 301be7c9e39SKrzysztof Parzyszek 302be7c9e39SKrzysztof Parzyszek class OpenMPDecompositionTest : public testing::Test { 303be7c9e39SKrzysztof Parzyszek protected: 304be7c9e39SKrzysztof Parzyszek void SetUp() override {} 305be7c9e39SKrzysztof Parzyszek void TearDown() override {} 306be7c9e39SKrzysztof Parzyszek 307be7c9e39SKrzysztof Parzyszek omp::Helper Helper; 308be7c9e39SKrzysztof Parzyszek uint32_t AnyVersion = 999; 309be7c9e39SKrzysztof Parzyszek }; 310be7c9e39SKrzysztof Parzyszek 311be7c9e39SKrzysztof Parzyszek // PRIVATE 312be7c9e39SKrzysztof Parzyszek // [5.2:111:5-7] 313be7c9e39SKrzysztof Parzyszek // Directives: distribute, do, for, loop, parallel, scope, sections, simd, 314be7c9e39SKrzysztof Parzyszek // single, target, task, taskloop, teams 315be7c9e39SKrzysztof Parzyszek // 316be7c9e39SKrzysztof Parzyszek // [5.2:340:1-2] 317be7c9e39SKrzysztof Parzyszek // (1) The effect of the 1 private clause is as if it is applied only to the 318be7c9e39SKrzysztof Parzyszek // innermost leaf construct that permits it. 319be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Private1) { 320be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 321be7c9e39SKrzysztof Parzyszek 322be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 323be7c9e39SKrzysztof Parzyszek {OMPC_private, omp::clause::Private{{x}}}, 324be7c9e39SKrzysztof Parzyszek }; 325be7c9e39SKrzysztof Parzyszek 326be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, 327be7c9e39SKrzysztof Parzyszek Clauses); 328be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 329be7c9e39SKrzysztof Parzyszek 330be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 331be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 332be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel"); // (1) 333be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "sections private(x)"); // (1) 334be7c9e39SKrzysztof Parzyszek } 335be7c9e39SKrzysztof Parzyszek 336be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Private2) { 337be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 338be7c9e39SKrzysztof Parzyszek 339be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 340be7c9e39SKrzysztof Parzyszek {OMPC_private, omp::clause::Private{{x}}}, 341be7c9e39SKrzysztof Parzyszek }; 342be7c9e39SKrzysztof Parzyszek 343be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, 344be7c9e39SKrzysztof Parzyszek Clauses); 345be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 346be7c9e39SKrzysztof Parzyszek 347be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 348be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 349be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel private(x)"); // (1) 350be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "masked"); // (1) 351be7c9e39SKrzysztof Parzyszek } 352be7c9e39SKrzysztof Parzyszek 353be7c9e39SKrzysztof Parzyszek // FIRSTPRIVATE 354be7c9e39SKrzysztof Parzyszek // [5.2:112:5-7] 355be7c9e39SKrzysztof Parzyszek // Directives: distribute, do, for, parallel, scope, sections, single, target, 356be7c9e39SKrzysztof Parzyszek // task, taskloop, teams 357be7c9e39SKrzysztof Parzyszek // 358be7c9e39SKrzysztof Parzyszek // [5.2:340:3-20] 359be7c9e39SKrzysztof Parzyszek // (3) The effect of the firstprivate clause is as if it is applied to one or 360be7c9e39SKrzysztof Parzyszek // more leaf constructs as follows: 361be7c9e39SKrzysztof Parzyszek // (5) To the distribute construct if it is among the constituent constructs; 362be7c9e39SKrzysztof Parzyszek // (6) To the teams construct if it is among the constituent constructs and the 363be7c9e39SKrzysztof Parzyszek // distribute construct is not; 364be7c9e39SKrzysztof Parzyszek // (8) To a worksharing construct that accepts the clause if one is among the 365be7c9e39SKrzysztof Parzyszek // constituent constructs; 366be7c9e39SKrzysztof Parzyszek // (9) To the taskloop construct if it is among the constituent constructs; 367be7c9e39SKrzysztof Parzyszek // (10) To the parallel construct if it is among the constituent constructs and 368be7c9e39SKrzysztof Parzyszek // neither a taskloop construct nor a worksharing construct that accepts 369be7c9e39SKrzysztof Parzyszek // the clause is among them; 370be7c9e39SKrzysztof Parzyszek // (12) To the target construct if it is among the constituent constructs and 371be7c9e39SKrzysztof Parzyszek // the same list item neither appears in a lastprivate clause nor is the 372be7c9e39SKrzysztof Parzyszek // base variable or base pointer of a list item that appears in a map 373be7c9e39SKrzysztof Parzyszek // clause. 374be7c9e39SKrzysztof Parzyszek // 375be7c9e39SKrzysztof Parzyszek // (15) If the parallel construct is among the constituent constructs and the 376be7c9e39SKrzysztof Parzyszek // effect is not as if the firstprivate clause is applied to it by the above 377be7c9e39SKrzysztof Parzyszek // rules, then the effect is as if the shared clause with the same list item is 378be7c9e39SKrzysztof Parzyszek // applied to the parallel construct. 379be7c9e39SKrzysztof Parzyszek // (17) If the teams construct is among the constituent constructs and the 380be7c9e39SKrzysztof Parzyszek // effect is not as if the firstprivate clause is applied to it by the above 381be7c9e39SKrzysztof Parzyszek // rules, then the effect is as if the shared clause with the same list item is 382be7c9e39SKrzysztof Parzyszek // applied to the teams construct. 383be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Firstprivate1) { 384be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 385be7c9e39SKrzysztof Parzyszek 386be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 387be7c9e39SKrzysztof Parzyszek {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, 388be7c9e39SKrzysztof Parzyszek }; 389be7c9e39SKrzysztof Parzyszek 390be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, 391be7c9e39SKrzysztof Parzyszek Clauses); 392be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 393be7c9e39SKrzysztof Parzyszek 394be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 395be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 396be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x)"); // (10), (15) 397be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "sections firstprivate(x)"); // (8) 398be7c9e39SKrzysztof Parzyszek } 399be7c9e39SKrzysztof Parzyszek 400be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Firstprivate2) { 401be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 402be7c9e39SKrzysztof Parzyszek 403be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 404be7c9e39SKrzysztof Parzyszek {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, 405be7c9e39SKrzysztof Parzyszek }; 406be7c9e39SKrzysztof Parzyszek 407be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 408be7c9e39SKrzysztof Parzyszek OMPD_target_teams_distribute, Clauses); 409be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 410be7c9e39SKrzysztof Parzyszek 411be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 412be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 413be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 414be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target firstprivate(x)"); // (12) 415be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) 416be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "distribute firstprivate(x)"); // (5) 417be7c9e39SKrzysztof Parzyszek } 418be7c9e39SKrzysztof Parzyszek 419be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Firstprivate3) { 420be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 421be7c9e39SKrzysztof Parzyszek 422be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 423be7c9e39SKrzysztof Parzyszek {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, 424be7c9e39SKrzysztof Parzyszek {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, 425be7c9e39SKrzysztof Parzyszek }; 426be7c9e39SKrzysztof Parzyszek 427be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 428be7c9e39SKrzysztof Parzyszek OMPD_target_teams_distribute, Clauses); 429be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 430be7c9e39SKrzysztof Parzyszek 431be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 432be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 433be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 434be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (12), (27) 435be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17) 436be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "distribute firstprivate(x) lastprivate(, (x))"); // (5), (21) 437be7c9e39SKrzysztof Parzyszek } 438be7c9e39SKrzysztof Parzyszek 439be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Firstprivate4) { 440be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 441be7c9e39SKrzysztof Parzyszek 442be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 443be7c9e39SKrzysztof Parzyszek {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, 444be7c9e39SKrzysztof Parzyszek }; 445be7c9e39SKrzysztof Parzyszek 446be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_teams, 447be7c9e39SKrzysztof Parzyszek Clauses); 448be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 449be7c9e39SKrzysztof Parzyszek 450be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 451be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 452be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target firstprivate(x)"); // (12) 453be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "teams firstprivate(x)"); // (6) 454be7c9e39SKrzysztof Parzyszek } 455be7c9e39SKrzysztof Parzyszek 456be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Firstprivate5) { 457be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 458be7c9e39SKrzysztof Parzyszek 459be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 460be7c9e39SKrzysztof Parzyszek {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, 461be7c9e39SKrzysztof Parzyszek }; 462be7c9e39SKrzysztof Parzyszek 463be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 464be7c9e39SKrzysztof Parzyszek OMPD_parallel_masked_taskloop, Clauses); 465be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 466be7c9e39SKrzysztof Parzyszek 467be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 468be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 469be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 470be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x)"); // (10) 471be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "masked"); 472be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "taskloop firstprivate(x)"); // (9) 473be7c9e39SKrzysztof Parzyszek } 474be7c9e39SKrzysztof Parzyszek 475be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Firstprivate6) { 476be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 477be7c9e39SKrzysztof Parzyszek 478be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 479be7c9e39SKrzysztof Parzyszek {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, 480be7c9e39SKrzysztof Parzyszek }; 481be7c9e39SKrzysztof Parzyszek 482be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, 483be7c9e39SKrzysztof Parzyszek Clauses); 484be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 485be7c9e39SKrzysztof Parzyszek 486be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 487be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 488be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel firstprivate(x)"); // (10) 489be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "masked"); 490be7c9e39SKrzysztof Parzyszek } 491be7c9e39SKrzysztof Parzyszek 492be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Firstprivate7) { 493be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 494be7c9e39SKrzysztof Parzyszek 495be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 496be7c9e39SKrzysztof Parzyszek {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, 497be7c9e39SKrzysztof Parzyszek }; 498be7c9e39SKrzysztof Parzyszek 499be7c9e39SKrzysztof Parzyszek // Composite constructs are still decomposed. 500be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_distribute, 501be7c9e39SKrzysztof Parzyszek Clauses); 502be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 503be7c9e39SKrzysztof Parzyszek 504be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 505be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 506be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "teams shared(x)"); // (17) 507be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "distribute firstprivate(x)"); // (5) 508be7c9e39SKrzysztof Parzyszek } 509be7c9e39SKrzysztof Parzyszek 510be7c9e39SKrzysztof Parzyszek // LASTPRIVATE 511be7c9e39SKrzysztof Parzyszek // [5.2:115:7-8] 512be7c9e39SKrzysztof Parzyszek // Directives: distribute, do, for, loop, sections, simd, taskloop 513be7c9e39SKrzysztof Parzyszek // 514be7c9e39SKrzysztof Parzyszek // [5.2:340:21-30] 515be7c9e39SKrzysztof Parzyszek // (21) The effect of the lastprivate clause is as if it is applied to all leaf 516be7c9e39SKrzysztof Parzyszek // constructs that permit the clause. 517be7c9e39SKrzysztof Parzyszek // (22) If the parallel construct is among the constituent constructs and the 518be7c9e39SKrzysztof Parzyszek // list item is not also specified in the firstprivate clause, then the effect 519be7c9e39SKrzysztof Parzyszek // of the lastprivate clause is as if the shared clause with the same list item 520be7c9e39SKrzysztof Parzyszek // is applied to the parallel construct. 521be7c9e39SKrzysztof Parzyszek // (24) If the teams construct is among the constituent constructs and the list 522be7c9e39SKrzysztof Parzyszek // item is not also specified in the firstprivate clause, then the effect of the 523be7c9e39SKrzysztof Parzyszek // lastprivate clause is as if the shared clause with the same list item is 524be7c9e39SKrzysztof Parzyszek // applied to the teams construct. 525be7c9e39SKrzysztof Parzyszek // (27) If the target construct is among the constituent constructs and the list 526be7c9e39SKrzysztof Parzyszek // item is not the base variable or base pointer of a list item that appears in 527be7c9e39SKrzysztof Parzyszek // a map clause, the effect of the lastprivate clause is as if the same list 528be7c9e39SKrzysztof Parzyszek // item appears in a map clause with a map-type of tofrom. 529be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Lastprivate1) { 530be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 531be7c9e39SKrzysztof Parzyszek 532be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 533be7c9e39SKrzysztof Parzyszek {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, 534be7c9e39SKrzysztof Parzyszek }; 535be7c9e39SKrzysztof Parzyszek 536be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, 537be7c9e39SKrzysztof Parzyszek Clauses); 538be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 539be7c9e39SKrzysztof Parzyszek 540be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 541be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 542be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x)"); // (21), (22) 543be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "sections lastprivate(, (x))"); // (21) 544be7c9e39SKrzysztof Parzyszek } 545be7c9e39SKrzysztof Parzyszek 546be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Lastprivate2) { 547be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 548be7c9e39SKrzysztof Parzyszek 549be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 550be7c9e39SKrzysztof Parzyszek {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, 551be7c9e39SKrzysztof Parzyszek }; 552be7c9e39SKrzysztof Parzyszek 553be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_distribute, 554be7c9e39SKrzysztof Parzyszek Clauses); 555be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 556be7c9e39SKrzysztof Parzyszek 557be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 558be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 559be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "teams shared(x)"); // (21), (25) 560be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "distribute lastprivate(, (x))"); // (21) 561be7c9e39SKrzysztof Parzyszek } 562be7c9e39SKrzysztof Parzyszek 563be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Lastprivate3) { 564be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 565be7c9e39SKrzysztof Parzyszek 566be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 567be7c9e39SKrzysztof Parzyszek {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, 568be7c9e39SKrzysztof Parzyszek }; 569be7c9e39SKrzysztof Parzyszek 570be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_do, 571be7c9e39SKrzysztof Parzyszek Clauses); 572be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 573be7c9e39SKrzysztof Parzyszek 574be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 575be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 576be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 577be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (21), (27) 578be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "parallel shared(x)"); // (22) 579be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21) 580be7c9e39SKrzysztof Parzyszek } 581be7c9e39SKrzysztof Parzyszek 582be7c9e39SKrzysztof Parzyszek // SHARED 583be7c9e39SKrzysztof Parzyszek // [5.2:110:5-6] 584be7c9e39SKrzysztof Parzyszek // Directives: parallel, task, taskloop, teams 585be7c9e39SKrzysztof Parzyszek // 586be7c9e39SKrzysztof Parzyszek // [5.2:340:31-32] 587be7c9e39SKrzysztof Parzyszek // (31) The effect of the shared, default, thread_limit, or order clause is as 588be7c9e39SKrzysztof Parzyszek // if it is applied to all leaf constructs that permit the clause. 589be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Shared1) { 590be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 591be7c9e39SKrzysztof Parzyszek 592be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 593be7c9e39SKrzysztof Parzyszek {OMPC_shared, omp::clause::Shared{{x}}}, 594be7c9e39SKrzysztof Parzyszek }; 595be7c9e39SKrzysztof Parzyszek 596be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 597be7c9e39SKrzysztof Parzyszek OMPD_parallel_masked_taskloop, Clauses); 598be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 599be7c9e39SKrzysztof Parzyszek 600be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 601be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 602be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 603be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x)"); // (31) 604be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "masked"); // (31) 605be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "taskloop shared(x)"); // (31) 606be7c9e39SKrzysztof Parzyszek } 607be7c9e39SKrzysztof Parzyszek 608be7c9e39SKrzysztof Parzyszek // DEFAULT 609be7c9e39SKrzysztof Parzyszek // [5.2:109:5-6] 610be7c9e39SKrzysztof Parzyszek // Directives: parallel, task, taskloop, teams 611be7c9e39SKrzysztof Parzyszek // 612be7c9e39SKrzysztof Parzyszek // [5.2:340:31-32] 613be7c9e39SKrzysztof Parzyszek // (31) The effect of the shared, default, thread_limit, or order clause is as 614be7c9e39SKrzysztof Parzyszek // if it is applied to all leaf constructs that permit the clause. 615be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Default1) { 616be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 617be7c9e39SKrzysztof Parzyszek 618be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 619be7c9e39SKrzysztof Parzyszek {OMPC_default, 620be7c9e39SKrzysztof Parzyszek omp::clause::Default{ 621be7c9e39SKrzysztof Parzyszek omp::clause::Default::DataSharingAttribute::Firstprivate}}, 622be7c9e39SKrzysztof Parzyszek }; 623be7c9e39SKrzysztof Parzyszek 624be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 625be7c9e39SKrzysztof Parzyszek OMPD_parallel_masked_taskloop, Clauses); 626be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 627be7c9e39SKrzysztof Parzyszek 628be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 629be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 630be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 631be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel default(0)"); // (31) 632be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "masked"); // (31) 633be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "taskloop default(0)"); // (31) 634be7c9e39SKrzysztof Parzyszek } 635be7c9e39SKrzysztof Parzyszek 636be7c9e39SKrzysztof Parzyszek // THREAD_LIMIT 637be7c9e39SKrzysztof Parzyszek // [5.2:277:14-15] 638be7c9e39SKrzysztof Parzyszek // Directives: target, teams 639be7c9e39SKrzysztof Parzyszek // 640be7c9e39SKrzysztof Parzyszek // [5.2:340:31-32] 641be7c9e39SKrzysztof Parzyszek // (31) The effect of the shared, default, thread_limit, or order clause is as 642be7c9e39SKrzysztof Parzyszek // if it is applied to all leaf constructs that permit the clause. 643be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, ThreadLimit1) { 644be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 645be7c9e39SKrzysztof Parzyszek 646be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 647be7c9e39SKrzysztof Parzyszek {OMPC_thread_limit, omp::clause::ThreadLimit{omp::ExprTy{}}}, 648be7c9e39SKrzysztof Parzyszek }; 649be7c9e39SKrzysztof Parzyszek 650be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 651be7c9e39SKrzysztof Parzyszek OMPD_target_teams_distribute, Clauses); 652be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 653be7c9e39SKrzysztof Parzyszek 654be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 655be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 656be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 657be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target thread_limit(expr)"); // (31) 658be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "teams thread_limit(expr)"); // (31) 659be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "distribute"); // (31) 660be7c9e39SKrzysztof Parzyszek } 661be7c9e39SKrzysztof Parzyszek 662be7c9e39SKrzysztof Parzyszek // ORDER 663be7c9e39SKrzysztof Parzyszek // [5.2:234:3-4] 664be7c9e39SKrzysztof Parzyszek // Directives: distribute, do, for, loop, simd 665be7c9e39SKrzysztof Parzyszek // 666be7c9e39SKrzysztof Parzyszek // [5.2:340:31-32] 667be7c9e39SKrzysztof Parzyszek // (31) The effect of the shared, default, thread_limit, or order clause is as 668be7c9e39SKrzysztof Parzyszek // if it is applied to all leaf constructs that permit the clause. 669be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Order1) { 670be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 671be7c9e39SKrzysztof Parzyszek 672be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 673be7c9e39SKrzysztof Parzyszek {OMPC_order, 674be7c9e39SKrzysztof Parzyszek omp::clause::Order{{omp::clause::Order::OrderModifier::Unconstrained, 675be7c9e39SKrzysztof Parzyszek omp::clause::Order::Ordering::Concurrent}}}, 676be7c9e39SKrzysztof Parzyszek }; 677be7c9e39SKrzysztof Parzyszek 678be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec( 679be7c9e39SKrzysztof Parzyszek AnyVersion, Helper, OMPD_target_teams_distribute_parallel_for_simd, 680be7c9e39SKrzysztof Parzyszek Clauses); 681be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 6u); 682be7c9e39SKrzysztof Parzyszek 683be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 684be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 685be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 686be7c9e39SKrzysztof Parzyszek std::string Dir3 = stringify(Dec.output[3]); 687be7c9e39SKrzysztof Parzyszek std::string Dir4 = stringify(Dec.output[4]); 688be7c9e39SKrzysztof Parzyszek std::string Dir5 = stringify(Dec.output[5]); 689be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target"); // (31) 690be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "teams"); // (31) 691b4ab52c8Sharishch4 ASSERT_EQ(Dir2, "distribute order(1, 0)"); // (31) 692be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir3, "parallel"); // (31) 693be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir4, "for order(1, 0)"); // (31) 694be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir5, "simd order(1, 0)"); // (31) 695be7c9e39SKrzysztof Parzyszek } 696be7c9e39SKrzysztof Parzyszek 697be7c9e39SKrzysztof Parzyszek // ALLOCATE 698be7c9e39SKrzysztof Parzyszek // [5.2:178:7-9] 699be7c9e39SKrzysztof Parzyszek // Directives: allocators, distribute, do, for, parallel, scope, sections, 700be7c9e39SKrzysztof Parzyszek // single, target, task, taskgroup, taskloop, teams 701be7c9e39SKrzysztof Parzyszek // 702be7c9e39SKrzysztof Parzyszek // [5.2:340:33-35] 703be7c9e39SKrzysztof Parzyszek // (33) The effect of the allocate clause is as if it is applied to all leaf 704be7c9e39SKrzysztof Parzyszek // constructs that permit the clause and to which a data-sharing attribute 705be7c9e39SKrzysztof Parzyszek // clause that may create a private copy of the same list item is applied. 706be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Allocate1) { 707be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 708be7c9e39SKrzysztof Parzyszek 7094ec4a8e7SKrzysztof Parzyszek // Allocate + firstprivate 7104ec4a8e7SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 711cdbd2287SKrzysztof Parzyszek {OMPC_allocate, omp::clause::Allocate{{std::nullopt, std::nullopt, {x}}}}, 7124ec4a8e7SKrzysztof Parzyszek {OMPC_firstprivate, omp::clause::Firstprivate{{x}}}, 7134ec4a8e7SKrzysztof Parzyszek }; 7144ec4a8e7SKrzysztof Parzyszek 7154ec4a8e7SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, 7164ec4a8e7SKrzysztof Parzyszek Clauses); 7174ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 7184ec4a8e7SKrzysztof Parzyszek 7194ec4a8e7SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 7204ec4a8e7SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 7214ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x)"); // (33) 722cdbd2287SKrzysztof Parzyszek ASSERT_EQ(Dir1, "sections firstprivate(x) allocate(, , (x))"); // (33) 7234ec4a8e7SKrzysztof Parzyszek } 7244ec4a8e7SKrzysztof Parzyszek 7254ec4a8e7SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Allocate2) { 7264ec4a8e7SKrzysztof Parzyszek omp::Object x{"x"}; 7274ec4a8e7SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 7284ec4a8e7SKrzysztof Parzyszek 7294ec4a8e7SKrzysztof Parzyszek // Allocate + in_reduction 7304ec4a8e7SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 731cdbd2287SKrzysztof Parzyszek {OMPC_allocate, omp::clause::Allocate{{std::nullopt, std::nullopt, {x}}}}, 7324ec4a8e7SKrzysztof Parzyszek {OMPC_in_reduction, omp::clause::InReduction{{{Add}, {x}}}}, 7334ec4a8e7SKrzysztof Parzyszek }; 7344ec4a8e7SKrzysztof Parzyszek 7354ec4a8e7SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel, 7364ec4a8e7SKrzysztof Parzyszek Clauses); 7374ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 7384ec4a8e7SKrzysztof Parzyszek 7394ec4a8e7SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 7404ec4a8e7SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 741cdbd2287SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target in_reduction((3), (x)) allocate(, , (x))"); // (33) 7424ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dir1, "parallel"); // (33) 7434ec4a8e7SKrzysztof Parzyszek } 7444ec4a8e7SKrzysztof Parzyszek 7454ec4a8e7SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Allocate3) { 7464ec4a8e7SKrzysztof Parzyszek omp::Object x{"x"}; 7474ec4a8e7SKrzysztof Parzyszek 7484ec4a8e7SKrzysztof Parzyszek // Allocate + linear 7494ec4a8e7SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 750cdbd2287SKrzysztof Parzyszek {OMPC_allocate, omp::clause::Allocate{{std::nullopt, std::nullopt, {x}}}}, 751*03cbe426SKrzysztof Parzyszek {OMPC_linear, omp::clause::Linear{{std::nullopt, std::nullopt, {x}}}}, 7524ec4a8e7SKrzysztof Parzyszek }; 7534ec4a8e7SKrzysztof Parzyszek 7544ec4a8e7SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_for, 7554ec4a8e7SKrzysztof Parzyszek Clauses); 7564ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 7574ec4a8e7SKrzysztof Parzyszek 7584ec4a8e7SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 7594ec4a8e7SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 7604ec4a8e7SKrzysztof Parzyszek // The "shared" clause is duplicated---this isn't harmful, but it 7614ec4a8e7SKrzysztof Parzyszek // should be fixed eventually. 7624ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x) shared(x)"); // (33) 763*03cbe426SKrzysztof Parzyszek ASSERT_EQ(Dir1, "for linear(, , (x)) firstprivate(x) lastprivate(, (x)) " 764cdbd2287SKrzysztof Parzyszek "allocate(, , (x))"); // (33) 7654ec4a8e7SKrzysztof Parzyszek } 7664ec4a8e7SKrzysztof Parzyszek 7674ec4a8e7SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Allocate4) { 7684ec4a8e7SKrzysztof Parzyszek omp::Object x{"x"}; 7694ec4a8e7SKrzysztof Parzyszek 7704ec4a8e7SKrzysztof Parzyszek // Allocate + lastprivate 7714ec4a8e7SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 772cdbd2287SKrzysztof Parzyszek {OMPC_allocate, omp::clause::Allocate{{std::nullopt, std::nullopt, {x}}}}, 7734ec4a8e7SKrzysztof Parzyszek {OMPC_lastprivate, omp::clause::Lastprivate{{std::nullopt, {x}}}}, 7744ec4a8e7SKrzysztof Parzyszek }; 7754ec4a8e7SKrzysztof Parzyszek 7764ec4a8e7SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, 7774ec4a8e7SKrzysztof Parzyszek Clauses); 7784ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 7794ec4a8e7SKrzysztof Parzyszek 7804ec4a8e7SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 7814ec4a8e7SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 7824ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x)"); // (33) 783cdbd2287SKrzysztof Parzyszek ASSERT_EQ(Dir1, "sections lastprivate(, (x)) allocate(, , (x))"); // (33) 7844ec4a8e7SKrzysztof Parzyszek } 7854ec4a8e7SKrzysztof Parzyszek 7864ec4a8e7SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Allocate5) { 7874ec4a8e7SKrzysztof Parzyszek omp::Object x{"x"}; 7884ec4a8e7SKrzysztof Parzyszek 7894ec4a8e7SKrzysztof Parzyszek // Allocate + private 790be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 791cdbd2287SKrzysztof Parzyszek {OMPC_allocate, omp::clause::Allocate{{std::nullopt, std::nullopt, {x}}}}, 792be7c9e39SKrzysztof Parzyszek {OMPC_private, omp::clause::Private{{x}}}, 793be7c9e39SKrzysztof Parzyszek }; 794be7c9e39SKrzysztof Parzyszek 795be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, 796be7c9e39SKrzysztof Parzyszek Clauses); 797be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 798be7c9e39SKrzysztof Parzyszek 799be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 800be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 801be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel"); // (33) 802cdbd2287SKrzysztof Parzyszek ASSERT_EQ(Dir1, "sections private(x) allocate(, , (x))"); // (33) 803be7c9e39SKrzysztof Parzyszek } 804be7c9e39SKrzysztof Parzyszek 8054ec4a8e7SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Allocate6) { 8064ec4a8e7SKrzysztof Parzyszek omp::Object x{"x"}; 8074ec4a8e7SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 8084ec4a8e7SKrzysztof Parzyszek 8094ec4a8e7SKrzysztof Parzyszek // Allocate + reduction 8104ec4a8e7SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 811cdbd2287SKrzysztof Parzyszek {OMPC_allocate, omp::clause::Allocate{{std::nullopt, std::nullopt, {x}}}}, 8124ec4a8e7SKrzysztof Parzyszek {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, 8134ec4a8e7SKrzysztof Parzyszek }; 8144ec4a8e7SKrzysztof Parzyszek 8154ec4a8e7SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, 8164ec4a8e7SKrzysztof Parzyszek Clauses); 8174ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 8184ec4a8e7SKrzysztof Parzyszek 8194ec4a8e7SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 8204ec4a8e7SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 8214ec4a8e7SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x)"); // (33) 822cdbd2287SKrzysztof Parzyszek ASSERT_EQ(Dir1, "sections reduction(, (3), (x)) allocate(, , (x))"); // (33) 8234ec4a8e7SKrzysztof Parzyszek } 8244ec4a8e7SKrzysztof Parzyszek 825be7c9e39SKrzysztof Parzyszek // REDUCTION 826be7c9e39SKrzysztof Parzyszek // [5.2:134:17-18] 827be7c9e39SKrzysztof Parzyszek // Directives: do, for, loop, parallel, scope, sections, simd, taskloop, teams 828be7c9e39SKrzysztof Parzyszek // 829be7c9e39SKrzysztof Parzyszek // [5.2:340-341:36-13] 830be7c9e39SKrzysztof Parzyszek // (36) The effect of the reduction clause is as if it is applied to all leaf 831be7c9e39SKrzysztof Parzyszek // constructs that permit the clause, except for the following constructs: 832be7c9e39SKrzysztof Parzyszek // (1) The parallel construct, when combined with the sections, 833be7c9e39SKrzysztof Parzyszek // worksharing-loop, loop, or taskloop construct; and 834be7c9e39SKrzysztof Parzyszek // (3) The teams construct, when combined with the loop construct. 835be7c9e39SKrzysztof Parzyszek // (4) For the parallel and teams constructs above, the effect of the reduction 836be7c9e39SKrzysztof Parzyszek // clause instead is as if each list item or, for any list item that is an array 837be7c9e39SKrzysztof Parzyszek // item, its corresponding base array or base pointer appears in a shared clause 838be7c9e39SKrzysztof Parzyszek // for the construct. 839be7c9e39SKrzysztof Parzyszek // (6) If the task reduction-modifier is specified, the effect is as if it only 840be7c9e39SKrzysztof Parzyszek // modifies the behavior of the reduction clause on the innermost leaf construct 841be7c9e39SKrzysztof Parzyszek // that accepts the modifier (see Section 5.5.8). 842be7c9e39SKrzysztof Parzyszek // (8) If the inscan reduction-modifier is specified, the effect is as if it 843be7c9e39SKrzysztof Parzyszek // modifies the behavior of the reduction clause on all constructs of the 844be7c9e39SKrzysztof Parzyszek // combined construct to which the clause is applied and that accept the 845be7c9e39SKrzysztof Parzyszek // modifier. 846be7c9e39SKrzysztof Parzyszek // (10) If a list item in a reduction clause on a combined target construct does 847be7c9e39SKrzysztof Parzyszek // not have the same base variable or base pointer as a list item in a map 848be7c9e39SKrzysztof Parzyszek // clause on the construct, then the effect is as if the list item in the 849be7c9e39SKrzysztof Parzyszek // reduction clause appears as a list item in a map clause with a map-type of 850be7c9e39SKrzysztof Parzyszek // tofrom. 851be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Reduction1) { 852be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 853be7c9e39SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 854be7c9e39SKrzysztof Parzyszek 855be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 856be7c9e39SKrzysztof Parzyszek {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, 857be7c9e39SKrzysztof Parzyszek }; 858be7c9e39SKrzysztof Parzyszek 859be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_sections, 860be7c9e39SKrzysztof Parzyszek Clauses); 861be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 862be7c9e39SKrzysztof Parzyszek 863be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 864be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 865be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel shared(x)"); // (36), (1), (4) 866be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "sections reduction(, (3), (x))"); // (36) 867be7c9e39SKrzysztof Parzyszek } 868be7c9e39SKrzysztof Parzyszek 869be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Reduction2) { 870be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 871be7c9e39SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 872be7c9e39SKrzysztof Parzyszek 873be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 874be7c9e39SKrzysztof Parzyszek {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, 875be7c9e39SKrzysztof Parzyszek }; 876be7c9e39SKrzysztof Parzyszek 877be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_parallel_masked, 878be7c9e39SKrzysztof Parzyszek Clauses); 879be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 880be7c9e39SKrzysztof Parzyszek 881be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 882be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 883be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "parallel reduction(, (3), (x))"); // (36), (1), (4) 884be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "masked"); // (36) 885be7c9e39SKrzysztof Parzyszek } 886be7c9e39SKrzysztof Parzyszek 887be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Reduction3) { 888be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 889be7c9e39SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 890be7c9e39SKrzysztof Parzyszek 891be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 892be7c9e39SKrzysztof Parzyszek {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, 893be7c9e39SKrzysztof Parzyszek }; 894be7c9e39SKrzysztof Parzyszek 895be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_teams_loop, Clauses); 896be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 897be7c9e39SKrzysztof Parzyszek 898be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 899be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 900be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "teams shared(x)"); // (36), (3), (4) 901be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "loop reduction(, (3), (x))"); // (36) 902be7c9e39SKrzysztof Parzyszek } 903be7c9e39SKrzysztof Parzyszek 904be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Reduction4) { 905be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 906be7c9e39SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 907be7c9e39SKrzysztof Parzyszek 908be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 909be7c9e39SKrzysztof Parzyszek {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, 910be7c9e39SKrzysztof Parzyszek }; 911be7c9e39SKrzysztof Parzyszek 912be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 913be7c9e39SKrzysztof Parzyszek OMPD_teams_distribute_parallel_for, Clauses); 914be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 4u); 915be7c9e39SKrzysztof Parzyszek 916be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 917be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 918be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 919be7c9e39SKrzysztof Parzyszek std::string Dir3 = stringify(Dec.output[3]); 920be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3) 921be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "distribute"); // (36) 922be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) 923be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir3, "for reduction(, (3), (x))"); // (36) 924be7c9e39SKrzysztof Parzyszek } 925be7c9e39SKrzysztof Parzyszek 926be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Reduction5) { 927be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 928be7c9e39SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 929be7c9e39SKrzysztof Parzyszek auto TaskMod = omp::clause::Reduction::ReductionModifier::Task; 930be7c9e39SKrzysztof Parzyszek 931be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 932be7c9e39SKrzysztof Parzyszek {OMPC_reduction, omp::clause::Reduction{{TaskMod, {Add}, {x}}}}, 933be7c9e39SKrzysztof Parzyszek }; 934be7c9e39SKrzysztof Parzyszek 935be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 936be7c9e39SKrzysztof Parzyszek OMPD_teams_distribute_parallel_for, Clauses); 937be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 4u); 938be7c9e39SKrzysztof Parzyszek 939be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 940be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 941be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 942be7c9e39SKrzysztof Parzyszek std::string Dir3 = stringify(Dec.output[3]); 943be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3), (6) 944be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "distribute"); // (36) 945be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) 946be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir3, "for reduction(2, (3), (x))"); // (36), (6) 947be7c9e39SKrzysztof Parzyszek } 948be7c9e39SKrzysztof Parzyszek 949be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Reduction6) { 950be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 951be7c9e39SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 952be7c9e39SKrzysztof Parzyszek auto InscanMod = omp::clause::Reduction::ReductionModifier::Inscan; 953be7c9e39SKrzysztof Parzyszek 954be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 955be7c9e39SKrzysztof Parzyszek {OMPC_reduction, omp::clause::Reduction{{InscanMod, {Add}, {x}}}}, 956be7c9e39SKrzysztof Parzyszek }; 957be7c9e39SKrzysztof Parzyszek 958be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 959be7c9e39SKrzysztof Parzyszek OMPD_teams_distribute_parallel_for, Clauses); 960be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 4u); 961be7c9e39SKrzysztof Parzyszek 962be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 963be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 964be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 965be7c9e39SKrzysztof Parzyszek std::string Dir3 = stringify(Dec.output[3]); 966be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "teams reduction(, (3), (x))"); // (36), (3), (8) 967be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "distribute"); // (36) 968be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "parallel shared(x)"); // (36), (1), (4) 969be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir3, "for reduction(1, (3), (x))"); // (36), (8) 970be7c9e39SKrzysztof Parzyszek } 971be7c9e39SKrzysztof Parzyszek 972be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Reduction7) { 973be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 974be7c9e39SKrzysztof Parzyszek auto Add = red::makeOp(omp::clause::DefinedOperator::IntrinsicOperator::Add); 975be7c9e39SKrzysztof Parzyszek 976be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 977be7c9e39SKrzysztof Parzyszek {OMPC_reduction, omp::clause::Reduction{{std::nullopt, {Add}, {x}}}}, 978be7c9e39SKrzysztof Parzyszek }; 979be7c9e39SKrzysztof Parzyszek 980be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_do, 981be7c9e39SKrzysztof Parzyszek Clauses); 982be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 983be7c9e39SKrzysztof Parzyszek 984be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 985be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 986be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 987eb88e7c1SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (36), (10) 988be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4) 989be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36) 990be7c9e39SKrzysztof Parzyszek } 991be7c9e39SKrzysztof Parzyszek 992be7c9e39SKrzysztof Parzyszek // IF 993be7c9e39SKrzysztof Parzyszek // [5.2:72:7-9] 994be7c9e39SKrzysztof Parzyszek // Directives: cancel, parallel, simd, target, target data, target enter data, 995be7c9e39SKrzysztof Parzyszek // target exit data, target update, task, taskloop 996be7c9e39SKrzysztof Parzyszek // 997be7c9e39SKrzysztof Parzyszek // [5.2:72:15-18] 998be7c9e39SKrzysztof Parzyszek // (15) For combined or composite constructs, the if clause only applies to the 999be7c9e39SKrzysztof Parzyszek // semantics of the construct named in the directive-name-modifier. 1000be7c9e39SKrzysztof Parzyszek // (16) For a combined or composite construct, if no directive-name-modifier is 1001be7c9e39SKrzysztof Parzyszek // specified then the if clause applies to all constituent constructs to which 1002be7c9e39SKrzysztof Parzyszek // an if clause can apply. 1003be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, If1) { 1004be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 1005be7c9e39SKrzysztof Parzyszek {OMPC_if, 1006be7c9e39SKrzysztof Parzyszek omp::clause::If{{llvm::omp::Directive::OMPD_parallel, omp::ExprTy{}}}}, 1007be7c9e39SKrzysztof Parzyszek }; 1008be7c9e39SKrzysztof Parzyszek 1009be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 1010be7c9e39SKrzysztof Parzyszek OMPD_target_parallel_for_simd, Clauses); 1011be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 4u); 1012be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 1013be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 1014be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 1015be7c9e39SKrzysztof Parzyszek std::string Dir3 = stringify(Dec.output[3]); 1016be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target"); // (15) 1017be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "parallel if(, expr)"); // (15) 1018be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "for"); // (15) 1019be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir3, "simd"); // (15) 1020be7c9e39SKrzysztof Parzyszek } 1021be7c9e39SKrzysztof Parzyszek 1022be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, If2) { 1023be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 1024be7c9e39SKrzysztof Parzyszek {OMPC_if, omp::clause::If{{std::nullopt, omp::ExprTy{}}}}, 1025be7c9e39SKrzysztof Parzyszek }; 1026be7c9e39SKrzysztof Parzyszek 1027be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, 1028be7c9e39SKrzysztof Parzyszek OMPD_target_parallel_for_simd, Clauses); 1029be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 4u); 1030be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 1031be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 1032be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 1033be7c9e39SKrzysztof Parzyszek std::string Dir3 = stringify(Dec.output[3]); 1034be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target if(, expr)"); // (16) 1035be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "parallel if(, expr)"); // (16) 1036be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "for"); // (16) 1037be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir3, "simd if(, expr)"); // (16) 1038be7c9e39SKrzysztof Parzyszek } 1039be7c9e39SKrzysztof Parzyszek 1040be7c9e39SKrzysztof Parzyszek // LINEAR 1041be7c9e39SKrzysztof Parzyszek // [5.2:118:1-2] 1042be7c9e39SKrzysztof Parzyszek // Directives: declare simd, do, for, simd 1043be7c9e39SKrzysztof Parzyszek // 1044be7c9e39SKrzysztof Parzyszek // [5.2:341:15-22] 1045be7c9e39SKrzysztof Parzyszek // (15.1) The effect of the linear clause is as if it is applied to the 1046be7c9e39SKrzysztof Parzyszek // innermost leaf construct. 1047be7c9e39SKrzysztof Parzyszek // (15.2) Additionally, if the list item is not the iteration variable of a simd 1048be7c9e39SKrzysztof Parzyszek // or worksharing-loop SIMD construct, the effect on the outer leaf constructs 1049be7c9e39SKrzysztof Parzyszek // is as if the list item was specified in firstprivate and lastprivate clauses 1050be7c9e39SKrzysztof Parzyszek // on the combined or composite construct, with the rules specified above 1051be7c9e39SKrzysztof Parzyszek // applied. 1052be7c9e39SKrzysztof Parzyszek // (19) If a list item of the linear clause is the iteration variable of a simd 1053be7c9e39SKrzysztof Parzyszek // or worksharing-loop SIMD construct and it is not declared in the construct, 1054be7c9e39SKrzysztof Parzyszek // the effect on the outer leaf constructs is as if the list item was specified 1055be7c9e39SKrzysztof Parzyszek // in a lastprivate clause on the combined or composite construct with the rules 1056be7c9e39SKrzysztof Parzyszek // specified above applied. 1057be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Linear1) { 1058be7c9e39SKrzysztof Parzyszek omp::Object x{"x"}; 1059be7c9e39SKrzysztof Parzyszek 1060be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 1061*03cbe426SKrzysztof Parzyszek {OMPC_linear, omp::clause::Linear{{std::nullopt, std::nullopt, {x}}}}, 1062be7c9e39SKrzysztof Parzyszek }; 1063be7c9e39SKrzysztof Parzyszek 1064be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_for_simd, Clauses); 1065be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 2u); 1066be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 1067be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 1068be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "for firstprivate(x) lastprivate(, (x))"); // (15.1), (15.2) 1069*03cbe426SKrzysztof Parzyszek ASSERT_EQ(Dir1, "simd linear(, , (x)) lastprivate(, (x))"); // (15.1) 1070be7c9e39SKrzysztof Parzyszek } 1071be7c9e39SKrzysztof Parzyszek 1072be7c9e39SKrzysztof Parzyszek // NOWAIT 1073be7c9e39SKrzysztof Parzyszek // [5.2:308:11-13] 1074be7c9e39SKrzysztof Parzyszek // Directives: dispatch, do, for, interop, scope, sections, single, target, 1075be7c9e39SKrzysztof Parzyszek // target enter data, target exit data, target update, taskwait, workshare 1076be7c9e39SKrzysztof Parzyszek // 1077be7c9e39SKrzysztof Parzyszek // [5.2:341:23] 1078be7c9e39SKrzysztof Parzyszek // (23) The effect of the nowait clause is as if it is applied to the outermost 1079be7c9e39SKrzysztof Parzyszek // leaf construct that permits it. 1080be7c9e39SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Nowait1) { 1081be7c9e39SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 1082be7c9e39SKrzysztof Parzyszek {OMPC_nowait, omp::clause::Nowait{}}, 1083be7c9e39SKrzysztof Parzyszek }; 1084be7c9e39SKrzysztof Parzyszek 1085be7c9e39SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_target_parallel_for, 1086be7c9e39SKrzysztof Parzyszek Clauses); 1087be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 3u); 1088be7c9e39SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 1089be7c9e39SKrzysztof Parzyszek std::string Dir1 = stringify(Dec.output[1]); 1090be7c9e39SKrzysztof Parzyszek std::string Dir2 = stringify(Dec.output[2]); 1091be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir0, "target nowait"); // (23) 1092be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir1, "parallel"); // (23) 1093be7c9e39SKrzysztof Parzyszek ASSERT_EQ(Dir2, "for"); // (23) 1094be7c9e39SKrzysztof Parzyszek } 1095a0c59079SKrzysztof Parzyszek 1096a0c59079SKrzysztof Parzyszek // --- 1097a0c59079SKrzysztof Parzyszek 1098a0c59079SKrzysztof Parzyszek // Check that "simd linear(x)" does not fail despite the implied "firstprivate" 1099a0c59079SKrzysztof Parzyszek // (which "simd" does not allow). 1100a0c59079SKrzysztof Parzyszek TEST_F(OpenMPDecompositionTest, Misc1) { 1101a0c59079SKrzysztof Parzyszek omp::Object x{"x"}; 1102a0c59079SKrzysztof Parzyszek omp::List<omp::Clause> Clauses{ 1103*03cbe426SKrzysztof Parzyszek {OMPC_linear, omp::clause::Linear{{std::nullopt, std::nullopt, {x}}}}, 1104a0c59079SKrzysztof Parzyszek }; 1105a0c59079SKrzysztof Parzyszek 1106a0c59079SKrzysztof Parzyszek omp::ConstructDecomposition Dec(AnyVersion, Helper, OMPD_simd, Clauses); 1107a0c59079SKrzysztof Parzyszek ASSERT_EQ(Dec.output.size(), 1u); 1108a0c59079SKrzysztof Parzyszek std::string Dir0 = stringify(Dec.output[0]); 1109*03cbe426SKrzysztof Parzyszek ASSERT_EQ(Dir0, "simd linear(, , (x)) lastprivate(, (x))"); 1110a0c59079SKrzysztof Parzyszek } 1111be7c9e39SKrzysztof Parzyszek } // namespace 1112