diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-09 13:28:42 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-09 13:28:42 +0000 |
| commit | b1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch) | |
| tree | 7d6e51c294ab6719475d660217aa0c0ad0526292 /llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp | |
| parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) | |
Diffstat (limited to 'llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp')
| -rw-r--r-- | llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp | 105 |
1 files changed, 82 insertions, 23 deletions
diff --git a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp index 74931e1032d1..9cf4e448c9b6 100644 --- a/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp @@ -11,38 +11,57 @@ #include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; #define DEBUG_TYPE "forceattrs" -static cl::list<std::string> - ForceAttributes("force-attribute", cl::Hidden, - cl::desc("Add an attribute to a function. This should be a " - "pair of 'function-name:attribute-name', for " - "example -force-attribute=foo:noinline. This " - "option can be specified multiple times.")); +static cl::list<std::string> ForceAttributes( + "force-attribute", cl::Hidden, + cl::desc( + "Add an attribute to a function. This can be a " + "pair of 'function-name:attribute-name', to apply an attribute to a " + "specific function. For " + "example -force-attribute=foo:noinline. Specifying only an attribute " + "will apply the attribute to every function in the module. This " + "option can be specified multiple times.")); static cl::list<std::string> ForceRemoveAttributes( "force-remove-attribute", cl::Hidden, - cl::desc("Remove an attribute from a function. This should be a " - "pair of 'function-name:attribute-name', for " - "example -force-remove-attribute=foo:noinline. This " + cl::desc("Remove an attribute from a function. This can be a " + "pair of 'function-name:attribute-name' to remove an attribute " + "from a specific function. For " + "example -force-remove-attribute=foo:noinline. Specifying only an " + "attribute will remove the attribute from all functions in the " + "module. This " "option can be specified multiple times.")); +static cl::opt<std::string> CSVFilePath( + "forceattrs-csv-path", cl::Hidden, + cl::desc( + "Path to CSV file containing lines of function names and attributes to " + "add to them in the form of `f1,attr1` or `f2,attr2=str`.")); + /// If F has any forced attributes given on the command line, add them. /// If F has any forced remove attributes given on the command line, remove /// them. When both force and force-remove are given to a function, the latter /// takes precedence. static void forceAttributes(Function &F) { auto ParseFunctionAndAttr = [&](StringRef S) { - auto Kind = Attribute::None; - auto KV = StringRef(S).split(':'); - if (KV.first != F.getName()) - return Kind; - Kind = Attribute::getAttrKindFromName(KV.second); + StringRef AttributeText; + if (S.contains(':')) { + auto KV = StringRef(S).split(':'); + if (KV.first != F.getName()) + return Attribute::None; + AttributeText = KV.second; + } else { + AttributeText = S; + } + auto Kind = Attribute::getAttrKindFromName(AttributeText); if (Kind == Attribute::None || !Attribute::canUseAsFnAttr(Kind)) { - LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second + LLVM_DEBUG(dbgs() << "ForcedAttribute: " << AttributeText << " unknown or not a function attribute!\n"); } return Kind; @@ -69,12 +88,52 @@ static bool hasForceAttributes() { PreservedAnalyses ForceFunctionAttrsPass::run(Module &M, ModuleAnalysisManager &) { - if (!hasForceAttributes()) - return PreservedAnalyses::all(); - - for (Function &F : M.functions()) - forceAttributes(F); - - // Just conservatively invalidate analyses, this isn't likely to be important. - return PreservedAnalyses::none(); + bool Changed = false; + if (!CSVFilePath.empty()) { + auto BufferOrError = MemoryBuffer::getFileOrSTDIN(CSVFilePath); + if (!BufferOrError) + report_fatal_error("Cannot open CSV file."); + StringRef Buffer = BufferOrError.get()->getBuffer(); + auto MemoryBuffer = MemoryBuffer::getMemBuffer(Buffer); + line_iterator It(*MemoryBuffer); + for (; !It.is_at_end(); ++It) { + auto SplitPair = It->split(','); + if (SplitPair.second.empty()) + continue; + Function *Func = M.getFunction(SplitPair.first); + if (Func) { + if (Func->isDeclaration()) + continue; + auto SecondSplitPair = SplitPair.second.split('='); + if (!SecondSplitPair.second.empty()) { + Func->addFnAttr(SecondSplitPair.first, SecondSplitPair.second); + Changed = true; + } else { + auto AttrKind = Attribute::getAttrKindFromName(SplitPair.second); + if (AttrKind != Attribute::None && + Attribute::canUseAsFnAttr(AttrKind)) { + // TODO: There could be string attributes without a value, we should + // support those, too. + Func->addFnAttr(AttrKind); + Changed = true; + } else + errs() << "Cannot add " << SplitPair.second + << " as an attribute name.\n"; + } + } else { + errs() << "Function in CSV file at line " << It.line_number() + << " does not exist.\n"; + // TODO: `report_fatal_error at end of pass for missing functions. + continue; + } + } + } + if (hasForceAttributes()) { + for (Function &F : M.functions()) + forceAttributes(F); + Changed = true; + } + // Just conservatively invalidate analyses if we've made any changes, this + // isn't likely to be important. + return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); } |
