aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-09 13:28:42 +0000
commitb1c73532ee8997fe5dfbeb7d223027bdf99758a0 (patch)
tree7d6e51c294ab6719475d660217aa0c0ad0526292 /llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp')
-rw-r--r--llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp105
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();
}