xref: /llvm-project/offload/include/Shared/Requirements.h (revision 330d8983d25d08580fc1642fea48b2473f47a9da)
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