|
@@ -1264,6 +1264,51 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
|
|
loadOffloadInfoMetadata();
|
|
loadOffloadInfoMetadata();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool tryEmitAlias(CodeGenModule &CGM, const GlobalDecl &NewGD,
|
|
|
|
+ const GlobalDecl &OldGD, llvm::GlobalValue *OrigAddr,
|
|
|
|
+ bool IsForDefinition) {
|
|
|
|
+ // Emit at least a definition for the aliasee if the the address of the
|
|
|
|
+ // original function is requested.
|
|
|
|
+ if (IsForDefinition || OrigAddr)
|
|
|
|
+ (void)CGM.GetAddrOfGlobal(NewGD);
|
|
|
|
+ StringRef NewMangledName = CGM.getMangledName(NewGD);
|
|
|
|
+ llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName);
|
|
|
|
+ if (Addr && !Addr->isDeclaration()) {
|
|
|
|
+ const auto *D = cast<FunctionDecl>(OldGD.getDecl());
|
|
|
|
+ const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(OldGD);
|
|
|
|
+ llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI);
|
|
|
|
+
|
|
|
|
+ // Create a reference to the named value. This ensures that it is emitted
|
|
|
|
+ // if a deferred decl.
|
|
|
|
+ llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD);
|
|
|
|
+
|
|
|
|
+ // Create the new alias itself, but don't set a name yet.
|
|
|
|
+ auto *GA =
|
|
|
|
+ llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule());
|
|
|
|
+
|
|
|
|
+ if (OrigAddr) {
|
|
|
|
+ assert(OrigAddr->isDeclaration() && "Expected declaration");
|
|
|
|
+
|
|
|
|
+ GA->takeName(OrigAddr);
|
|
|
|
+ OrigAddr->replaceAllUsesWith(
|
|
|
|
+ llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType()));
|
|
|
|
+ OrigAddr->eraseFromParent();
|
|
|
|
+ } else {
|
|
|
|
+ GA->setName(CGM.getMangledName(OldGD));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Set attributes which are particular to an alias; this is a
|
|
|
|
+ // specialization of the attributes which may be set on a global function.
|
|
|
|
+ if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() ||
|
|
|
|
+ D->isWeakImported())
|
|
|
|
+ GA->setLinkage(llvm::Function::WeakAnyLinkage);
|
|
|
|
+
|
|
|
|
+ CGM.SetCommonAttributes(OldGD, GA);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
void CGOpenMPRuntime::clear() {
|
|
void CGOpenMPRuntime::clear() {
|
|
InternalVars.clear();
|
|
InternalVars.clear();
|
|
// Clean non-target variable declarations possibly used only in debug info.
|
|
// Clean non-target variable declarations possibly used only in debug info.
|
|
@@ -1277,6 +1322,14 @@ void CGOpenMPRuntime::clear() {
|
|
continue;
|
|
continue;
|
|
GV->eraseFromParent();
|
|
GV->eraseFromParent();
|
|
}
|
|
}
|
|
|
|
+ // Emit aliases for the deferred aliasees.
|
|
|
|
+ for (const auto &Pair : DeferredVariantFunction) {
|
|
|
|
+ StringRef MangledName = CGM.getMangledName(Pair.second.second);
|
|
|
|
+ llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName);
|
|
|
|
+ // If not able to emit alias, just emit original declaration.
|
|
|
|
+ (void)tryEmitAlias(CGM, Pair.second.first, Pair.second.second, Addr,
|
|
|
|
+ /*IsForDefinition=*/false);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
|
|
std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
|
|
@@ -11086,6 +11139,80 @@ Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
|
|
return Address(Addr, Align);
|
|
return Address(Addr, Align);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/// Checks current context and returns true if it matches the context selector.
|
|
|
|
+template <OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
|
|
|
|
+ OMPDeclareVariantAttr::CtxSelectorType Ctx>
|
|
|
|
+static bool checkContext(const OMPDeclareVariantAttr *A) {
|
|
|
|
+ assert(CtxSet != OMPDeclareVariantAttr::CtxSetUnknown &&
|
|
|
|
+ Ctx != OMPDeclareVariantAttr::CtxUnknown &&
|
|
|
|
+ "Unknown context selector or context selector set.");
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// Checks for implementation={vendor(<vendor>)} context selector.
|
|
|
|
+/// \returns true iff <vendor>="llvm", false otherwise.
|
|
|
|
+template <>
|
|
|
|
+bool checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
|
|
|
|
+ OMPDeclareVariantAttr::CtxVendor>(
|
|
|
|
+ const OMPDeclareVariantAttr *A) {
|
|
|
|
+ return !A->getImplVendor().compare("llvm");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// Finds the variant function that matches current context with its context
|
|
|
|
+/// selector.
|
|
|
|
+static const FunctionDecl *getDeclareVariantFunction(const FunctionDecl *FD) {
|
|
|
|
+ if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
|
|
|
|
+ return FD;
|
|
|
|
+ // Iterate through all DeclareVariant attributes and check context selectors.
|
|
|
|
+ SmallVector<const OMPDeclareVariantAttr *, 4> MatchingAttributes;
|
|
|
|
+ for (const auto * A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
|
|
|
|
+ switch (A->getCtxSelectorSet()) {
|
|
|
|
+ case OMPDeclareVariantAttr::CtxSetImplementation:
|
|
|
|
+ switch (A->getCtxSelector()) {
|
|
|
|
+ case OMPDeclareVariantAttr::CtxVendor:
|
|
|
|
+ if (checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
|
|
|
|
+ OMPDeclareVariantAttr::CtxVendor>(A))
|
|
|
|
+ MatchingAttributes.push_back(A);
|
|
|
|
+ break;
|
|
|
|
+ case OMPDeclareVariantAttr::CtxUnknown:
|
|
|
|
+ llvm_unreachable(
|
|
|
|
+ "Unknown context selector in implementation selctor set.");
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ case OMPDeclareVariantAttr::CtxSetUnknown:
|
|
|
|
+ llvm_unreachable("Unknown context selector set.");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (MatchingAttributes.empty())
|
|
|
|
+ return FD;
|
|
|
|
+ // TODO: implement score analysis of multiple context selectors.
|
|
|
|
+ const OMPDeclareVariantAttr *MainAttr = MatchingAttributes.front();
|
|
|
|
+ return cast<FunctionDecl>(
|
|
|
|
+ cast<DeclRefExpr>(MainAttr->getVariantFuncRef()->IgnoreParenImpCasts())
|
|
|
|
+ ->getDecl());
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
|
|
|
|
+ const auto *D = cast<FunctionDecl>(GD.getDecl());
|
|
|
|
+ // If the original function is defined already, use its definition.
|
|
|
|
+ StringRef MangledName = CGM.getMangledName(GD);
|
|
|
|
+ llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
|
|
|
|
+ if (Orig && !Orig->isDeclaration())
|
|
|
|
+ return false;
|
|
|
|
+ const FunctionDecl *NewFD = getDeclareVariantFunction(D);
|
|
|
|
+ // Emit original function if it does not have declare variant attribute or the
|
|
|
|
+ // context does not match.
|
|
|
|
+ if (NewFD == D)
|
|
|
|
+ return false;
|
|
|
|
+ GlobalDecl NewGD = GD.getWithDecl(NewFD);
|
|
|
|
+ if (tryEmitAlias(CGM, NewGD, GD, Orig, IsForDefinition)) {
|
|
|
|
+ DeferredVariantFunction.erase(D);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
|
|
llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
|
|
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
|
|
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
|
|
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
|
|
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
|