Skip to content

Commit f98e746

Browse files
committed
Merging r342152:
------------------------------------------------------------------------ r342152 | erichkeane | 2018-09-13 09:58:24 -0700 (Thu, 13 Sep 2018) | 6 lines [NFC]Refactor MultiVersion Resolver Emission to combine types Previously, both types (plus the future target-clones) of multiversioning had a separate ResolverOption structure and emission function. This patch combines the two, at the expense of a slightly more expensive sorting function. ------------------------------------------------------------------------ llvm-svn: 348681
1 parent c5ae766 commit f98e746

File tree

4 files changed

+108
-93
lines changed

4 files changed

+108
-93
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,6 +1953,39 @@ def Target : InheritableAttr {
19531953
return parse(getFeaturesStr());
19541954
}
19551955

1956+
StringRef getArchitecture() const {
1957+
StringRef Features = getFeaturesStr();
1958+
if (Features == "default") return {};
1959+
1960+
SmallVector<StringRef, 1> AttrFeatures;
1961+
Features.split(AttrFeatures, ",");
1962+
1963+
for (auto &Feature : AttrFeatures) {
1964+
Feature = Feature.trim();
1965+
if (Feature.startswith("arch="))
1966+
return Feature.drop_front(sizeof("arch=") - 1);
1967+
}
1968+
return "";
1969+
}
1970+
1971+
// Gets the list of features as simple string-refs with no +/- or 'no-'.
1972+
// Only adds the items to 'Out' that are additions.
1973+
void getAddedFeatures(llvm::SmallVectorImpl<StringRef> &Out) const {
1974+
StringRef Features = getFeaturesStr();
1975+
if (Features == "default") return;
1976+
1977+
SmallVector<StringRef, 1> AttrFeatures;
1978+
Features.split(AttrFeatures, ",");
1979+
1980+
for (auto &Feature : AttrFeatures) {
1981+
Feature = Feature.trim();
1982+
1983+
if (!Feature.startswith("no-") && !Feature.startswith("arch=") &&
1984+
!Feature.startswith("fpmath=") && !Feature.startswith("tune="))
1985+
Out.push_back(Feature);
1986+
}
1987+
}
1988+
19561989
template<class Compare>
19571990
ParsedTargetAttr parse(Compare cmp) const {
19581991
ParsedTargetAttr Attrs = parse();

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 21 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,91 +2359,53 @@ void CodeGenFunction::EmitSanitizerStatReport(llvm::SanitizerStatKind SSK) {
23592359
CGM.getSanStats().create(IRB, SSK);
23602360
}
23612361

2362-
llvm::Value *CodeGenFunction::FormResolverCondition(
2363-
const TargetMultiVersionResolverOption &RO) {
2364-
llvm::Value *TrueCondition = nullptr;
2365-
if (!RO.ParsedAttribute.Architecture.empty())
2366-
TrueCondition = EmitX86CpuIs(RO.ParsedAttribute.Architecture);
2367-
2368-
if (!RO.ParsedAttribute.Features.empty()) {
2369-
SmallVector<StringRef, 8> FeatureList;
2370-
llvm::for_each(RO.ParsedAttribute.Features,
2371-
[&FeatureList](const std::string &Feature) {
2372-
FeatureList.push_back(StringRef{Feature}.substr(1));
2373-
});
2374-
llvm::Value *FeatureCmp = EmitX86CpuSupports(FeatureList);
2375-
TrueCondition = TrueCondition ? Builder.CreateAnd(TrueCondition, FeatureCmp)
2376-
: FeatureCmp;
2377-
}
2378-
return TrueCondition;
2379-
}
2380-
2381-
void CodeGenFunction::EmitTargetMultiVersionResolver(
2382-
llvm::Function *Resolver,
2383-
ArrayRef<TargetMultiVersionResolverOption> Options) {
2384-
assert((getContext().getTargetInfo().getTriple().getArch() ==
2385-
llvm::Triple::x86 ||
2386-
getContext().getTargetInfo().getTriple().getArch() ==
2387-
llvm::Triple::x86_64) &&
2388-
"Only implemented for x86 targets");
2389-
2390-
// Main function's basic block.
2391-
llvm::BasicBlock *CurBlock = createBasicBlock("entry", Resolver);
2392-
Builder.SetInsertPoint(CurBlock);
2393-
EmitX86CpuInit();
2362+
llvm::Value *
2363+
CodeGenFunction::FormResolverCondition(const MultiVersionResolverOption &RO) {
2364+
llvm::Value *Condition = nullptr;
23942365

2395-
llvm::Function *DefaultFunc = nullptr;
2396-
for (const TargetMultiVersionResolverOption &RO : Options) {
2397-
Builder.SetInsertPoint(CurBlock);
2398-
llvm::Value *TrueCondition = FormResolverCondition(RO);
2366+
if (!RO.Conditions.Architecture.empty())
2367+
Condition = EmitX86CpuIs(RO.Conditions.Architecture);
23992368

2400-
if (!TrueCondition) {
2401-
DefaultFunc = RO.Function;
2402-
} else {
2403-
llvm::BasicBlock *RetBlock = createBasicBlock("ro_ret", Resolver);
2404-
llvm::IRBuilder<> RetBuilder(RetBlock);
2405-
RetBuilder.CreateRet(RO.Function);
2406-
CurBlock = createBasicBlock("ro_else", Resolver);
2407-
Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
2408-
}
2369+
if (!RO.Conditions.Features.empty()) {
2370+
llvm::Value *FeatureCond = EmitX86CpuSupports(RO.Conditions.Features);
2371+
Condition =
2372+
Condition ? Builder.CreateAnd(Condition, FeatureCond) : FeatureCond;
24092373
}
2410-
2411-
assert(DefaultFunc && "No default version?");
2412-
// Emit return from the 'else-ist' block.
2413-
Builder.SetInsertPoint(CurBlock);
2414-
Builder.CreateRet(DefaultFunc);
2374+
return Condition;
24152375
}
24162376

2417-
void CodeGenFunction::EmitCPUDispatchMultiVersionResolver(
2418-
llvm::Function *Resolver,
2419-
ArrayRef<CPUDispatchMultiVersionResolverOption> Options) {
2377+
void CodeGenFunction::EmitMultiVersionResolver(
2378+
llvm::Function *Resolver, ArrayRef<MultiVersionResolverOption> Options) {
24202379
assert((getContext().getTargetInfo().getTriple().getArch() ==
24212380
llvm::Triple::x86 ||
24222381
getContext().getTargetInfo().getTriple().getArch() ==
24232382
llvm::Triple::x86_64) &&
24242383
"Only implemented for x86 targets");
2425-
24262384
// Main function's basic block.
24272385
llvm::BasicBlock *CurBlock = createBasicBlock("resolver_entry", Resolver);
24282386
Builder.SetInsertPoint(CurBlock);
24292387
EmitX86CpuInit();
24302388

2431-
for (const CPUDispatchMultiVersionResolverOption &RO : Options) {
2389+
for (const MultiVersionResolverOption &RO : Options) {
24322390
Builder.SetInsertPoint(CurBlock);
2391+
llvm::Value *Condition = FormResolverCondition(RO);
24332392

2434-
// "generic" case should catch-all.
2435-
if (RO.FeatureMask == 0) {
2393+
// The 'default' or 'generic' case.
2394+
if (!Condition) {
2395+
assert(&RO == Options.end() - 1 &&
2396+
"Default or Generic case must be last");
24362397
Builder.CreateRet(RO.Function);
24372398
return;
24382399
}
2400+
24392401
llvm::BasicBlock *RetBlock = createBasicBlock("resolver_return", Resolver);
24402402
llvm::IRBuilder<> RetBuilder(RetBlock);
24412403
RetBuilder.CreateRet(RO.Function);
24422404
CurBlock = createBasicBlock("resolver_else", Resolver);
2443-
llvm::Value *TrueCondition = EmitX86CpuSupports(RO.FeatureMask);
2444-
Builder.CreateCondBr(TrueCondition, RetBlock, CurBlock);
2405+
Builder.CreateCondBr(Condition, RetBlock, CurBlock);
24452406
}
24462407

2408+
// If no generic/default, emit an unreachable.
24472409
Builder.SetInsertPoint(CurBlock);
24482410
llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
24492411
TrapCall->setDoesNotReturn();

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4247,30 +4247,26 @@ class CodeGenFunction : public CodeGenTypeCache {
42474247

42484248
void EmitSanitizerStatReport(llvm::SanitizerStatKind SSK);
42494249

4250-
struct TargetMultiVersionResolverOption {
4250+
struct MultiVersionResolverOption {
42514251
llvm::Function *Function;
4252-
TargetAttr::ParsedTargetAttr ParsedAttribute;
4253-
unsigned Priority;
4254-
TargetMultiVersionResolverOption(
4255-
const TargetInfo &TargInfo, llvm::Function *F,
4256-
const clang::TargetAttr::ParsedTargetAttr &PT)
4257-
: Function(F), ParsedAttribute(PT), Priority(0u) {
4258-
for (StringRef Feat : PT.Features)
4259-
Priority = std::max(Priority,
4260-
TargInfo.multiVersionSortPriority(Feat.substr(1)));
4261-
4262-
if (!PT.Architecture.empty())
4263-
Priority = std::max(Priority,
4264-
TargInfo.multiVersionSortPriority(PT.Architecture));
4265-
}
4252+
struct Conds {
4253+
StringRef Architecture;
4254+
llvm::SmallVector<StringRef, 8> Features;
42664255

4267-
bool operator>(const TargetMultiVersionResolverOption &Other) const {
4268-
return Priority > Other.Priority;
4269-
}
4256+
Conds(StringRef Arch, ArrayRef<StringRef> Feats)
4257+
: Architecture(Arch), Features(Feats.begin(), Feats.end()) {}
4258+
} Conditions;
4259+
4260+
MultiVersionResolverOption(llvm::Function *F, StringRef Arch,
4261+
ArrayRef<StringRef> Feats)
4262+
: Function(F), Conditions(Arch, Feats) {}
42704263
};
4271-
void EmitTargetMultiVersionResolver(
4272-
llvm::Function *Resolver,
4273-
ArrayRef<TargetMultiVersionResolverOption> Options);
4264+
4265+
// Emits the body of a multiversion function's resolver. Assumes that the
4266+
// options are already sorted in the proper order, with the 'default' option
4267+
// last (if it exists).
4268+
void EmitMultiVersionResolver(llvm::Function *Resolver,
4269+
ArrayRef<MultiVersionResolverOption> Options);
42744270

42754271
struct CPUDispatchMultiVersionResolverOption {
42764272
llvm::Function *Function;
@@ -4306,8 +4302,7 @@ class CodeGenFunction : public CodeGenTypeCache {
43064302
llvm::Value *EmitX86CpuSupports(ArrayRef<StringRef> FeatureStrs);
43074303
llvm::Value *EmitX86CpuSupports(uint32_t Mask);
43084304
llvm::Value *EmitX86CpuInit();
4309-
llvm::Value *
4310-
FormResolverCondition(const TargetMultiVersionResolverOption &RO);
4305+
llvm::Value *FormResolverCondition(const MultiVersionResolverOption &RO);
43114306
};
43124307

43134308
inline DominatingLLVMValue::saved_type

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2399,9 +2399,22 @@ void CodeGenModule::EmitGlobalDefinition(GlobalDecl GD, llvm::GlobalValue *GV) {
23992399
static void ReplaceUsesOfNonProtoTypeWithRealFunction(llvm::GlobalValue *Old,
24002400
llvm::Function *NewFn);
24012401

2402+
static unsigned
2403+
TargetMVPriority(const TargetInfo &TI,
2404+
const CodeGenFunction::MultiVersionResolverOption &RO) {
2405+
unsigned Priority = 0;
2406+
for (StringRef Feat : RO.Conditions.Features)
2407+
Priority = std::max(Priority, TI.multiVersionSortPriority(Feat));
2408+
2409+
if (!RO.Conditions.Architecture.empty())
2410+
Priority = std::max(
2411+
Priority, TI.multiVersionSortPriority(RO.Conditions.Architecture));
2412+
return Priority;
2413+
}
2414+
24022415
void CodeGenModule::emitMultiVersionFunctions() {
24032416
for (GlobalDecl GD : MultiVersionFuncs) {
2404-
SmallVector<CodeGenFunction::TargetMultiVersionResolverOption, 10> Options;
2417+
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
24052418
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
24062419
getContext().forEachMultiversionedFunctionVersion(
24072420
FD, [this, &GD, &Options](const FunctionDecl *CurFD) {
@@ -2422,20 +2435,30 @@ void CodeGenModule::emitMultiVersionFunctions() {
24222435
}
24232436
assert(Func && "This should have just been created");
24242437
}
2425-
Options.emplace_back(getTarget(), cast<llvm::Function>(Func),
2426-
CurFD->getAttr<TargetAttr>()->parse());
2438+
2439+
const auto *TA = CurFD->getAttr<TargetAttr>();
2440+
llvm::SmallVector<StringRef, 8> Feats;
2441+
TA->getAddedFeatures(Feats);
2442+
2443+
Options.emplace_back(cast<llvm::Function>(Func),
2444+
TA->getArchitecture(), Feats);
24272445
});
24282446

24292447
llvm::Function *ResolverFunc = cast<llvm::Function>(
24302448
GetGlobalValue((getMangledName(GD) + ".resolver").str()));
24312449
if (supportsCOMDAT())
24322450
ResolverFunc->setComdat(
24332451
getModule().getOrInsertComdat(ResolverFunc->getName()));
2452+
2453+
const TargetInfo &TI = getTarget();
24342454
std::stable_sort(
24352455
Options.begin(), Options.end(),
2436-
std::greater<CodeGenFunction::TargetMultiVersionResolverOption>());
2456+
[&TI](const CodeGenFunction::MultiVersionResolverOption &LHS,
2457+
const CodeGenFunction::MultiVersionResolverOption &RHS) {
2458+
return TargetMVPriority(TI, LHS) > TargetMVPriority(TI, RHS);
2459+
});
24372460
CodeGenFunction CGF(*this);
2438-
CGF.EmitTargetMultiVersionResolver(ResolverFunc, Options);
2461+
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
24392462
}
24402463
}
24412464

@@ -2455,8 +2478,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
24552478
GetOrCreateLLVMFunction(ResolverName, ResolverType, GlobalDecl{},
24562479
/*ForVTable=*/false));
24572480

2458-
SmallVector<CodeGenFunction::CPUDispatchMultiVersionResolverOption, 10>
2459-
Options;
2481+
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
24602482
const TargetInfo &Target = getTarget();
24612483
for (const IdentifierInfo *II : DD->cpus()) {
24622484
// Get the name of the target function so we can look it up/create it.
@@ -2473,15 +2495,18 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
24732495
Features.begin(), Features.end(), [&Target](StringRef Feat) {
24742496
return !Target.validateCpuSupports(Feat);
24752497
}), Features.end());
2476-
Options.emplace_back(cast<llvm::Function>(Func),
2477-
CodeGenFunction::GetX86CpuSupportsMask(Features));
2498+
Options.emplace_back(cast<llvm::Function>(Func), StringRef{}, Features);
24782499
}
24792500

24802501
llvm::sort(
24812502
Options.begin(), Options.end(),
2482-
std::greater<CodeGenFunction::CPUDispatchMultiVersionResolverOption>());
2503+
[](const CodeGenFunction::MultiVersionResolverOption &LHS,
2504+
const CodeGenFunction::MultiVersionResolverOption &RHS) {
2505+
return CodeGenFunction::GetX86CpuSupportsMask(LHS.Conditions.Features) >
2506+
CodeGenFunction::GetX86CpuSupportsMask(RHS.Conditions.Features);
2507+
});
24832508
CodeGenFunction CGF(*this);
2484-
CGF.EmitCPUDispatchMultiVersionResolver(ResolverFunc, Options);
2509+
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
24852510
}
24862511

24872512
/// If an ifunc for the specified mangled name is not in the module, create and

0 commit comments

Comments
 (0)