: 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();
}
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;
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;
}
}
};
- 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
// 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;
}
OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
- VarName, Addr, VarSize, Flags, Linkage, CGM.getLangOpts().OpenMPIsDevice);
+ VarName, Addr, VarSize, Flags, Linkage);
}
bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
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()) {
///
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;
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.");
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();
/// 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.
/// \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;
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.
// We only generate metadata for function that contain target regions.
void createOffloadEntriesAndInfoMetadata(
OffloadEntriesInfoManager &OffloadEntriesInfoManager,
- bool IsTargetCodegen, bool IsEmbedded,
- bool HasRequiresUnifiedSharedMemory,
EmitMetadataErrorReportFunctionTy &ErrorReportFunction);
public:
/// 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:
bool empty() const;
/// Return number of entries defined so far.
unsigned size() const { return OffloadingEntriesNum; }
- explicit OffloadEntriesInfoManager() {}
+
+ OffloadEntriesInfoManager() : Config() {}
//
// Target region entries related.
/// 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,
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;
}
}
-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;
}
// 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.
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<
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);
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());
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.");
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.
// 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;
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;
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