19cfab5e2SMichael Kruse //===------ DumpFunctionPass.cpp --------------------------------*- C++ -*-===//
29cfab5e2SMichael Kruse //
39cfab5e2SMichael Kruse // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49cfab5e2SMichael Kruse // See https://llvm.org/LICENSE.txt for license information.
59cfab5e2SMichael Kruse // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69cfab5e2SMichael Kruse //
79cfab5e2SMichael Kruse //===----------------------------------------------------------------------===//
89cfab5e2SMichael Kruse //
99cfab5e2SMichael Kruse // Write a function to a file.
109cfab5e2SMichael Kruse //
119cfab5e2SMichael Kruse //===----------------------------------------------------------------------===//
129cfab5e2SMichael Kruse
139cfab5e2SMichael Kruse #include "polly/Support/DumpFunctionPass.h"
149cfab5e2SMichael Kruse #include "llvm/IR/Module.h"
15*36c6632eSNikita Popov #include "llvm/IR/PassInstrumentation.h"
169cfab5e2SMichael Kruse #include "llvm/Pass.h"
179cfab5e2SMichael Kruse #include "llvm/Support/Debug.h"
189cfab5e2SMichael Kruse #include "llvm/Support/FileSystem.h"
199cfab5e2SMichael Kruse #include "llvm/Support/Path.h"
209cfab5e2SMichael Kruse #include "llvm/Support/ToolOutputFile.h"
219cfab5e2SMichael Kruse #include "llvm/Transforms/IPO/GlobalDCE.h"
229cfab5e2SMichael Kruse #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
239cfab5e2SMichael Kruse #include "llvm/Transforms/Utils/Cloning.h"
249cfab5e2SMichael Kruse
259cfab5e2SMichael Kruse #define DEBUG_TYPE "polly-dump-func"
269cfab5e2SMichael Kruse
279cfab5e2SMichael Kruse using namespace llvm;
289cfab5e2SMichael Kruse using namespace polly;
299cfab5e2SMichael Kruse
309cfab5e2SMichael Kruse namespace {
319cfab5e2SMichael Kruse
runDumpFunction(llvm::Function & F,StringRef Suffix)329cfab5e2SMichael Kruse static void runDumpFunction(llvm::Function &F, StringRef Suffix) {
339cfab5e2SMichael Kruse StringRef FName = F.getName();
349cfab5e2SMichael Kruse Module *M = F.getParent();
359cfab5e2SMichael Kruse
369cfab5e2SMichael Kruse StringRef ModuleName = M->getName();
379cfab5e2SMichael Kruse StringRef Stem = sys::path::stem(ModuleName);
389cfab5e2SMichael Kruse std::string Dumpfile = (Twine(Stem) + "-" + FName + Suffix + ".ll").str();
399cfab5e2SMichael Kruse LLVM_DEBUG(dbgs() << "Dumping function '" << FName << "' to '" << Dumpfile
409cfab5e2SMichael Kruse << "'...\n");
419cfab5e2SMichael Kruse
429cfab5e2SMichael Kruse ValueToValueMapTy VMap;
439cfab5e2SMichael Kruse auto ShouldCloneDefinition = [&F](const GlobalValue *GV) -> bool {
449cfab5e2SMichael Kruse return GV == &F;
459cfab5e2SMichael Kruse };
469cfab5e2SMichael Kruse std::unique_ptr<Module> CM = CloneModule(*M, VMap, ShouldCloneDefinition);
47e4f3f2c0SMichael Kruse Function *NewF = cast<Function>(VMap.lookup(&F));
48e4f3f2c0SMichael Kruse assert(NewF && "Expected selected function to be cloned");
499cfab5e2SMichael Kruse
509cfab5e2SMichael Kruse LLVM_DEBUG(dbgs() << "Global DCE...\n");
519cfab5e2SMichael Kruse
52e4f3f2c0SMichael Kruse // Stop F itself from being pruned
53e4f3f2c0SMichael Kruse GlobalValue::LinkageTypes OrigLinkage = NewF->getLinkage();
54e4f3f2c0SMichael Kruse NewF->setLinkage(GlobalValue::ExternalLinkage);
55e4f3f2c0SMichael Kruse
569cfab5e2SMichael Kruse {
579cfab5e2SMichael Kruse ModuleAnalysisManager MAM;
589cfab5e2SMichael Kruse ModulePassManager MPM;
599cfab5e2SMichael Kruse
609cfab5e2SMichael Kruse PassInstrumentationCallbacks PIC;
619cfab5e2SMichael Kruse MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
629cfab5e2SMichael Kruse
639cfab5e2SMichael Kruse MPM.addPass(GlobalDCEPass());
649cfab5e2SMichael Kruse MPM.addPass(StripDeadPrototypesPass());
659cfab5e2SMichael Kruse MPM.run(*CM, MAM);
669cfab5e2SMichael Kruse }
679cfab5e2SMichael Kruse
68e4f3f2c0SMichael Kruse // Restore old linkage
69e4f3f2c0SMichael Kruse NewF->setLinkage(OrigLinkage);
70e4f3f2c0SMichael Kruse
719cfab5e2SMichael Kruse LLVM_DEBUG(dbgs() << "Write to file '" << Dumpfile << "'...\n");
729cfab5e2SMichael Kruse
739cfab5e2SMichael Kruse std::unique_ptr<ToolOutputFile> Out;
749cfab5e2SMichael Kruse std::error_code EC;
759cfab5e2SMichael Kruse Out.reset(new ToolOutputFile(Dumpfile, EC, sys::fs::OF_None));
769cfab5e2SMichael Kruse if (EC) {
779cfab5e2SMichael Kruse errs() << EC.message() << '\n';
789cfab5e2SMichael Kruse return;
799cfab5e2SMichael Kruse }
809cfab5e2SMichael Kruse
819cfab5e2SMichael Kruse CM->print(Out->os(), nullptr);
829cfab5e2SMichael Kruse Out->keep();
839cfab5e2SMichael Kruse LLVM_DEBUG(dbgs() << "Dump file " << Dumpfile << " written successfully\n");
849cfab5e2SMichael Kruse }
859cfab5e2SMichael Kruse
86bd93df93SMichael Kruse class DumpFunctionWrapperPass final : public FunctionPass {
879cfab5e2SMichael Kruse private:
889cfab5e2SMichael Kruse DumpFunctionWrapperPass(const DumpFunctionWrapperPass &) = delete;
899cfab5e2SMichael Kruse const DumpFunctionWrapperPass &
909cfab5e2SMichael Kruse operator=(const DumpFunctionWrapperPass &) = delete;
919cfab5e2SMichael Kruse
929cfab5e2SMichael Kruse std::string Suffix;
939cfab5e2SMichael Kruse
949cfab5e2SMichael Kruse public:
959cfab5e2SMichael Kruse static char ID;
969cfab5e2SMichael Kruse
DumpFunctionWrapperPass()979cfab5e2SMichael Kruse explicit DumpFunctionWrapperPass() : FunctionPass(ID), Suffix("-dump") {}
989cfab5e2SMichael Kruse
DumpFunctionWrapperPass(std::string Suffix)999cfab5e2SMichael Kruse explicit DumpFunctionWrapperPass(std::string Suffix)
1009cfab5e2SMichael Kruse : FunctionPass(ID), Suffix(std::move(Suffix)) {}
1019cfab5e2SMichael Kruse
1029cfab5e2SMichael Kruse /// @name FunctionPass interface
1039cfab5e2SMichael Kruse //@{
getAnalysisUsage(llvm::AnalysisUsage & AU) const1043f3930a4SKazu Hirata void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
1059cfab5e2SMichael Kruse AU.setPreservesAll();
1069cfab5e2SMichael Kruse }
1079cfab5e2SMichael Kruse
runOnFunction(llvm::Function & F)1083f3930a4SKazu Hirata bool runOnFunction(llvm::Function &F) override {
1099cfab5e2SMichael Kruse runDumpFunction(F, Suffix);
1109cfab5e2SMichael Kruse return false;
1119cfab5e2SMichael Kruse }
1129cfab5e2SMichael Kruse //@}
1139cfab5e2SMichael Kruse };
1149cfab5e2SMichael Kruse
1159cfab5e2SMichael Kruse char DumpFunctionWrapperPass::ID;
1169cfab5e2SMichael Kruse } // namespace
1179cfab5e2SMichael Kruse
createDumpFunctionWrapperPass(std::string Suffix)1189cfab5e2SMichael Kruse FunctionPass *polly::createDumpFunctionWrapperPass(std::string Suffix) {
1199cfab5e2SMichael Kruse return new DumpFunctionWrapperPass(std::move(Suffix));
1209cfab5e2SMichael Kruse }
1219cfab5e2SMichael Kruse
run(Function & F,FunctionAnalysisManager & AM)1229cfab5e2SMichael Kruse llvm::PreservedAnalyses DumpFunctionPass::run(Function &F,
1239cfab5e2SMichael Kruse FunctionAnalysisManager &AM) {
1249cfab5e2SMichael Kruse runDumpFunction(F, Suffix);
1259cfab5e2SMichael Kruse return PreservedAnalyses::all();
1269cfab5e2SMichael Kruse }
1279cfab5e2SMichael Kruse
1289cfab5e2SMichael Kruse INITIALIZE_PASS_BEGIN(DumpFunctionWrapperPass, "polly-dump-function",
1299cfab5e2SMichael Kruse "Polly - Dump Function", false, false)
1309cfab5e2SMichael Kruse INITIALIZE_PASS_END(DumpFunctionWrapperPass, "polly-dump-function",
1319cfab5e2SMichael Kruse "Polly - Dump Function", false, false)
132