[PATCH] D51650: Implement target_clones multiversioning
Richard Smith - zygoloid via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 10 11:14:41 PDT 2018
rsmith added inline comments.
================
Comment at: include/clang/Basic/Attr.td:2031-2042
+ mutable unsigned ActiveArgIndex = 0;
+ void AdvanceActiveArgIndex() const {
+ ++ActiveArgIndex;
+ while(ActiveArgIndex < featuresStrs_size()) {
+ if (std::find(featuresStrs_begin(),
+ featuresStrs_begin() + ActiveArgIndex,
+ *(featuresStrs_begin() + ActiveArgIndex))
----------------
Sorry, I don't think it's acceptable from a design perspective to have mutable state in an `Attr` object, even if you can ensure that only one client of the `Attr` will be using the state at a time. CodeGen is going to need to track its own index into the attribute's list of clones.
================
Comment at: include/clang/Basic/AttrDocs.td:1619-1621
+Note that unlike the ``target`` syntax, every option listed creates a new
+version, disregarding whether it is split on a comma inside or outside a string.
+The following will emit 4 versions of the function.
----------------
Can we warn on attributes that contain multiple strings where one or more such strings contains a comma? That seems like it would always be user error.
I think I'd then prefer to document this as: "The versions can either be listed as a comma-separated sequence of string literals or as a single string literal containing a comma-separated list of versions. For compatibility with GCC, the two formats can be mixed. For example, the following will emit 4 versions of the function:"
================
Comment at: lib/CodeGen/CodeGenModule.cpp:961-970
if (const auto *FD = dyn_cast<FunctionDecl>(ND))
if (FD->isMultiVersion() && !OmitMultiVersionMangling) {
if (FD->isCPUDispatchMultiVersion() || FD->isCPUSpecificMultiVersion())
AppendCPUSpecificCPUDispatchMangling(
CGM, FD->getAttr<CPUSpecificAttr>(), Out);
+ else if (FD->isTargetClonesMultiVersion())
+ AppendTargetClonesMangling(CGM, FD->getAttr<TargetClonesAttr>(), Out);
----------------
This chain of `if`s and similar things elsewhere make me think we're missing an abstraction. Perhaps `FunctionDecl` should have a `getMultiVersionAttr()` and/or `getMultiVersionKind()` functions?
================
Comment at: lib/CodeGen/CodeGenModule.cpp:1043
+
+ std::pair<GlobalDecl, unsigned> SpecCanonicalGD{CanonicalGD, VersionID};
----------------
This target index should be part of the `GlobalDecl`, not tracked alongside it, because it identifies which global we're talking about.
================
Comment at: lib/Sema/SemaDecl.cpp:9800-9807
// Mixing Multiversioning types is prohibited.
- if ((NewTA && NewCPUDisp) || (NewTA && NewCPUSpec) ||
- (NewCPUDisp && NewCPUSpec)) {
+ if ((static_cast<bool>(NewTA) + static_cast<bool>(NewCPUDisp) +
+ static_cast<bool>(NewCPUSpec) + static_cast<bool>(NewTargetClones)) >
+ 1) {
S.Diag(NewFD->getLocation(), diag::err_multiversion_types_mixed);
NewFD->setInvalidDecl();
return true;
----------------
We should also disallow multiple `TargetClonesAttr`s on the same declaration. GCC allows this and then ignores all but the last such attribute; we can do better.
================
Comment at: lib/Sema/SemaDecl.cpp:9811-9812
// Main isn't allowed to become a multiversion function, however it IS
// permitted to have 'main' be marked with the 'target' optimization hint.
if (NewFD->isMain()) {
----------------
Why can't `main` be multiversioned? That seems like an arbitrary restriction.
================
Comment at: lib/Sema/SemaDecl.cpp:9839
- if (OldFD->isMultiVersion() && MVType == MultiVersioning::None) {
+ // MultiVersioned redeclarations aren't allowed to omit the attribute except
+ // for target_clones.
----------------
I would expect the plain English term to not have interior capitalization.
================
Comment at: lib/Sema/SemaDeclAttr.cpp:3011
+bool Sema::checkTargetClonesAttr(SourceLocation LiteralLoc, StringRef Str,
+ bool &HasDefault,
----------------
Should be something like `checkTargetClonesAttrStr` to indicate that this is checking one specific string, not the entire attribute.
================
Comment at: lib/Sema/SemaDeclAttr.cpp:3018-3029
+ // Warn on empty at the beginning of a string.
+ if (Str.size() == 0 || Str[0] == ',')
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << None << "" << TargetClones;
+
+ while (Str.size() != 0) {
+ // Remove the comma we found last time through.
----------------
When looping through comma-delimited strings, it's easier to use `StringRef::split`:
```
std::pair<StringRef, StringRef> Parts = {{}, Str};
while (!Parts.second.empty()) {
Parts = Parts.second.split(',');
StringRef Cur = Parts.first.trim();
// ...
}
```
================
Comment at: lib/Sema/SemaDeclAttr.cpp:3035-3043
+ return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
+ << Unsupported << Architecture
+ << Cur.drop_front(sizeof("arch=") - 1) << TargetClones;
+ } else if (Cur == "default") {
+ HasDefault = true;
+ continue;
+ } else if (!Context.getTargetInfo().isValidFeatureName(Cur))
----------------
Rather than just repeating the problematic portion of the string textually in the diagnostic, pass the `StringLiteral` into here and use `StringLiteral::getLocationOfByte` to highlight the problematic source range within the string.
================
Comment at: lib/Sema/SemaDeclAttr.cpp:3068-3071
+ if (!HasDefault) {
+ S.Diag(AL.getLoc(), diag::err_target_clone_must_have_default);
+ return;
+ }
----------------
Do we need any other validation here? What if there are duplicate versions?
================
Comment at: test/CodeGen/attr-cpuspecific.c:14-15
-__attribute__((cpu_specific(ivybridge)))
-void NotCalled(void){}
+__attribute__((cpu_specific(ivybridge))) inline void InlineSingleVersion(void) {}
+// CHECK: define available_externally void @InlineSingleVersion.S() #[[S:[0-9]+]]
+
----------------
Should this really have external linkage? These `.` suffixes are reserved for vendor-specific manglings that typically should only be used for symbols with internal linkage.
If you really want to give these symbols external linkage, I think they should at least be put in a COMDAT keyed off the primary symbol so that we don't get a mishmash of different suffix combinations from different compilers.
https://reviews.llvm.org/D51650
More information about the cfe-commits
mailing list