Skip to content

Commit ea9e47d

Browse files
Puneeth-A-Rmtrofin
authored andcommitted
ForceFunctionAttrs: support overriding attributes via csv file
Update `ForceFunctionAttrs` pass to optionally take its input from a csv file, for example, function-level optimization attributes. A subsequent patch will enable the pass pipeline to be aware of these attributes, and this pass will be used to test that is the case. Eventually, the annotations would be driven by an agent, e.g. a machine learning-based policy. This patch is a part of GSoC 2023, more details can be found [[ https://summerofcode.withgoogle.com/programs/2023/projects/T8rB84Sr | here ]] Reviewed By: mtrofin, aeubanks Differential Revision: https://reviews.llvm.org/D155617
1 parent 11c07ce commit ea9e47d

File tree

4 files changed

+98
-8
lines changed

4 files changed

+98
-8
lines changed

llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "llvm/IR/Module.h"
1212
#include "llvm/Support/CommandLine.h"
1313
#include "llvm/Support/Debug.h"
14+
#include "llvm/Support/LineIterator.h"
15+
#include "llvm/Support/MemoryBuffer.h"
1416
#include "llvm/Support/raw_ostream.h"
1517
using namespace llvm;
1618

@@ -36,6 +38,12 @@ static cl::list<std::string> ForceRemoveAttributes(
3638
"module. This "
3739
"option can be specified multiple times."));
3840

41+
static cl::opt<std::string> CSVFilePath(
42+
"forceattrs-csv-path", cl::Hidden,
43+
cl::desc(
44+
"Path to CSV file containing lines of function names and attributes to "
45+
"add to them in the form of `f1,attr1` or `f2,attr2=str`."));
46+
3947
/// If F has any forced attributes given on the command line, add them.
4048
/// If F has any forced remove attributes given on the command line, remove
4149
/// them. When both force and force-remove are given to a function, the latter
@@ -80,12 +88,52 @@ static bool hasForceAttributes() {
8088

8189
PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,
8290
ModuleAnalysisManager &) {
83-
if (!hasForceAttributes())
84-
return PreservedAnalyses::all();
85-
86-
for (Function &F : M.functions())
87-
forceAttributes(F);
88-
89-
// Just conservatively invalidate analyses, this isn't likely to be important.
90-
return PreservedAnalyses::none();
91+
bool Changed = false;
92+
if (!CSVFilePath.empty()) {
93+
auto BufferOrError = MemoryBuffer::getFileOrSTDIN(CSVFilePath);
94+
if (!BufferOrError)
95+
report_fatal_error("Cannot open CSV file.");
96+
StringRef Buffer = BufferOrError.get()->getBuffer();
97+
auto MemoryBuffer = MemoryBuffer::getMemBuffer(Buffer);
98+
line_iterator It(*MemoryBuffer);
99+
for (; !It.is_at_end(); ++It) {
100+
auto SplitPair = It->split(',');
101+
if (SplitPair.second.empty())
102+
continue;
103+
Function *Func = M.getFunction(SplitPair.first);
104+
if (Func) {
105+
if (Func->isDeclaration())
106+
continue;
107+
auto SecondSplitPair = SplitPair.second.split('=');
108+
if (!SecondSplitPair.second.empty()) {
109+
Func->addFnAttr(SecondSplitPair.first, SecondSplitPair.second);
110+
Changed = true;
111+
} else {
112+
auto AttrKind = Attribute::getAttrKindFromName(SplitPair.second);
113+
if (AttrKind != Attribute::None &&
114+
Attribute::canUseAsFnAttr(AttrKind)) {
115+
// TODO: There could be string attributes without a value, we should
116+
// support those, too.
117+
Func->addFnAttr(AttrKind);
118+
Changed = true;
119+
} else
120+
errs() << "Cannot add " << SplitPair.second
121+
<< " as an attribute name.\n";
122+
}
123+
} else {
124+
errs() << "Function in CSV file at line " << It.line_number()
125+
<< " does not exist.\n";
126+
// TODO: `report_fatal_error at end of pass for missing functions.
127+
continue;
128+
}
129+
}
130+
}
131+
if (hasForceAttributes()) {
132+
for (Function &F : M.functions())
133+
forceAttributes(F);
134+
Changed = true;
135+
}
136+
// Just conservatively invalidate analyses if we've made any changes, this
137+
// isn't likely to be important.
138+
return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
91139
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
unknown_function,hot=cold
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
first_function,opt-level=O1
2+
second_function,cold
3+
third_function,opt-level=O1
4+
fourth_function,opt-level=O2
5+
fifth_function,foo=bar
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; RUN: opt -passes='forceattrs' -forceattrs-csv-path="%S/FunctionAnnotation.csv" -S < %s | FileCheck %s
2+
; RUN: opt -passes='forceattrs' -forceattrs-csv-path="%S/DoesNotExist.csv" -S < %s 2>&1 | FileCheck %s --check-prefix=NonexistentFunc
3+
define void @first_function() {
4+
; CHECK: @first_function() #0
5+
ret void
6+
}
7+
8+
define void @second_function() {
9+
; CHECK: @second_function() #1
10+
ret void
11+
}
12+
13+
define void @third_function() {
14+
; CHECK: @third_function() #0
15+
ret void
16+
}
17+
18+
define void @fourth_function() {
19+
; CHECK: @fourth_function() #2
20+
ret void
21+
}
22+
23+
define void @fifth_function() {
24+
; CHECK: @fifth_function() #3
25+
ret void
26+
}
27+
28+
; CHECK-LABEL: attributes #0 = { "opt-level"="O1" }
29+
30+
; CHECK-LABEL: attributes #1 = { cold }
31+
32+
; CHECK-LABEL: attributes #2 = { "opt-level"="O2" }
33+
34+
; CHECK-LABEL: attributes #3 = { "foo"="bar" }
35+
36+
; NonexistentFunc: Function in CSV file at line 1 does not exist.

0 commit comments

Comments
 (0)