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"
159cfab5e2SMichael Kruse #include "llvm/Pass.h"
169cfab5e2SMichael Kruse #include "llvm/Support/Debug.h"
179cfab5e2SMichael Kruse #include "llvm/Support/FileSystem.h"
189cfab5e2SMichael Kruse #include "llvm/Support/Path.h"
199cfab5e2SMichael Kruse #include "llvm/Support/ToolOutputFile.h"
209cfab5e2SMichael Kruse #include "llvm/Transforms/IPO/GlobalDCE.h"
219cfab5e2SMichael Kruse #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
229cfab5e2SMichael Kruse #include "llvm/Transforms/Utils/Cloning.h"
239cfab5e2SMichael Kruse 
249cfab5e2SMichael Kruse #define DEBUG_TYPE "polly-dump-func"
259cfab5e2SMichael Kruse 
269cfab5e2SMichael Kruse using namespace llvm;
279cfab5e2SMichael Kruse using namespace polly;
289cfab5e2SMichael Kruse 
299cfab5e2SMichael Kruse namespace {
309cfab5e2SMichael Kruse 
runDumpFunction(llvm::Function & F,StringRef Suffix)319cfab5e2SMichael Kruse static void runDumpFunction(llvm::Function &F, StringRef Suffix) {
329cfab5e2SMichael Kruse   StringRef FName = F.getName();
339cfab5e2SMichael Kruse   Module *M = F.getParent();
349cfab5e2SMichael Kruse 
359cfab5e2SMichael Kruse   StringRef ModuleName = M->getName();
369cfab5e2SMichael Kruse   StringRef Stem = sys::path::stem(ModuleName);
379cfab5e2SMichael Kruse   std::string Dumpfile = (Twine(Stem) + "-" + FName + Suffix + ".ll").str();
389cfab5e2SMichael Kruse   LLVM_DEBUG(dbgs() << "Dumping function '" << FName << "' to '" << Dumpfile
399cfab5e2SMichael Kruse                     << "'...\n");
409cfab5e2SMichael Kruse 
419cfab5e2SMichael Kruse   ValueToValueMapTy VMap;
429cfab5e2SMichael Kruse   auto ShouldCloneDefinition = [&F](const GlobalValue *GV) -> bool {
439cfab5e2SMichael Kruse     return GV == &F;
449cfab5e2SMichael Kruse   };
459cfab5e2SMichael Kruse   std::unique_ptr<Module> CM = CloneModule(*M, VMap, ShouldCloneDefinition);
46e4f3f2c0SMichael Kruse   Function *NewF = cast<Function>(VMap.lookup(&F));
47e4f3f2c0SMichael Kruse   assert(NewF && "Expected selected function to be cloned");
489cfab5e2SMichael Kruse 
499cfab5e2SMichael Kruse   LLVM_DEBUG(dbgs() << "Global DCE...\n");
509cfab5e2SMichael Kruse 
51e4f3f2c0SMichael Kruse   // Stop F itself from being pruned
52e4f3f2c0SMichael Kruse   GlobalValue::LinkageTypes OrigLinkage = NewF->getLinkage();
53e4f3f2c0SMichael Kruse   NewF->setLinkage(GlobalValue::ExternalLinkage);
54e4f3f2c0SMichael Kruse 
559cfab5e2SMichael Kruse   {
569cfab5e2SMichael Kruse     ModuleAnalysisManager MAM;
579cfab5e2SMichael Kruse     ModulePassManager MPM;
589cfab5e2SMichael Kruse 
599cfab5e2SMichael Kruse     PassInstrumentationCallbacks PIC;
609cfab5e2SMichael Kruse     MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
619cfab5e2SMichael Kruse 
629cfab5e2SMichael Kruse     MPM.addPass(GlobalDCEPass());
639cfab5e2SMichael Kruse     MPM.addPass(StripDeadPrototypesPass());
649cfab5e2SMichael Kruse     MPM.run(*CM, MAM);
659cfab5e2SMichael Kruse   }
669cfab5e2SMichael Kruse 
67e4f3f2c0SMichael Kruse   // Restore old linkage
68e4f3f2c0SMichael Kruse   NewF->setLinkage(OrigLinkage);
69e4f3f2c0SMichael Kruse 
709cfab5e2SMichael Kruse   LLVM_DEBUG(dbgs() << "Write to file '" << Dumpfile << "'...\n");
719cfab5e2SMichael Kruse 
729cfab5e2SMichael Kruse   std::unique_ptr<ToolOutputFile> Out;
739cfab5e2SMichael Kruse   std::error_code EC;
749cfab5e2SMichael Kruse   Out.reset(new ToolOutputFile(Dumpfile, EC, sys::fs::OF_None));
759cfab5e2SMichael Kruse   if (EC) {
769cfab5e2SMichael Kruse     errs() << EC.message() << '\n';
779cfab5e2SMichael Kruse     return;
789cfab5e2SMichael Kruse   }
799cfab5e2SMichael Kruse 
809cfab5e2SMichael Kruse   CM->print(Out->os(), nullptr);
819cfab5e2SMichael Kruse   Out->keep();
829cfab5e2SMichael Kruse   LLVM_DEBUG(dbgs() << "Dump file " << Dumpfile << " written successfully\n");
839cfab5e2SMichael Kruse }
849cfab5e2SMichael Kruse 
85bd93df93SMichael Kruse class DumpFunctionWrapperPass final : public FunctionPass {
869cfab5e2SMichael Kruse private:
879cfab5e2SMichael Kruse   DumpFunctionWrapperPass(const DumpFunctionWrapperPass &) = delete;
889cfab5e2SMichael Kruse   const DumpFunctionWrapperPass &
899cfab5e2SMichael Kruse   operator=(const DumpFunctionWrapperPass &) = delete;
909cfab5e2SMichael Kruse 
919cfab5e2SMichael Kruse   std::string Suffix;
929cfab5e2SMichael Kruse 
939cfab5e2SMichael Kruse public:
949cfab5e2SMichael Kruse   static char ID;
959cfab5e2SMichael Kruse 
DumpFunctionWrapperPass()969cfab5e2SMichael Kruse   explicit DumpFunctionWrapperPass() : FunctionPass(ID), Suffix("-dump") {}
979cfab5e2SMichael Kruse 
DumpFunctionWrapperPass(std::string Suffix)989cfab5e2SMichael Kruse   explicit DumpFunctionWrapperPass(std::string Suffix)
999cfab5e2SMichael Kruse       : FunctionPass(ID), Suffix(std::move(Suffix)) {}
1009cfab5e2SMichael Kruse 
1019cfab5e2SMichael Kruse   /// @name FunctionPass interface
1029cfab5e2SMichael Kruse   //@{
getAnalysisUsage(llvm::AnalysisUsage & AU) const103*3f3930a4SKazu Hirata   void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
1049cfab5e2SMichael Kruse     AU.setPreservesAll();
1059cfab5e2SMichael Kruse   }
1069cfab5e2SMichael Kruse 
runOnFunction(llvm::Function & F)107*3f3930a4SKazu Hirata   bool runOnFunction(llvm::Function &F) override {
1089cfab5e2SMichael Kruse     runDumpFunction(F, Suffix);
1099cfab5e2SMichael Kruse     return false;
1109cfab5e2SMichael Kruse   }
1119cfab5e2SMichael Kruse   //@}
1129cfab5e2SMichael Kruse };
1139cfab5e2SMichael Kruse 
1149cfab5e2SMichael Kruse char DumpFunctionWrapperPass::ID;
1159cfab5e2SMichael Kruse } // namespace
1169cfab5e2SMichael Kruse 
createDumpFunctionWrapperPass(std::string Suffix)1179cfab5e2SMichael Kruse FunctionPass *polly::createDumpFunctionWrapperPass(std::string Suffix) {
1189cfab5e2SMichael Kruse   return new DumpFunctionWrapperPass(std::move(Suffix));
1199cfab5e2SMichael Kruse }
1209cfab5e2SMichael Kruse 
run(Function & F,FunctionAnalysisManager & AM)1219cfab5e2SMichael Kruse llvm::PreservedAnalyses DumpFunctionPass::run(Function &F,
1229cfab5e2SMichael Kruse                                               FunctionAnalysisManager &AM) {
1239cfab5e2SMichael Kruse   runDumpFunction(F, Suffix);
1249cfab5e2SMichael Kruse   return PreservedAnalyses::all();
1259cfab5e2SMichael Kruse }
1269cfab5e2SMichael Kruse 
1279cfab5e2SMichael Kruse INITIALIZE_PASS_BEGIN(DumpFunctionWrapperPass, "polly-dump-function",
1289cfab5e2SMichael Kruse                       "Polly - Dump Function", false, false)
1299cfab5e2SMichael Kruse INITIALIZE_PASS_END(DumpFunctionWrapperPass, "polly-dump-function",
1309cfab5e2SMichael Kruse                     "Polly - Dump Function", false, false)
131