@@ -1264,6 +1264,51 @@ CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1264
1264
loadOffloadInfoMetadata ();
1265
1265
}
1266
1266
1267
+ static bool tryEmitAlias (CodeGenModule &CGM, const GlobalDecl &NewGD,
1268
+ const GlobalDecl &OldGD, llvm::GlobalValue *OrigAddr,
1269
+ bool IsForDefinition) {
1270
+ // Emit at least a definition for the aliasee if the the address of the
1271
+ // original function is requested.
1272
+ if (IsForDefinition || OrigAddr)
1273
+ (void )CGM.GetAddrOfGlobal (NewGD);
1274
+ StringRef NewMangledName = CGM.getMangledName (NewGD);
1275
+ llvm::GlobalValue *Addr = CGM.GetGlobalValue (NewMangledName);
1276
+ if (Addr && !Addr->isDeclaration ()) {
1277
+ const auto *D = cast<FunctionDecl>(OldGD.getDecl ());
1278
+ const CGFunctionInfo &FI = CGM.getTypes ().arrangeGlobalDeclaration (OldGD);
1279
+ llvm::Type *DeclTy = CGM.getTypes ().GetFunctionType (FI);
1280
+
1281
+ // Create a reference to the named value. This ensures that it is emitted
1282
+ // if a deferred decl.
1283
+ llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage (OldGD);
1284
+
1285
+ // Create the new alias itself, but don't set a name yet.
1286
+ auto *GA =
1287
+ llvm::GlobalAlias::create (DeclTy, 0 , LT, " " , Addr, &CGM.getModule ());
1288
+
1289
+ if (OrigAddr) {
1290
+ assert (OrigAddr->isDeclaration () && " Expected declaration" );
1291
+
1292
+ GA->takeName (OrigAddr);
1293
+ OrigAddr->replaceAllUsesWith (
1294
+ llvm::ConstantExpr::getBitCast (GA, OrigAddr->getType ()));
1295
+ OrigAddr->eraseFromParent ();
1296
+ } else {
1297
+ GA->setName (CGM.getMangledName (OldGD));
1298
+ }
1299
+
1300
+ // Set attributes which are particular to an alias; this is a
1301
+ // specialization of the attributes which may be set on a global function.
1302
+ if (D->hasAttr <WeakAttr>() || D->hasAttr <WeakRefAttr>() ||
1303
+ D->isWeakImported ())
1304
+ GA->setLinkage (llvm::Function::WeakAnyLinkage);
1305
+
1306
+ CGM.SetCommonAttributes (OldGD, GA);
1307
+ return true ;
1308
+ }
1309
+ return false ;
1310
+ }
1311
+
1267
1312
void CGOpenMPRuntime::clear () {
1268
1313
InternalVars.clear ();
1269
1314
// Clean non-target variable declarations possibly used only in debug info.
@@ -1277,6 +1322,14 @@ void CGOpenMPRuntime::clear() {
1277
1322
continue ;
1278
1323
GV->eraseFromParent ();
1279
1324
}
1325
+ // Emit aliases for the deferred aliasees.
1326
+ for (const auto &Pair : DeferredVariantFunction) {
1327
+ StringRef MangledName = CGM.getMangledName (Pair.second .second );
1328
+ llvm::GlobalValue *Addr = CGM.GetGlobalValue (MangledName);
1329
+ // If not able to emit alias, just emit original declaration.
1330
+ (void )tryEmitAlias (CGM, Pair.second .first , Pair.second .second , Addr,
1331
+ /* IsForDefinition=*/ false );
1332
+ }
1280
1333
}
1281
1334
1282
1335
std::string CGOpenMPRuntime::getName (ArrayRef<StringRef> Parts) const {
@@ -11086,6 +11139,80 @@ Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11086
11139
return Address (Addr, Align);
11087
11140
}
11088
11141
11142
+ // / Checks current context and returns true if it matches the context selector.
11143
+ template <OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
11144
+ OMPDeclareVariantAttr::CtxSelectorType Ctx>
11145
+ static bool checkContext (const OMPDeclareVariantAttr *A) {
11146
+ assert (CtxSet != OMPDeclareVariantAttr::CtxSetUnknown &&
11147
+ Ctx != OMPDeclareVariantAttr::CtxUnknown &&
11148
+ " Unknown context selector or context selector set." );
11149
+ return false ;
11150
+ }
11151
+
11152
+ // / Checks for implementation={vendor(<vendor>)} context selector.
11153
+ // / \returns true iff <vendor>="llvm", false otherwise.
11154
+ template <>
11155
+ bool checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
11156
+ OMPDeclareVariantAttr::CtxVendor>(
11157
+ const OMPDeclareVariantAttr *A) {
11158
+ return !A->getImplVendor ().compare (" llvm" );
11159
+ }
11160
+
11161
+ // / Finds the variant function that matches current context with its context
11162
+ // / selector.
11163
+ static const FunctionDecl *getDeclareVariantFunction (const FunctionDecl *FD) {
11164
+ if (!FD->hasAttrs () || !FD->hasAttr <OMPDeclareVariantAttr>())
11165
+ return FD;
11166
+ // Iterate through all DeclareVariant attributes and check context selectors.
11167
+ SmallVector<const OMPDeclareVariantAttr *, 4 > MatchingAttributes;
11168
+ for (const auto * A : FD->specific_attrs <OMPDeclareVariantAttr>()) {
11169
+ switch (A->getCtxSelectorSet ()) {
11170
+ case OMPDeclareVariantAttr::CtxSetImplementation:
11171
+ switch (A->getCtxSelector ()) {
11172
+ case OMPDeclareVariantAttr::CtxVendor:
11173
+ if (checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
11174
+ OMPDeclareVariantAttr::CtxVendor>(A))
11175
+ MatchingAttributes.push_back (A);
11176
+ break ;
11177
+ case OMPDeclareVariantAttr::CtxUnknown:
11178
+ llvm_unreachable (
11179
+ " Unknown context selector in implementation selctor set." );
11180
+ }
11181
+ break ;
11182
+ case OMPDeclareVariantAttr::CtxSetUnknown:
11183
+ llvm_unreachable (" Unknown context selector set." );
11184
+ }
11185
+ }
11186
+ if (MatchingAttributes.empty ())
11187
+ return FD;
11188
+ // TODO: implement score analysis of multiple context selectors.
11189
+ const OMPDeclareVariantAttr *MainAttr = MatchingAttributes.front ();
11190
+ return cast<FunctionDecl>(
11191
+ cast<DeclRefExpr>(MainAttr->getVariantFuncRef ()->IgnoreParenImpCasts ())
11192
+ ->getDecl ());
11193
+ }
11194
+
11195
+ bool CGOpenMPRuntime::emitDeclareVariant (GlobalDecl GD, bool IsForDefinition) {
11196
+ const auto *D = cast<FunctionDecl>(GD.getDecl ());
11197
+ // If the original function is defined already, use its definition.
11198
+ StringRef MangledName = CGM.getMangledName (GD);
11199
+ llvm::GlobalValue *Orig = CGM.GetGlobalValue (MangledName);
11200
+ if (Orig && !Orig->isDeclaration ())
11201
+ return false ;
11202
+ const FunctionDecl *NewFD = getDeclareVariantFunction (D);
11203
+ // Emit original function if it does not have declare variant attribute or the
11204
+ // context does not match.
11205
+ if (NewFD == D)
11206
+ return false ;
11207
+ GlobalDecl NewGD = GD.getWithDecl (NewFD);
11208
+ if (tryEmitAlias (CGM, NewGD, GD, Orig, IsForDefinition)) {
11209
+ DeferredVariantFunction.erase (D);
11210
+ return true ;
11211
+ }
11212
+ DeferredVariantFunction.insert (std::make_pair (D, std::make_pair (NewGD, GD)));
11213
+ return true ;
11214
+ }
11215
+
11089
11216
llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction (
11090
11217
const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11091
11218
OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
0 commit comments