From 93e58667ee1030f36affff0cc5c43e404be19523 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Mon, 12 Feb 2018 17:01:41 +0000 Subject: Make attribute-target on a Definition-after-use update the LLVM attributes As reported here: https://bugs.llvm.org/show_bug.cgi?id=36301 The issue is that the 'use' causes the plain declaration to emit the attributes to LLVM-IR. However, if the definition added it later, these would silently disappear. This commit extracts that logic to its own function in CodeGenModule, and has the attribute-applications done during 'definition' update the attributes properly. Differential Revision: https://reviews.llvm.org/D43095 llvm-svn: 324907 --- clang/lib/CodeGen/CodeGenModule.cpp | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 7a93123a549b..33cf0bc9571e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1248,6 +1248,52 @@ void CodeGenModule::setAliasAttributes(const Decl *D, GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); } +bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D, + llvm::AttrBuilder &Attrs) { + // Add target-cpu and target-features attributes to functions. If + // we have a decl for the function and it has a target attribute then + // parse that and add it to the feature set. + StringRef TargetCPU = getTarget().getTargetOpts().CPU; + std::vector Features; + const auto *FD = dyn_cast_or_null(D); + FD = FD ? FD->getMostRecentDecl() : FD; + const auto *TD = FD ? FD->getAttr() : nullptr; + bool AddedAttr = false; + if (TD) { + llvm::StringMap FeatureMap; + getFunctionFeatureMap(FeatureMap, FD); + + // Produce the canonical string for this set of features. + for (const llvm::StringMap::value_type &Entry : FeatureMap) + Features.push_back((Entry.getValue() ? "+" : "-") + Entry.getKey().str()); + + // Now add the target-cpu and target-features to the function. + // While we populated the feature map above, we still need to + // get and parse the target attribute so we can get the cpu for + // the function. + TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); + if (ParsedAttr.Architecture != "" && + getTarget().isValidCPUName(ParsedAttr.Architecture)) + TargetCPU = ParsedAttr.Architecture; + } else { + // Otherwise just add the existing target cpu and target features to the + // function. + Features = getTarget().getTargetOpts().Features; + } + + if (TargetCPU != "") { + Attrs.addAttribute("target-cpu", TargetCPU); + AddedAttr = true; + } + if (!Features.empty()) { + std::sort(Features.begin(), Features.end()); + Attrs.addAttribute("target-features", llvm::join(Features, ",")); + AddedAttr = true; + } + + return AddedAttr; +} + void CodeGenModule::setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO) { SetCommonAttributes(D, GO); @@ -1266,6 +1312,16 @@ void CodeGenModule::setNonAliasAttributes(const Decl *D, if (auto *SA = D->getAttr()) if (!D->getAttr()) F->addFnAttr("implicit-section-name", SA->getName()); + + llvm::AttrBuilder Attrs; + if (GetCPUAndFeaturesAttributes(D, Attrs)) { + // We know that GetCPUAndFeaturesAttributes will always have the + // newest set, since it has the newest possible FunctionDecl, so the + // new ones should replace the old. + F->removeFnAttr("target-cpu"); + F->removeFnAttr("target-features"); + F->addAttributes(llvm::AttributeList::FunctionIndex, Attrs); + } } if (const SectionAttr *SA = D->getAttr()) -- cgit v1.2.3