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