diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 05703df2129f61..a98ea0cbbef8ac 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -2420,11 +2420,11 @@ command line. The current set of options correspond to the existing "subtarget features" for the target with or without a "-mno-" in front corresponding to the absence -of the feature, as well as ``arch="CPU"`` which will change the default "CPU" -for the function. +of the feature, as well as ``arch="CPU"`` and ``cpu="CPU"`` which will change +the default processor for the function. -For X86, the attribute also allows ``tune="CPU"`` to optimize the generated -code for the given CPU without changing the available instructions. +For X86 and PowerPC, the attribute also allows ``tune="CPU"`` to optimize the +generated code for the given CPU without changing the available instructions. For AArch64, ``arch="Arch"`` will set the architecture, similar to the -march command line options. ``cpu="CPU"`` can be used to select a specific cpu, diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 6cd5d618a4acaa..474f4173eb5257 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -560,11 +560,12 @@ ParsedTargetAttr TargetInfo::parseTargetAttr(StringRef Features) const { } // While we're here iterating check for a different target cpu. - if (Feature.startswith("arch=")) { + if (Feature.startswith("arch=") || Feature.startswith("cpu=")) { + auto [Key, CPU] = Feature.split("="); if (!Ret.CPU.empty()) - Ret.Duplicate = "arch="; + Ret.Duplicate = StringRef(Key.data(), Key.size() + 1); else - Ret.CPU = Feature.split("=").second.trim(); + Ret.CPU = CPU.trim(); } else if (Feature.startswith("tune=")) { if (!Ret.Tune.empty()) Ret.Duplicate = "tune="; diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index eec3cd558435e2..ddec93ab79f2d7 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -1695,6 +1695,46 @@ ArrayRef X86TargetInfo::getGCCAddlRegNames() const { return llvm::ArrayRef(AddlRegNames); } +ParsedTargetAttr X86TargetInfo::parseTargetAttr(StringRef Features) const { + ParsedTargetAttr Ret; + if (Features == "default") + return Ret; + SmallVector AttrFeatures; + Features.split(AttrFeatures, ","); + + for (auto &Feature : AttrFeatures) { + Feature = Feature.trim(); + + // TODO: Support the fpmath option. It will require checking + // overall feature validity for the function with the rest of the + // attributes on the function. + if (Feature.startswith("fpmath=")) + continue; + + if (Feature.startswith("branch-protection=")) { + Ret.BranchProtection = Feature.split('=').second.trim(); + continue; + } + + if (Feature.startswith("arch=")) { + auto [Key, CPU] = Feature.split("="); + if (!Ret.CPU.empty()) + Ret.Duplicate = StringRef(Key.data(), Key.size() + 1); + else + Ret.CPU = CPU.trim(); + } else if (Feature.startswith("tune=")) { + if (!Ret.Tune.empty()) + Ret.Duplicate = "tune="; + else + Ret.Tune = Feature.split("=").second.trim(); + } else if (Feature.startswith("no-")) + Ret.Features.push_back("-" + Feature.split("-").second.str()); + else + Ret.Features.push_back("+" + Feature.str()); + } + return Ret; +} + ArrayRef X86_32TargetInfo::getTargetBuiltins() const { return llvm::ArrayRef(BuiltinInfoX86, clang::X86::LastX86CommonBuiltin - Builtin::FirstTSBuiltin + 1); diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 99a64501d263ce..a338eb2360c024 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -423,6 +423,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { return getPointerWidthV(AddrSpace); } + ParsedTargetAttr parseTargetAttr(StringRef Features) const override; }; // X86-32 generic target diff --git a/clang/test/Sema/attr-target.c b/clang/test/Sema/attr-target.c index 5328f056507a71..c3cf73f57fe183 100644 --- a/clang/test/Sema/attr-target.c +++ b/clang/test/Sema/attr-target.c @@ -76,10 +76,14 @@ int __attribute__((target("fpmath=387"))) walrus(void) { return 4; } int __attribute__((target("float128,arch=hiss"))) meow(void) { return 4; } // no warning, same as saying 'nothing'. int __attribute__((target("arch="))) turtle(void) { return 4; } +// no warning, same as saying 'nothing'. +int __attribute__((target("cpu="))) equus(void) { return 4; } //expected-warning@+1 {{unknown CPU 'hiss' in the 'target' attribute string; 'target' attribute ignored}} int __attribute__((target("arch=hiss,arch=woof"))) pine_tree(void) { return 4; } //expected-warning@+1 {{duplicate 'arch=' in the 'target' attribute string; 'target' attribute ignored}} int __attribute__((target("arch=pwr9,arch=pwr10"))) oak_tree(void) { return 4; } +//expected-warning@+1 {{duplicate 'cpu=' in the 'target' attribute string; 'target' attribute ignored}} +int __attribute__((target("arch=pwr8,cpu=pwr9"))) cypress_tree(void) { return 4; } //expected-warning@+1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}} int __attribute__((target("branch-protection=none"))) birch_tree(void) { return 5; } //expected-warning@+1 {{unknown tune CPU 'hiss' in the 'target' attribute string; 'target' attribute ignored}}