Skip to content

Commit 076f61d

Browse files
authored
Add CFFunctionAnalysisStorePass (#39)
* make instrumentation flexible * add store pass to O3 * remove useless loop * track handled blocks * track handled blocks2
1 parent f41393a commit 076f61d

File tree

6 files changed

+162
-117
lines changed

6 files changed

+162
-117
lines changed

llvm/include/llvm/Analysis/CFFunctionAnalysis.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "llvm/Passes/PassBuilder.h"
1010
#include "llvm/Passes/PassPlugin.h"
1111
#include "llvm/Support/Debug.h"
12+
#include <fstream>
1213

1314
namespace llvm {
1415

@@ -34,6 +35,20 @@ struct CFFunctionAnalysisPrinterPass
3435
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
3536
};
3637

38+
struct CFFunctionAnalysisStorePass
39+
: PassInfoMixin<CFFunctionAnalysisStorePass> {
40+
41+
std::string Filename;
42+
43+
public:
44+
explicit CFFunctionAnalysisStorePass(std::string Filename)
45+
: Filename(std::move(Filename)) {}
46+
47+
explicit CFFunctionAnalysisStorePass() : Filename("called_functions.txt") {}
48+
49+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
50+
};
51+
3752
} // namespace llvm
3853

3954
#endif // LLVM_ANALYSIS_CF_FUNCTION_ANALYSIS_H

llvm/lib/Analysis/CFFunctionAnalysis.cpp

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ using namespace llvm;
77
// Provide a definition for the static object used to identify passes.
88
AnalysisKey CFFunctionAnalysis::Key;
99

10-
CFFunctionAnalysisInfo CFFunctionAnalysis::run(Module &M,
11-
ModuleAnalysisManager &AM) {
12-
10+
CFFunctionAnalysisInfo analyse(Module &M) {
1311
CFFunctionAnalysisInfo CalledFunctions;
1412
for (auto &F : M) {
1513
if (F.isDeclaration()) {
@@ -75,6 +73,27 @@ CFFunctionAnalysisInfo CFFunctionAnalysis::run(Module &M,
7573
return CalledFunctions;
7674
}
7775

76+
CFFunctionAnalysisInfo CFFunctionAnalysis::run(Module &M,
77+
ModuleAnalysisManager &AM) {
78+
79+
CFFunctionAnalysisInfo CalledFunctions;
80+
81+
// check if called functions file exists
82+
std::ifstream file("called_functions.txt");
83+
if (file.good()) {
84+
std::string line;
85+
while (std::getline(file, line)) {
86+
char *cstr = new char[line.length() + 1];
87+
strcpy(cstr, line.c_str());
88+
CalledFunctions.insert(cstr);
89+
}
90+
} else {
91+
CalledFunctions = analyse(M);
92+
}
93+
file.close();
94+
return CalledFunctions;
95+
}
96+
7897
PreservedAnalyses
7998
CFFunctionAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
8099
OS << "Called functions for " << M.getName() << ":\n";
@@ -84,3 +103,25 @@ CFFunctionAnalysisPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
84103
OS << "\n";
85104
return PreservedAnalyses::all();
86105
}
106+
107+
PreservedAnalyses CFFunctionAnalysisStorePass::run(Module &M,
108+
ModuleAnalysisManager &AM) {
109+
CFFunctionAnalysisInfo CalledFunctions = AM.getResult<CFFunctionAnalysis>(M);
110+
111+
// store called functions to called_functions.txt
112+
std::ofstream out;
113+
out.open(Filename, std::ios::app);
114+
115+
if (!out) {
116+
errs() << "Error: cannot open file " << Filename << "\n";
117+
return PreservedAnalyses::none();
118+
}
119+
120+
for (auto &F : CalledFunctions) {
121+
out << F.str() << "\n";
122+
}
123+
124+
out.close();
125+
126+
return PreservedAnalyses::all();
127+
}

llvm/lib/Passes/PassBuilderPipelines.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/ADT/Statistic.h"
1818
#include "llvm/Analysis/AliasAnalysis.h"
1919
#include "llvm/Analysis/BasicAliasAnalysis.h"
20+
#include "llvm/Analysis/CFFunctionAnalysis.h"
2021
#include "llvm/Analysis/CGSCCPassManager.h"
2122
#include "llvm/Analysis/GlobalsModRef.h"
2223
#include "llvm/Analysis/InlineAdvisor.h"
@@ -123,9 +124,9 @@
123124
#include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
124125
#include "llvm/Transforms/Utils/AddDiscriminators.h"
125126
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
127+
#include "llvm/Transforms/Utils/CFFunctionInstrumentation.h"
126128
#include "llvm/Transforms/Utils/CanonicalizeAliases.h"
127129
#include "llvm/Transforms/Utils/CountVisits.h"
128-
#include "llvm/Transforms/Utils/CFFunctionInstrumentation.h"
129130
#include "llvm/Transforms/Utils/InjectTLIMappings.h"
130131
#include "llvm/Transforms/Utils/LibCallsShrinkWrap.h"
131132
#include "llvm/Transforms/Utils/Mem2Reg.h"
@@ -181,9 +182,9 @@ static cl::opt<bool> EnablePostPGOLoopRotation(
181182
"enable-post-pgo-loop-rotation", cl::init(true), cl::Hidden,
182183
cl::desc("Run the loop rotation transformation after PGO instrumentation"));
183184

184-
static cl::opt<bool> EnableGlobalAnalyses(
185-
"enable-global-analyses", cl::init(true), cl::Hidden,
186-
cl::desc("Enable inter-procedural analyses"));
185+
static cl::opt<bool>
186+
EnableGlobalAnalyses("enable-global-analyses", cl::init(true), cl::Hidden,
187+
cl::desc("Enable inter-procedural analyses"));
187188

188189
static cl::opt<bool>
189190
RunPartialInlining("enable-partial-inlining", cl::init(false), cl::Hidden,
@@ -1084,11 +1085,10 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level,
10841085
// and prior to optimizing globals.
10851086
// FIXME: This position in the pipeline hasn't been carefully considered in
10861087
// years, it should be re-analyzed.
1087-
MPM.addPass(IPSCCPPass(
1088-
IPSCCPOptions(/*AllowFuncSpec=*/
1089-
Level != OptimizationLevel::Os &&
1090-
Level != OptimizationLevel::Oz &&
1091-
!isLTOPreLink(Phase))));
1088+
MPM.addPass(IPSCCPPass(IPSCCPOptions(/*AllowFuncSpec=*/
1089+
Level != OptimizationLevel::Os &&
1090+
Level != OptimizationLevel::Oz &&
1091+
!isLTOPreLink(Phase))));
10921092

10931093
// Attach metadata to indirect call sites indicating the set of functions
10941094
// they may target at run-time. This should follow IPSCCP.
@@ -1498,6 +1498,7 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level,
14981498

14991499
ModulePassManager MPM;
15001500

1501+
MPM.addPass(CFFunctionAnalysisStorePass("cffunction-analysis-store.txt"));
15011502
MPM.addPass(CFFunctionInstrumentationPass());
15021503

15031504
// Convert @llvm.global.annotations to !annotation metadata.
@@ -1559,7 +1560,7 @@ PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO,
15591560
ModulePassManager
15601561
PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) {
15611562
if (Level == OptimizationLevel::O0)
1562-
return buildO0DefaultPipeline(Level, /*LTOPreLink*/true);
1563+
return buildO0DefaultPipeline(Level, /*LTOPreLink*/ true);
15631564

15641565
ModulePassManager MPM;
15651566

llvm/lib/Passes/PassRegistry.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ MODULE_ALIAS_ANALYSIS("globals-aa", GlobalsAA())
4242
#ifndef MODULE_PASS
4343
#define MODULE_PASS(NAME, CREATE_PASS)
4444
#endif
45+
MODULE_PASS("store<cffunction-analysis>", CFFunctionAnalysisStorePass())
4546
MODULE_PASS("print<cffunction-analysis>", CFFunctionAnalysisPrinterPass(errs()))
4647
MODULE_PASS("cffunction-instrumentation", CFFunctionInstrumentationPass())
4748
MODULE_PASS("always-inline", AlwaysInlinerPass())

llvm/lib/Transforms/Utils/CFFunctionInstrumentation.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ PreservedAnalyses
1010
CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
1111

1212
CFFunctionAnalysisInfo CalledFunctions = AM.getResult<CFFunctionAnalysis>(M);
13+
LLVM_DEBUG(
14+
for (auto &F
15+
: CalledFunctions) { dbgs() << "Called function: " << F << "\n"; });
1316
int permissions_created = 0;
1417
Value *WritePermission = nullptr;
1518
Value *FileName = nullptr;
@@ -33,10 +36,17 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
3336
StringRef funcFileName = StringRef(fileName);
3437
// for all return instructions, print the return value to a file with the
3538
// name of the function
39+
40+
// store already handled blocks
41+
std::set<BasicBlock *> HandledBlocks;
3642
for (auto &BB : F) {
43+
if (HandledBlocks.count(&BB)) {
44+
continue;
45+
}
3746
// Do NOT reinstrument the inserted blocks
3847
if (BB.getName() == "return" || BB.getName() == "print" ||
3948
BB.getName() == "open") {
49+
HandledBlocks.insert(&BB);
4050
continue;
4151
}
4252
if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator())) {
@@ -113,8 +123,13 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
113123

114124
// place new BBs in the correct order
115125
ReturnBB->moveAfter(PrintBB);
126+
127+
HandledBlocks.insert(AccessBB);
128+
HandledBlocks.insert(PrintBB);
129+
HandledBlocks.insert(ReturnBB);
116130
}
117131
}
132+
HandledBlocks.insert(&BB);
118133
}
119134
}
120135

0 commit comments

Comments
 (0)