1*330d8983SJohannes Doerfert //===-- OpenMP/Requirements.h - User required requirements -----*- C++ -*-===// 2*330d8983SJohannes Doerfert // 3*330d8983SJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*330d8983SJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 5*330d8983SJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*330d8983SJohannes Doerfert // 7*330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 8*330d8983SJohannes Doerfert // 9*330d8983SJohannes Doerfert // Handling of the `omp requires` directive, e.g., requiring unified shared 10*330d8983SJohannes Doerfert // memory. 11*330d8983SJohannes Doerfert // 12*330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 13*330d8983SJohannes Doerfert 14*330d8983SJohannes Doerfert #ifndef OMPTARGET_OPENMP_REQUIREMENTS_H 15*330d8983SJohannes Doerfert #define OMPTARGET_OPENMP_REQUIREMENTS_H 16*330d8983SJohannes Doerfert 17*330d8983SJohannes Doerfert #include "Shared/Debug.h" 18*330d8983SJohannes Doerfert 19*330d8983SJohannes Doerfert #include "llvm/ADT/StringRef.h" 20*330d8983SJohannes Doerfert 21*330d8983SJohannes Doerfert #include <cassert> 22*330d8983SJohannes Doerfert #include <cstdint> 23*330d8983SJohannes Doerfert 24*330d8983SJohannes Doerfert enum OpenMPOffloadingRequiresDirFlags : int64_t { 25*330d8983SJohannes Doerfert /// flag undefined. 26*330d8983SJohannes Doerfert OMP_REQ_UNDEFINED = 0x000, 27*330d8983SJohannes Doerfert /// no requires directive present. 28*330d8983SJohannes Doerfert OMP_REQ_NONE = 0x001, 29*330d8983SJohannes Doerfert /// reverse_offload clause. 30*330d8983SJohannes Doerfert OMP_REQ_REVERSE_OFFLOAD = 0x002, 31*330d8983SJohannes Doerfert /// unified_address clause. 32*330d8983SJohannes Doerfert OMP_REQ_UNIFIED_ADDRESS = 0x004, 33*330d8983SJohannes Doerfert /// unified_shared_memory clause. 34*330d8983SJohannes Doerfert OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 35*330d8983SJohannes Doerfert /// dynamic_allocators clause. 36*330d8983SJohannes Doerfert OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 37*330d8983SJohannes Doerfert /// Auto zero-copy extension: 38*330d8983SJohannes Doerfert /// when running on an APU, the GPU plugin may decide to 39*330d8983SJohannes Doerfert /// run in zero-copy even though the user did not program 40*330d8983SJohannes Doerfert /// their application with unified_shared_memory requirement. 41*330d8983SJohannes Doerfert OMPX_REQ_AUTO_ZERO_COPY = 0x020 42*330d8983SJohannes Doerfert }; 43*330d8983SJohannes Doerfert 44*330d8983SJohannes Doerfert class RequirementCollection { 45*330d8983SJohannes Doerfert int64_t SetFlags = OMP_REQ_UNDEFINED; 46*330d8983SJohannes Doerfert 47*330d8983SJohannes Doerfert /// Check consistency between different requires flags (from different 48*330d8983SJohannes Doerfert /// translation units). checkConsistency(int64_t NewFlags,int64_t SetFlags,OpenMPOffloadingRequiresDirFlags Flag,llvm::StringRef Clause)49*330d8983SJohannes Doerfert void checkConsistency(int64_t NewFlags, int64_t SetFlags, 50*330d8983SJohannes Doerfert OpenMPOffloadingRequiresDirFlags Flag, 51*330d8983SJohannes Doerfert llvm::StringRef Clause) { 52*330d8983SJohannes Doerfert if ((SetFlags & Flag) != (NewFlags & Flag)) { 53*330d8983SJohannes Doerfert FATAL_MESSAGE(2, "'#pragma omp requires %s' not used consistently!", 54*330d8983SJohannes Doerfert Clause.data()); 55*330d8983SJohannes Doerfert } 56*330d8983SJohannes Doerfert } 57*330d8983SJohannes Doerfert 58*330d8983SJohannes Doerfert public: 59*330d8983SJohannes Doerfert /// Register \p NewFlags as part of the user requirements. addRequirements(int64_t NewFlags)60*330d8983SJohannes Doerfert void addRequirements(int64_t NewFlags) { 61*330d8983SJohannes Doerfert // TODO: add more elaborate check. 62*330d8983SJohannes Doerfert // Minimal check: only set requires flags if previous value 63*330d8983SJohannes Doerfert // is undefined. This ensures that only the first call to this 64*330d8983SJohannes Doerfert // function will set the requires flags. All subsequent calls 65*330d8983SJohannes Doerfert // will be checked for compatibility. 66*330d8983SJohannes Doerfert assert(NewFlags != OMP_REQ_UNDEFINED && 67*330d8983SJohannes Doerfert "illegal undefined flag for requires directive!"); 68*330d8983SJohannes Doerfert if (SetFlags == OMP_REQ_UNDEFINED) { 69*330d8983SJohannes Doerfert SetFlags = NewFlags; 70*330d8983SJohannes Doerfert return; 71*330d8983SJohannes Doerfert } 72*330d8983SJohannes Doerfert 73*330d8983SJohannes Doerfert // Auto zero-copy is only valid when no other requirement has been set 74*330d8983SJohannes Doerfert // and it is computed at device initialization time, after the requirement 75*330d8983SJohannes Doerfert // flag has already been set to OMP_REQ_NONE. 76*330d8983SJohannes Doerfert if (SetFlags == OMP_REQ_NONE && NewFlags == OMPX_REQ_AUTO_ZERO_COPY) { 77*330d8983SJohannes Doerfert SetFlags = NewFlags; 78*330d8983SJohannes Doerfert return; 79*330d8983SJohannes Doerfert } 80*330d8983SJohannes Doerfert 81*330d8983SJohannes Doerfert // If multiple compilation units are present enforce 82*330d8983SJohannes Doerfert // consistency across all of them for require clauses: 83*330d8983SJohannes Doerfert // - reverse_offload 84*330d8983SJohannes Doerfert // - unified_address 85*330d8983SJohannes Doerfert // - unified_shared_memory 86*330d8983SJohannes Doerfert // - dynamic_allocators 87*330d8983SJohannes Doerfert checkConsistency(NewFlags, SetFlags, OMP_REQ_REVERSE_OFFLOAD, 88*330d8983SJohannes Doerfert "reverse_offload"); 89*330d8983SJohannes Doerfert checkConsistency(NewFlags, SetFlags, OMP_REQ_UNIFIED_ADDRESS, 90*330d8983SJohannes Doerfert "unified_address"); 91*330d8983SJohannes Doerfert checkConsistency(NewFlags, SetFlags, OMP_REQ_UNIFIED_SHARED_MEMORY, 92*330d8983SJohannes Doerfert "unified_shared_memory"); 93*330d8983SJohannes Doerfert checkConsistency(NewFlags, SetFlags, OMP_REQ_DYNAMIC_ALLOCATORS, 94*330d8983SJohannes Doerfert "dynamic_allocators"); 95*330d8983SJohannes Doerfert } 96*330d8983SJohannes Doerfert 97*330d8983SJohannes Doerfert /// Return the user provided requirements. getRequirements()98*330d8983SJohannes Doerfert int64_t getRequirements() const { return SetFlags; } 99*330d8983SJohannes Doerfert }; 100*330d8983SJohannes Doerfert 101*330d8983SJohannes Doerfert #endif // OMPTARGET_OPENMP_DEVICE_REQUIREMENTS_H 102