Skip to content

Commit d23c614

Browse files
committed
[OpenMP] Introduce the OpenMP-IR-Builder
This is the initial patch for the OpenMP-IR-Builder, as discussed on the mailing list ([1] and later) and at the US Dev Meeting'19. The design is similar to D61953 but: - in a non-WIP status, with proper documentation and working. - using a OpenMPKinds.def file to manage lists of directives, runtime functions, types, ..., similar to the current Clang implementation. - restricted to handle only (simple) barriers, to implement most `#pragma omp barrier` directives and most implicit barriers. - properly hooked into Clang to be used if possible (D69922). - compatible with the remaining code generation. Parts have been extracted into D69853. The plan is to have multiple people working on moving logic from Clang here once the initial scaffolding (=this patch) landed. [1] http://lists.flang-compiler.org/pipermail/flang-dev_lists.flang-compiler.org/2019-May/000197.html Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim Subscribers: mgorny, hiraditya, bollu, guansong, jfb, cfe-commits, llvm-commits, penzn, ppenzin Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D69785
1 parent 6d64162 commit d23c614

File tree

9 files changed

+808
-1
lines changed

9 files changed

+808
-1
lines changed

llvm/include/llvm/Frontend/OpenMP/OMPConstants.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,18 @@
1414
#ifndef LLVM_OPENMP_CONSTANTS_H
1515
#define LLVM_OPENMP_CONSTANTS_H
1616

17+
#include "llvm/ADT/BitmaskEnum.h"
1718
#include "llvm/ADT/StringRef.h"
1819

1920
namespace llvm {
21+
class Type;
22+
class Module;
23+
class StructType;
24+
class PointerType;
25+
class FunctionType;
2026

2127
namespace omp {
28+
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
2229

2330
/// IDs for all OpenMP directives.
2431
enum class Directive {
@@ -33,12 +40,58 @@ enum class Directive {
3340
#define OMP_DIRECTIVE(Enum, ...) constexpr auto Enum = omp::Directive::Enum;
3441
#include "llvm/Frontend/OpenMP/OMPKinds.def"
3542

43+
/// IDs for all omp runtime library (RTL) functions.
44+
enum class RuntimeFunction {
45+
#define OMP_RTL(Enum, ...) Enum,
46+
#include "llvm/Frontend/OpenMP/OMPKinds.def"
47+
};
48+
49+
#define OMP_RTL(Enum, ...) constexpr auto Enum = omp::RuntimeFunction::Enum;
50+
#include "llvm/Frontend/OpenMP/OMPKinds.def"
51+
52+
/// IDs for all omp runtime library ident_t flag encodings (see
53+
/// their defintion in openmp/runtime/src/kmp.h).
54+
enum class IdentFlag {
55+
#define OMP_IDENT_FLAG(Enum, Str, Value) Enum = Value,
56+
#include "llvm/Frontend/OpenMP/OMPKinds.def"
57+
LLVM_MARK_AS_BITMASK_ENUM(0x7FFFFFFF)
58+
};
59+
60+
#define OMP_IDENT_FLAG(Enum, ...) constexpr auto Enum = omp::IdentFlag::Enum;
61+
#include "llvm/Frontend/OpenMP/OMPKinds.def"
62+
3663
/// Parse \p Str and return the directive it matches or OMPD_unknown if none.
3764
Directive getOpenMPDirectiveKind(StringRef Str);
3865

3966
/// Return a textual representation of the directive \p D.
4067
StringRef getOpenMPDirectiveName(Directive D);
4168

69+
/// Forward declarations for LLVM-IR types (simple, function and structure) are
70+
/// generated below. Their names are defined and used in OpenMPKinds.def. Here
71+
/// we provide the forward declarations, the initializeTypes function will
72+
/// provide the values.
73+
///
74+
///{
75+
namespace types {
76+
77+
#define OMP_TYPE(VarName, InitValue) extern Type *VarName;
78+
#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
79+
extern FunctionType *VarName; \
80+
extern PointerType *VarName##Ptr;
81+
#define OMP_STRUCT_TYPE(VarName, StrName, ...) \
82+
extern StructType *VarName; \
83+
extern PointerType *VarName##Ptr;
84+
#include "llvm/Frontend/OpenMP/OMPKinds.def"
85+
86+
/// Helper to initialize all types defined in OpenMPKinds.def.
87+
void initializeTypes(Module &M);
88+
89+
/// Helper to uninitialize all types defined in OpenMPKinds.def.
90+
void uninitializeTypes();
91+
92+
} // namespace types
93+
///}
94+
4295
} // end namespace omp
4396

4497
} // end namespace llvm
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
//===- IR/OpenMPIRBuilder.h - OpenMP encoding builder for LLVM IR - 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+
// This file defines the OpenMPIRBuilder class and helpers used as a convenient
10+
// way to create LLVM instructions for OpenMP directives.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_OPENMP_IR_IRBUILDER_H
15+
#define LLVM_OPENMP_IR_IRBUILDER_H
16+
17+
#include "llvm/IR/DebugLoc.h"
18+
#include "llvm/IR/IRBuilder.h"
19+
#include "llvm/Frontend/OpenMP/OMPConstants.h"
20+
21+
namespace llvm {
22+
23+
/// An interface to create LLVM-IR for OpenMP directives.
24+
///
25+
/// Each OpenMP directive has a corresponding public generator method.
26+
class OpenMPIRBuilder {
27+
public:
28+
/// Create a new OpenMPIRBuilder operating on the given module \p M. This will
29+
/// not have an effect on \p M (see initialize).
30+
OpenMPIRBuilder(Module &M) : M(M), Builder(M.getContext()) {}
31+
32+
/// Initialize the internal state, this will put structures types and
33+
/// potentially other helpers into the underlying module. Must be called
34+
/// before any other method and only once!
35+
void initialize();
36+
37+
/// Add attributes known for \p FnID to \p Fn.
38+
void addAttributes(omp::RuntimeFunction FnID, Function &Fn);
39+
40+
/// Set the cancellation block to \p CBB.
41+
void setCancellationBlock(BasicBlock *CBB) { CancellationBlock = CBB; }
42+
43+
/// Type used throughout for insertion points.
44+
using InsertPointTy = IRBuilder<>::InsertPoint;
45+
46+
/// Description of a LLVM-IR insertion point (IP) and a debug/source location
47+
/// (filename, line, column, ...).
48+
struct LocationDescription {
49+
template <typename T, typename U>
50+
LocationDescription(const IRBuilder<T, U> &IRB)
51+
: IP(IRB.saveIP()), DL(IRB.getCurrentDebugLocation()) {}
52+
LocationDescription(const InsertPointTy &IP) : IP(IP) {}
53+
LocationDescription(const InsertPointTy &IP, const DebugLoc &DL)
54+
: IP(IP), DL(DL) {}
55+
InsertPointTy IP;
56+
DebugLoc DL;
57+
};
58+
59+
/// Emitter methods for OpenMP directives.
60+
///
61+
///{
62+
63+
/// Generator for '#omp barrier'
64+
///
65+
/// \param Loc The location where the barrier directive was encountered.
66+
/// \param DK The kind of directive that caused the barrier.
67+
/// \param ForceSimpleCall Flag to force a simple (=non-cancellation) barrier.
68+
/// \param CheckCancelFlag Flag to indicate a cancel barrier return value
69+
/// should be checked and acted upon.
70+
///
71+
/// \returns The insertion point after the barrier.
72+
InsertPointTy CreateBarrier(const LocationDescription &Loc, omp::Directive DK,
73+
bool ForceSimpleCall = false,
74+
bool CheckCancelFlag = true);
75+
76+
///}
77+
78+
private:
79+
/// Update the internal location to \p Loc.
80+
bool updateToLocation(const LocationDescription &Loc) {
81+
Builder.restoreIP(Loc.IP);
82+
Builder.SetCurrentDebugLocation(Loc.DL);
83+
return Loc.IP.getBlock() != nullptr;
84+
}
85+
86+
/// Return the function declaration for the runtime function with \p FnID.
87+
Function *getOrCreateRuntimeFunction(omp::RuntimeFunction FnID);
88+
89+
/// Return the (LLVM-IR) string describing the source location \p LocStr.
90+
Constant *getOrCreateSrcLocStr(StringRef LocStr);
91+
92+
/// Return the (LLVM-IR) string describing the default source location.
93+
Constant *getOrCreateDefaultSrcLocStr();
94+
95+
/// Return the (LLVM-IR) string describing the source location \p Loc.
96+
Constant *getOrCreateSrcLocStr(const LocationDescription &Loc);
97+
98+
/// Return an ident_t* encoding the source location \p SrcLocStr and \p Flags.
99+
Value *getOrCreateIdent(Constant *SrcLocStr,
100+
omp::IdentFlag Flags = omp::IdentFlag(0));
101+
102+
/// Generate a barrier runtime call.
103+
///
104+
/// \param Loc The location at which the request originated and is fulfilled.
105+
/// \param DK The directive which caused the barrier
106+
/// \param ForceSimpleCall Flag to force a simple (=non-cancellation) barrier.
107+
/// \param CheckCancelFlag Flag to indicate a cancel barrier return value
108+
/// should be checked and acted upon.
109+
///
110+
/// \returns The insertion point after the barrier.
111+
InsertPointTy emitBarrierImpl(const LocationDescription &Loc,
112+
omp::Directive DK, bool ForceSimpleCall,
113+
bool CheckCancelFlag);
114+
115+
/// Return the current thread ID.
116+
///
117+
/// \param Ident The ident (ident_t*) describing the query origin.
118+
Value *getOrCreateThreadID(Value *Ident);
119+
120+
/// The underlying LLVM-IR module
121+
Module &M;
122+
123+
/// The LLVM-IR Builder used to create IR.
124+
IRBuilder<> Builder;
125+
126+
/// TODO: Stub for a cancellation block stack.
127+
BasicBlock *CancellationBlock = nullptr;
128+
129+
/// Map to remember source location strings
130+
StringMap<Constant *> SrcLocStrMap;
131+
132+
/// Map to remember existing ident_t*.
133+
DenseMap<std::pair<Constant *, uint64_t>, GlobalVariable *> IdentMap;
134+
};
135+
136+
} // end namespace llvm
137+
138+
#endif // LLVM_IR_IRBUILDER_H

llvm/include/llvm/Frontend/OpenMP/OMPKinds.def

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,137 @@ __OMP_DIRECTIVE(unknown)
100100
#undef OMP_DIRECTIVE
101101

102102
///}
103+
104+
/// Types used in runtime structs or runtime functions
105+
///
106+
///{
107+
108+
#ifndef OMP_TYPE
109+
#define OMP_TYPE(VarName, InitValue)
110+
#endif
111+
112+
#define __OMP_TYPE(VarName) OMP_TYPE(VarName, Type::get##VarName##Ty(Ctx))
113+
114+
__OMP_TYPE(Void)
115+
__OMP_TYPE(Int8)
116+
__OMP_TYPE(Int32)
117+
__OMP_TYPE(Int8Ptr)
118+
__OMP_TYPE(Int32Ptr)
119+
120+
#undef __OMP_TYPE
121+
#undef OMP_TYPE
122+
123+
///}
124+
125+
/// Struct and function types
126+
///
127+
///{
128+
129+
#ifndef OMP_STRUCT_TYPE
130+
#define OMP_STRUCT_TYPE(VarName, StructName, ...)
131+
#endif
132+
133+
#define __OMP_STRUCT_TYPE(VarName, Name, ...) \
134+
OMP_STRUCT_TYPE(VarName, "struct." #Name, __VA_ARGS__)
135+
136+
__OMP_STRUCT_TYPE(Ident, ident_t, Int32, Int32, Int32, Int32, Int8Ptr)
137+
138+
#undef __OMP_STRUCT_TYPE
139+
#undef OMP_STRUCT_TYPE
140+
141+
#ifndef OMP_FUNCTION_TYPE
142+
#define OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...)
143+
#endif
144+
145+
#define __OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, ...) \
146+
OMP_FUNCTION_TYPE(VarName, IsVarArg, ReturnType, __VA_ARGS__)
147+
148+
__OMP_FUNCTION_TYPE(ParallelTask, true, Void, Int32Ptr, Int32Ptr)
149+
150+
#undef __OMP_FUNCTION_TYPE
151+
#undef OMP_FUNCTION_TYPE
152+
153+
///}
154+
155+
/// Runtime library function (and their attributes)
156+
///
157+
///{
158+
159+
#ifndef OMP_RTL
160+
#define OMP_RTL(Enum, Str, IsVarArg, ReturnType, ...)
161+
#endif
162+
163+
#define __OMP_RTL(Name, IsVarArg, ReturnType, ...) \
164+
OMP_RTL(OMPRTL_##Name, #Name, IsVarArg, ReturnType, __VA_ARGS__)
165+
166+
__OMP_RTL(__kmpc_barrier, false, Void, IdentPtr, Int32)
167+
__OMP_RTL(__kmpc_cancel_barrier, false, Int32, IdentPtr, Int32)
168+
__OMP_RTL(__kmpc_global_thread_num, false, Int32, IdentPtr)
169+
__OMP_RTL(__kmpc_fork_call, true, Void, IdentPtr, Int32, ParallelTaskPtr)
170+
__OMP_RTL(omp_get_thread_num, false, Int32, )
171+
172+
#undef __OMP_RTL
173+
#undef OMP_RTL
174+
175+
#define EnumAttr(Kind) Attribute::get(Ctx, Attribute::AttrKind::Kind)
176+
#define AttributeSet(...) \
177+
AttributeSet::get(Ctx, ArrayRef<Attribute>({__VA_ARGS__}))
178+
179+
#ifndef OMP_ATTRS_SET
180+
#define OMP_ATTRS_SET(VarName, AttrSet)
181+
#endif
182+
183+
#define __OMP_ATTRS_SET(VarName, AttrSet) OMP_ATTRS_SET(VarName, AttrSet)
184+
185+
__OMP_ATTRS_SET(GetterAttrs,
186+
OptimisticAttributes
187+
? AttributeSet(EnumAttr(NoUnwind), EnumAttr(ReadOnly),
188+
EnumAttr(NoSync), EnumAttr(NoFree))
189+
: AttributeSet(EnumAttr(NoUnwind)))
190+
191+
#undef __OMP_ATTRS_SET
192+
#undef OMP_ATTRS_SET
193+
194+
#ifndef OMP_RTL_ATTRS
195+
#define OMP_RTL_ATTRS(Enum, FnAttrSet, RetAttrSet, ArgAttrSets)
196+
#endif
197+
198+
#define __OMP_RTL_ATTRS(Name, FnAttrSet, RetAttrSet, ArgAttrSets) \
199+
OMP_RTL_ATTRS(OMPRTL_##Name, FnAttrSet, RetAttrSet, ArgAttrSets)
200+
201+
__OMP_RTL_ATTRS(__kmpc_global_thread_num, GetterAttrs, AttributeSet(), {})
202+
__OMP_RTL_ATTRS(omp_get_thread_num, GetterAttrs, AttributeSet(), {})
203+
204+
#undef __OMP_RTL_ATTRS
205+
#undef OMP_RTL_ATTRS
206+
#undef AttributeSet
207+
#undef EnumAttr
208+
209+
///}
210+
211+
/// KMP ident_t bit flags
212+
///
213+
/// In accordance with the values in `openmp/runtime/src/kmp.h`.
214+
///
215+
///{
216+
217+
#ifndef OMP_IDENT_FLAG
218+
#define OMP_IDENT_FLAG(Enum, Str, Value)
219+
#endif
220+
221+
#define __OMP_IDENT_FLAG(Name, Value) \
222+
OMP_IDENT_FLAG(OMP_IDENT_FLAG_##Name, #Name, Value)
223+
224+
__OMP_IDENT_FLAG(KMPC, 0x02)
225+
__OMP_IDENT_FLAG(BARRIER_EXPL, 0x20)
226+
__OMP_IDENT_FLAG(BARRIER_IMPL, 0x0040)
227+
__OMP_IDENT_FLAG(BARRIER_IMPL_MASK, 0x01C0)
228+
__OMP_IDENT_FLAG(BARRIER_IMPL_FOR, 0x0040)
229+
__OMP_IDENT_FLAG(BARRIER_IMPL_SECTIONS, 0x00C0)
230+
__OMP_IDENT_FLAG(BARRIER_IMPL_SINGLE, 0x0140)
231+
__OMP_IDENT_FLAG(BARRIER_IMPL_WORKSHARE, 0x01C0)
232+
233+
#undef __OMP_IDENT_FLAG
234+
#undef OMP_IDENT_FLAG
235+
236+
///}

llvm/lib/Frontend/OpenMP/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
add_llvm_component_library(LLVMFrontendOpenMP
22
OMPConstants.cpp
3+
OMPIRBuilder.cpp
34

45
ADDITIONAL_HEADER_DIRS
56
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
6-
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend/OpenMP
7+
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend/OpenMP/OMP
78

89
DEPENDS
910
intrinsics_gen

0 commit comments

Comments
 (0)