Skip to content

Commit

Permalink
[OpenMP][OMPIRBuilder] Add a configuration class that captures flags …
Browse files Browse the repository at this point in the history
…that affect codegen

This patch introudces the OpenMPIRBuilderConfig class which contains various
flags that are needed to lower OMP constructs to LLVM-IR. The purpose is to
keep the flags in one place so they do not have to be passed in every time.
The flags can be set optionally since some uses cases don't rely on functions
that depend on these flags.

Reviewed By: jdoerfert, tschuett

Differential Revision: https://reviews.llvm.org/D138220
  • Loading branch information
jsjodin committed Nov 22, 2022
1 parent cb261e3 commit 969d787
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 47 deletions.
22 changes: 11 additions & 11 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Expand Up @@ -1062,9 +1062,13 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
: CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager() {
KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
llvm::OpenMPIRBuilderConfig Config(CGM.getLangOpts().OpenMPIsDevice, false,
hasRequiresUnifiedSharedMemory());

// Initialize Types used in OpenMPIRBuilder from OMPKinds.def
OMPBuilder.initialize();
OMPBuilder.setConfig(Config);
OffloadEntriesInfoManager.setConfig(Config);
loadOffloadInfoMetadata();
}

Expand Down Expand Up @@ -1910,8 +1914,7 @@ bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
CtorEntryInfo.ParentName = Twine(Buffer, "_ctor").toStringRef(Out);
OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
CtorEntryInfo, Ctor, ID,
llvm::OffloadEntriesInfoManager::OMPTargetRegionEntryCtor,
CGM.getLangOpts().OpenMPIsDevice);
llvm::OffloadEntriesInfoManager::OMPTargetRegionEntryCtor);
}
if (VD->getType().isDestructedType() != QualType::DK_none) {
llvm::Constant *Dtor;
Expand Down Expand Up @@ -1960,8 +1963,7 @@ bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
DtorEntryInfo.ParentName = Twine(Buffer, "_dtor").toStringRef(Out);
OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
DtorEntryInfo, Dtor, ID,
llvm::OffloadEntriesInfoManager::OMPTargetRegionEntryDtor,
CGM.getLangOpts().OpenMPIsDevice);
llvm::OffloadEntriesInfoManager::OMPTargetRegionEntryDtor);
}
return CGM.getLangOpts().OpenMPIsDevice;
}
Expand Down Expand Up @@ -2980,10 +2982,8 @@ void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
}
};

OMPBuilder.createOffloadEntriesAndInfoMetadata(
OffloadEntriesInfoManager, isTargetCodegen(),
CGM.getLangOpts().OpenMPIsDevice,
CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory(), ErrorReportFn);
OMPBuilder.createOffloadEntriesAndInfoMetadata(OffloadEntriesInfoManager,
ErrorReportFn);
}

/// Loads all the offload entries information from the host IR
Expand Down Expand Up @@ -6153,8 +6153,7 @@ void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
// Register the information for the entry associated with this target region.
OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
EntryInfo, TargetRegionEntryAddr, OutlinedFnID,
llvm::OffloadEntriesInfoManager::OMPTargetRegionEntryTargetRegion,
CGM.getLangOpts().OpenMPIsDevice);
llvm::OffloadEntriesInfoManager::OMPTargetRegionEntryTargetRegion);

// Add NumTeams and ThreadLimit attributes to the outlined GPU function
int32_t DefaultValTeams = -1;
Expand Down Expand Up @@ -10419,7 +10418,7 @@ void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
}

OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
VarName, Addr, VarSize, Flags, Linkage, CGM.getLangOpts().OpenMPIsDevice);
VarName, Addr, VarSize, Flags, Linkage);
}

bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Expand Down Expand Up @@ -10461,6 +10460,7 @@ void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) {
for (const OMPClause *Clause : D->clauselists()) {
if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
HasRequiresUnifiedSharedMemory = true;
OMPBuilder.Config.setHasRequiresUnifiedSharedMemory(true);
} else if (const auto *AC =
dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
switch (AC->getAtomicDefaultMemOrderKind()) {
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/CodeGen/CGOpenMPRuntime.h
Expand Up @@ -413,8 +413,7 @@ class CGOpenMPRuntime {
///
llvm::Value *getCriticalRegionLock(StringRef CriticalName);

private:

protected:
/// Map for SourceLocation and OpenMP runtime library debug locations.
typedef llvm::DenseMap<SourceLocation, llvm::Value *> OpenMPDebugLocMapTy;
OpenMPDebugLocMapTy OpenMPDebugLocMap;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
Expand Up @@ -890,6 +890,11 @@ unsigned CGOpenMPRuntimeGPU::getDefaultLocationReserved2Flags() const {

CGOpenMPRuntimeGPU::CGOpenMPRuntimeGPU(CodeGenModule &CGM)
: CGOpenMPRuntime(CGM, "_", "$") {
llvm::OpenMPIRBuilderConfig Config(CGM.getLangOpts().OpenMPIsDevice, true,
hasRequiresUnifiedSharedMemory());
OMPBuilder.setConfig(Config);
OffloadEntriesInfoManager.setConfig(Config);

if (!CGM.getLangOpts().OpenMPIsDevice)
llvm_unreachable("OpenMP can only handle device code.");

Expand Down
79 changes: 66 additions & 13 deletions llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
Expand Up @@ -73,13 +73,62 @@ BasicBlock *splitBB(IRBuilder<> &Builder, bool CreateBranch, llvm::Twine Name);
BasicBlock *splitBBWithSuffix(IRBuilderBase &Builder, bool CreateBranch,
llvm::Twine Suffix = ".split");

/// Captures attributes that affect generating LLVM-IR using the
/// OpenMPIRBuilder and related classes. Note that not all attributes are
/// required for all classes or functions. In some use cases the configuration
/// is not necessary at all, because because the only functions that are called
/// are ones that are not dependent on the configuration.
class OpenMPIRBuilderConfig {
public:
/// Flag for specifying if the compilation is done for embedded device code
/// or host code.
Optional<bool> IsEmbedded;

/// Flag for specifying if the compilation is done for an offloading target,
/// like GPU.
Optional<bool> IsTargetCodegen;

/// Flag for specifying weather a requires unified_shared_memory
/// directive is present or not.
Optional<bool> HasRequiresUnifiedSharedMemory;

OpenMPIRBuilderConfig() {}
OpenMPIRBuilderConfig(bool IsEmbedded, bool IsTargetCodegen,
bool HasRequiresUnifiedSharedMemory)
: IsEmbedded(IsEmbedded), IsTargetCodegen(IsTargetCodegen),
HasRequiresUnifiedSharedMemory(HasRequiresUnifiedSharedMemory) {}

// Convenience getter functions that assert if the value is not present.
bool isEmbedded() {
assert(IsEmbedded.has_value() && "IsEmbedded is not set");
return IsEmbedded.value();
}

bool isTargetCodegen() {
assert(IsTargetCodegen.has_value() && "IsTargetCodegen is not set");
return IsTargetCodegen.value();
}

bool hasRequiresUnifiedSharedMemory() {
assert(HasRequiresUnifiedSharedMemory.has_value() &&
"HasUnifiedSharedMemory is not set");
return HasRequiresUnifiedSharedMemory.value();
}

void setIsEmbedded(bool Value) { IsEmbedded = Value; }
void setIsTargetCodegen(bool Value) { IsTargetCodegen = Value; }
void setHasRequiresUnifiedSharedMemory(bool Value) {
HasRequiresUnifiedSharedMemory = Value;
}
};

/// An interface to create LLVM-IR for OpenMP directives.
///
/// Each OpenMP directive has a corresponding public generator method.
class OpenMPIRBuilder {
public:
/// Create a new OpenMPIRBuilder operating on the given module \p M. This will
/// not have an effect on \p M (see initialize).
/// not have an effect on \p M (see initialize)
OpenMPIRBuilder(Module &M) : M(M), Builder(M.getContext()) {}
~OpenMPIRBuilder();

Expand All @@ -88,6 +137,8 @@ class OpenMPIRBuilder {
/// before any other method and only once!
void initialize();

void setConfig(OpenMPIRBuilderConfig C) { Config = C; }

/// Finalize the underlying module, e.g., by outlining regions.
/// \param Fn The function to be finalized. If not used,
/// all functions are finalized.
Expand Down Expand Up @@ -942,6 +993,9 @@ class OpenMPIRBuilder {
/// \param Ident The ident (ident_t*) describing the query origin.
Value *getOrCreateThreadID(Value *Ident);

/// The OpenMPIRBuilder Configuration
OpenMPIRBuilderConfig Config;

/// The underlying LLVM-IR module
Module &M;

Expand Down Expand Up @@ -1094,11 +1148,10 @@ class OpenMPIRBuilder {
bool EmitDebug = false,
bool ForEndCall = false);

/// Creates offloading entry for the provided entry ID \a ID,
/// address \a Addr, size \a Size, and flags \a Flags.
void createOffloadEntry(bool IsTargetCodegen, Constant *ID, Constant *Addr,
uint64_t Size, int32_t Flags,
GlobalValue::LinkageTypes);
/// Creates offloading entry for the provided entry ID \a ID, address \a
/// Addr, size \a Size, and flags \a Flags.
void createOffloadEntry(Constant *ID, Constant *Addr, uint64_t Size,
int32_t Flags, GlobalValue::LinkageTypes);

/// The kind of errors that can occur when emitting the offload entries and
/// metadata.
Expand All @@ -1121,8 +1174,6 @@ class OpenMPIRBuilder {
// We only generate metadata for function that contain target regions.
void createOffloadEntriesAndInfoMetadata(
OffloadEntriesInfoManager &OffloadEntriesInfoManager,
bool IsTargetCodegen, bool IsEmbedded,
bool HasRequiresUnifiedSharedMemory,
EmitMetadataErrorReportFunctionTy &ErrorReportFunction);

public:
Expand Down Expand Up @@ -1759,9 +1810,12 @@ struct TargetRegionEntryInfo {
/// Class that manages information about offload code regions and data
class OffloadEntriesInfoManager {
/// Number of entries registered so far.
OpenMPIRBuilderConfig Config;
unsigned OffloadingEntriesNum = 0;

public:
void setConfig(OpenMPIRBuilderConfig C) { Config = C; }

/// Base class of the entries info.
class OffloadEntryInfo {
public:
Expand Down Expand Up @@ -1813,7 +1867,8 @@ class OffloadEntriesInfoManager {
bool empty() const;
/// Return number of entries defined so far.
unsigned size() const { return OffloadingEntriesNum; }
explicit OffloadEntriesInfoManager() {}

OffloadEntriesInfoManager() : Config() {}

//
// Target region entries related.
Expand Down Expand Up @@ -1862,8 +1917,7 @@ class OffloadEntriesInfoManager {
/// Register target region entry.
void registerTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo,
Constant *Addr, Constant *ID,
OMPTargetRegionEntryKind Flags,
bool IsDevice);
OMPTargetRegionEntryKind Flags);
/// Return true if a target region entry with the provided information
/// exists.
bool hasTargetRegionEntryInfo(TargetRegionEntryInfo EntryInfo,
Expand Down Expand Up @@ -1932,8 +1986,7 @@ class OffloadEntriesInfoManager {
void registerDeviceGlobalVarEntryInfo(StringRef VarName, Constant *Addr,
int64_t VarSize,
OMPTargetGlobalVarEntryKind Flags,
GlobalValue::LinkageTypes Linkage,
bool IsDevice);
GlobalValue::LinkageTypes Linkage);
/// Checks if the variable with the given name has been registered already.
bool hasDeviceGlobalVarEntryInfo(StringRef VarName) const {
return OffloadEntriesDeviceGlobalVar.count(VarName) > 0;
Expand Down
33 changes: 15 additions & 18 deletions llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
Expand Up @@ -4683,11 +4683,10 @@ void OpenMPIRBuilder::OutlineInfo::collectBlocks(
}
}

void OpenMPIRBuilder::createOffloadEntry(bool IsTargetCodegen, Constant *ID,
Constant *Addr, uint64_t Size,
int32_t Flags,
void OpenMPIRBuilder::createOffloadEntry(Constant *ID, Constant *Addr,
uint64_t Size, int32_t Flags,
GlobalValue::LinkageTypes) {
if (!IsTargetCodegen) {
if (!Config.isTargetCodegen()) {
emitOffloadingEntry(ID, Addr->getName(), Size, Flags);
return;
}
Expand Down Expand Up @@ -4715,8 +4714,7 @@ void OpenMPIRBuilder::createOffloadEntry(bool IsTargetCodegen, Constant *ID,

// We only generate metadata for function that contain target regions.
void OpenMPIRBuilder::createOffloadEntriesAndInfoMetadata(
OffloadEntriesInfoManager &OffloadEntriesInfoManager, bool IsTargetCodegen,
bool IsEmbedded, bool HasRequiresUnifiedSharedMemory,
OffloadEntriesInfoManager &OffloadEntriesInfoManager,
EmitMetadataErrorReportFunctionTy &ErrorFn) {

// If there are no entries, we don't need to do anything.
Expand Down Expand Up @@ -4809,7 +4807,7 @@ void OpenMPIRBuilder::createOffloadEntriesAndInfoMetadata(
ErrorFn(EMIT_MD_TARGET_REGION_ERROR, EntryInfo);
continue;
}
createOffloadEntry(IsTargetCodegen, CE->getID(), CE->getAddress(),
createOffloadEntry(CE->getID(), CE->getAddress(),
/*Size=*/0, CE->getFlags(),
GlobalValue::WeakAnyLinkage);
} else if (const auto *CE = dyn_cast<
Expand All @@ -4820,7 +4818,7 @@ void OpenMPIRBuilder::createOffloadEntriesAndInfoMetadata(
CE->getFlags());
switch (Flags) {
case OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo: {
if (IsEmbedded && HasRequiresUnifiedSharedMemory)
if (Config.isEmbedded() && Config.hasRequiresUnifiedSharedMemory())
continue;
if (!CE->getAddress()) {
ErrorFn(EMIT_MD_DECLARE_TARGET_ERROR, E.second);
Expand All @@ -4832,10 +4830,10 @@ void OpenMPIRBuilder::createOffloadEntriesAndInfoMetadata(
break;
}
case OffloadEntriesInfoManager::OMPTargetGlobalVarEntryLink:
assert(((IsEmbedded && !CE->getAddress()) ||
(!IsEmbedded && CE->getAddress())) &&
assert(((Config.isEmbedded() && !CE->getAddress()) ||
(!Config.isEmbedded() && CE->getAddress())) &&
"Declaret target link address is set.");
if (IsEmbedded)
if (Config.isEmbedded())
continue;
if (!CE->getAddress()) {
ErrorFn(EMIT_MD_GLOBAL_VAR_LINK_ERROR, TargetRegionEntryInfo());
Expand All @@ -4851,8 +4849,8 @@ void OpenMPIRBuilder::createOffloadEntriesAndInfoMetadata(
if (GV->hasLocalLinkage() || GV->hasHiddenVisibility())
continue;

createOffloadEntry(IsTargetCodegen, CE->getAddress(), CE->getAddress(),
CE->getVarSize(), Flags, CE->getLinkage());
createOffloadEntry(CE->getAddress(), CE->getAddress(), CE->getVarSize(),
Flags, CE->getLinkage());

} else {
llvm_unreachable("Unsupported entry kind.");
Expand Down Expand Up @@ -4958,15 +4956,15 @@ void OffloadEntriesInfoManager::initializeTargetRegionEntryInfo(

void OffloadEntriesInfoManager::registerTargetRegionEntryInfo(
TargetRegionEntryInfo EntryInfo, Constant *Addr, Constant *ID,
OMPTargetRegionEntryKind Flags, bool IsDevice) {
OMPTargetRegionEntryKind Flags) {
assert(EntryInfo.Count == 0 && "expected default EntryInfo");

// Update the EntryInfo with the next available count for this location.
EntryInfo.Count = getTargetRegionEntryInfoCount(EntryInfo);

// If we are emitting code for a target, the entry is already initialized,
// only has to be registered.
if (IsDevice) {
if (Config.isEmbedded()) {
// This could happen if the device compilation is invoked standalone.
if (!hasTargetRegionEntryInfo(EntryInfo)) {
return;
Expand Down Expand Up @@ -5020,9 +5018,8 @@ void OffloadEntriesInfoManager::initializeDeviceGlobalVarEntryInfo(

void OffloadEntriesInfoManager::registerDeviceGlobalVarEntryInfo(
StringRef VarName, Constant *Addr, int64_t VarSize,
OMPTargetGlobalVarEntryKind Flags, GlobalValue::LinkageTypes Linkage,
bool IsDevice) {
if (IsDevice) {
OMPTargetGlobalVarEntryKind Flags, GlobalValue::LinkageTypes Linkage) {
if (Config.isEmbedded()) {
// This could happen if the device compilation is invoked standalone.
if (!hasDeviceGlobalVarEntryInfo(VarName))
return;
Expand Down
7 changes: 4 additions & 3 deletions llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp
Expand Up @@ -5504,17 +5504,18 @@ TEST_F(OpenMPIRBuilderTest, EmitOffloadingArraysArguments) {

TEST_F(OpenMPIRBuilderTest, OffloadEntriesInfoManager) {
OffloadEntriesInfoManager InfoManager;
InfoManager.setConfig(OpenMPIRBuilderConfig(true, false, false));
TargetRegionEntryInfo EntryInfo("parent", 1, 2, 4, 0);
InfoManager.initializeTargetRegionEntryInfo(EntryInfo, 0);
EXPECT_TRUE(InfoManager.hasTargetRegionEntryInfo(EntryInfo, true));
EXPECT_TRUE(InfoManager.hasTargetRegionEntryInfo(EntryInfo));
InfoManager.initializeDeviceGlobalVarEntryInfo(
"gvar", OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo, 0);
InfoManager.registerTargetRegionEntryInfo(
EntryInfo, nullptr, nullptr,
OffloadEntriesInfoManager::OMPTargetRegionEntryTargetRegion, true);
OffloadEntriesInfoManager::OMPTargetRegionEntryTargetRegion);
InfoManager.registerDeviceGlobalVarEntryInfo(
"gvar", 0x0, 8, OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo,
GlobalValue::WeakAnyLinkage, true);
GlobalValue::WeakAnyLinkage);
EXPECT_TRUE(InfoManager.hasDeviceGlobalVarEntryInfo("gvar"));
}
} // namespace

0 comments on commit 969d787

Please sign in to comment.