1 | //===------ DumpFunctionPass.cpp --------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Write a function to a file. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "polly/Support/DumpFunctionPass.h" |
14 | #include "llvm/IR/Module.h" |
15 | #include "llvm/Pass.h" |
16 | #include "llvm/Support/Debug.h" |
17 | #include "llvm/Support/FileSystem.h" |
18 | #include "llvm/Support/Path.h" |
19 | #include "llvm/Support/ToolOutputFile.h" |
20 | #include "llvm/Transforms/IPO/GlobalDCE.h" |
21 | #include "llvm/Transforms/IPO/StripDeadPrototypes.h" |
22 | #include "llvm/Transforms/Utils/Cloning.h" |
23 | |
24 | #define DEBUG_TYPE "polly-dump-func" |
25 | |
26 | using namespace llvm; |
27 | using namespace polly; |
28 | |
29 | namespace { |
30 | |
31 | static void runDumpFunction(llvm::Function &F, StringRef Suffix) { |
32 | StringRef FName = F.getName(); |
33 | Module *M = F.getParent(); |
34 | |
35 | StringRef ModuleName = M->getName(); |
36 | StringRef Stem = sys::path::stem(path: ModuleName); |
37 | std::string Dumpfile = (Twine(Stem) + "-" + FName + Suffix + ".ll" ).str(); |
38 | LLVM_DEBUG(dbgs() << "Dumping function '" << FName << "' to '" << Dumpfile |
39 | << "'...\n" ); |
40 | |
41 | ValueToValueMapTy VMap; |
42 | auto ShouldCloneDefinition = [&F](const GlobalValue *GV) -> bool { |
43 | return GV == &F; |
44 | }; |
45 | std::unique_ptr<Module> CM = CloneModule(M: *M, VMap, ShouldCloneDefinition); |
46 | Function *NewF = cast<Function>(Val: VMap.lookup(Val: &F)); |
47 | assert(NewF && "Expected selected function to be cloned" ); |
48 | |
49 | LLVM_DEBUG(dbgs() << "Global DCE...\n" ); |
50 | |
51 | // Stop F itself from being pruned |
52 | GlobalValue::LinkageTypes OrigLinkage = NewF->getLinkage(); |
53 | NewF->setLinkage(GlobalValue::ExternalLinkage); |
54 | |
55 | { |
56 | ModuleAnalysisManager MAM; |
57 | ModulePassManager MPM; |
58 | |
59 | PassInstrumentationCallbacks PIC; |
60 | MAM.registerPass(PassBuilder: [&] { return PassInstrumentationAnalysis(&PIC); }); |
61 | |
62 | MPM.addPass(Pass: GlobalDCEPass()); |
63 | MPM.addPass(Pass: StripDeadPrototypesPass()); |
64 | MPM.run(IR&: *CM, AM&: MAM); |
65 | } |
66 | |
67 | // Restore old linkage |
68 | NewF->setLinkage(OrigLinkage); |
69 | |
70 | LLVM_DEBUG(dbgs() << "Write to file '" << Dumpfile << "'...\n" ); |
71 | |
72 | std::unique_ptr<ToolOutputFile> Out; |
73 | std::error_code EC; |
74 | Out.reset(p: new ToolOutputFile(Dumpfile, EC, sys::fs::OF_None)); |
75 | if (EC) { |
76 | errs() << EC.message() << '\n'; |
77 | return; |
78 | } |
79 | |
80 | CM->print(OS&: Out->os(), AAW: nullptr); |
81 | Out->keep(); |
82 | LLVM_DEBUG(dbgs() << "Dump file " << Dumpfile << " written successfully\n" ); |
83 | } |
84 | |
85 | class DumpFunctionWrapperPass final : public FunctionPass { |
86 | private: |
87 | DumpFunctionWrapperPass(const DumpFunctionWrapperPass &) = delete; |
88 | const DumpFunctionWrapperPass & |
89 | operator=(const DumpFunctionWrapperPass &) = delete; |
90 | |
91 | std::string Suffix; |
92 | |
93 | public: |
94 | static char ID; |
95 | |
96 | explicit DumpFunctionWrapperPass() : FunctionPass(ID), Suffix("-dump" ) {} |
97 | |
98 | explicit DumpFunctionWrapperPass(std::string Suffix) |
99 | : FunctionPass(ID), Suffix(std::move(Suffix)) {} |
100 | |
101 | /// @name FunctionPass interface |
102 | //@{ |
103 | void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { |
104 | AU.setPreservesAll(); |
105 | } |
106 | |
107 | bool runOnFunction(llvm::Function &F) override { |
108 | runDumpFunction(F, Suffix); |
109 | return false; |
110 | } |
111 | //@} |
112 | }; |
113 | |
114 | char DumpFunctionWrapperPass::ID; |
115 | } // namespace |
116 | |
117 | FunctionPass *polly::createDumpFunctionWrapperPass(std::string Suffix) { |
118 | return new DumpFunctionWrapperPass(std::move(Suffix)); |
119 | } |
120 | |
121 | llvm::PreservedAnalyses DumpFunctionPass::run(Function &F, |
122 | FunctionAnalysisManager &AM) { |
123 | runDumpFunction(F, Suffix); |
124 | return PreservedAnalyses::all(); |
125 | } |
126 | |
127 | INITIALIZE_PASS_BEGIN(DumpFunctionWrapperPass, "polly-dump-function" , |
128 | "Polly - Dump Function" , false, false) |
129 | INITIALIZE_PASS_END(DumpFunctionWrapperPass, "polly-dump-function" , |
130 | "Polly - Dump Function" , false, false) |
131 | |