mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-13 11:22:03 +00:00
[Support] Add -polly-dump-module pass.
This pass allows writing the LLVM-IR just before and after the Polly passes to a file. Dumping the IR before Polly helps reproducing bugs that occur in code generated by clang. It is the only reliable way to get the IR that triggers a bug. The alternative is to emit the IR with clang -c -emit-llvm -S -o dump.ll then pass it through all optimization passes opt dump.ll -basicaa -sroa ... -S -o optdump.ll to then reproduce the error with opt optdump.ll -polly-opt-isl -polly-codegen -analyze However, the IR is not the same. -O3 uses a PassBuilder than creates passes with different parameters than the default. Dumping the IR after Polly is useful to compare a miscompilation with a known-good configuration. Differential Revision: https://reviews.llvm.org/D30788 llvm-svn: 297415
This commit is contained in:
parent
544210304f
commit
e4292bf086
@ -16,6 +16,8 @@
|
||||
#define POLLY_LINKALLPASSES_H
|
||||
|
||||
#include "polly/Config/config.h"
|
||||
#include "polly/Support/DumpModulePass.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace llvm {
|
||||
@ -84,6 +86,7 @@ struct PollyForcePassLinking {
|
||||
polly::createIslScheduleOptimizerPass();
|
||||
polly::createFlattenSchedulePass();
|
||||
polly::createDeLICMPass();
|
||||
polly::createDumpModulePass("", true);
|
||||
}
|
||||
} PollyForcePassLinking; // Force link by creating a global definition.
|
||||
} // namespace
|
||||
|
40
polly/include/polly/Support/DumpModulePass.h
Normal file
40
polly/include/polly/Support/DumpModulePass.h
Normal file
@ -0,0 +1,40 @@
|
||||
//===------ DumpModulePass.cpp ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Write a module to a file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef POLLY_SUPPORT_DUMPMODULEPASS_H
|
||||
#define POLLY_SUPPORT_DUMPMODULEPASS_H
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
class ModulePass;
|
||||
} // namespace llvm
|
||||
|
||||
namespace polly {
|
||||
/// Create a pass that prints the module into a file.
|
||||
///
|
||||
/// The meaning of @p Filename depends on @p IsSuffix. If IsSuffix==false, then
|
||||
/// the module is written to the @p Filename. If it is true, the filename is
|
||||
/// generated from the module's name, @p Filename with an '.ll' extension.
|
||||
///
|
||||
/// The intent of IsSuffix is to avoid the file being overwritten when
|
||||
/// processing multiple modules and/or with multiple dump passes in the
|
||||
/// pipeline.
|
||||
llvm::ModulePass *createDumpModulePass(llvm::StringRef Filename, bool IsSuffix);
|
||||
} // namespace polly
|
||||
|
||||
namespace llvm {
|
||||
class PassRegistry;
|
||||
void initializeDumpModulePass(llvm::PassRegistry &);
|
||||
} // namespace llvm
|
||||
|
||||
#endif /* POLLY_SUPPORT_DUMPMODULEPASS_H */
|
@ -51,6 +51,7 @@ add_polly_library(Polly
|
||||
Support/ScopHelper.cpp
|
||||
Support/ScopLocation.cpp
|
||||
Support/ISLTools.cpp
|
||||
Support/DumpModulePass.cpp
|
||||
${POLLY_JSON_FILES}
|
||||
Transform/Canonicalization.cpp
|
||||
Transform/CodePreparation.cpp
|
||||
|
95
polly/lib/Support/DumpModulePass.cpp
Normal file
95
polly/lib/Support/DumpModulePass.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
//===------ DumpModulePass.cpp ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Write a module to a file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "polly/Support/DumpModulePass.h"
|
||||
|
||||
#include "polly/Options.h"
|
||||
#include "llvm/IR/LegacyPassManagers.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/ToolOutputFile.h"
|
||||
#include <string.h>
|
||||
#define DEBUG_TYPE "polly-dump-module"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace polly;
|
||||
|
||||
namespace {
|
||||
|
||||
class DumpModule : public ModulePass {
|
||||
private:
|
||||
DumpModule(const DumpModule &) = delete;
|
||||
const DumpModule &operator=(const DumpModule &) = delete;
|
||||
|
||||
std::string Filename;
|
||||
bool IsSuffix;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
/// This constructor is used e.g. if using opt -polly-dump-module.
|
||||
///
|
||||
/// Provide a default suffix to not overwrite the original file.
|
||||
explicit DumpModule() : ModulePass(ID), Filename("-dump"), IsSuffix(true) {}
|
||||
|
||||
explicit DumpModule(llvm::StringRef Filename, bool IsSuffix)
|
||||
: ModulePass(ID), Filename(Filename), IsSuffix(IsSuffix) {}
|
||||
|
||||
/// @name ModulePass interface
|
||||
//@{
|
||||
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
virtual bool runOnModule(llvm::Module &M) override {
|
||||
std::string Dumpfile;
|
||||
if (IsSuffix) {
|
||||
auto ModuleName = M.getName();
|
||||
auto Stem = sys::path::stem(ModuleName);
|
||||
Dumpfile = (Twine(Stem) + Filename + ".ll").str();
|
||||
} else {
|
||||
Dumpfile = Filename;
|
||||
}
|
||||
DEBUG(dbgs() << "Dumping module to " << Dumpfile << '\n');
|
||||
|
||||
std::unique_ptr<tool_output_file> Out;
|
||||
std::error_code EC;
|
||||
Out.reset(new tool_output_file(Dumpfile, EC, sys::fs::F_None));
|
||||
if (EC) {
|
||||
errs() << EC.message() << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
M.print(Out->os(), nullptr);
|
||||
Out->keep();
|
||||
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
};
|
||||
|
||||
char DumpModule::ID;
|
||||
} // namespace
|
||||
|
||||
ModulePass *polly::createDumpModulePass(llvm::StringRef Filename,
|
||||
bool IsSuffix) {
|
||||
return new DumpModule(Filename, IsSuffix);
|
||||
}
|
||||
|
||||
INITIALIZE_PASS_BEGIN(DumpModule, "polly-dump-module", "Polly - Dump Module",
|
||||
false, false)
|
||||
INITIALIZE_PASS_END(DumpModule, "polly-dump-module", "Polly - Dump Module",
|
||||
false, false)
|
@ -31,6 +31,7 @@
|
||||
#include "polly/PolyhedralInfo.h"
|
||||
#include "polly/ScopDetection.h"
|
||||
#include "polly/ScopInfo.h"
|
||||
#include "polly/Support/DumpModulePass.h"
|
||||
#include "llvm/Analysis/CFGPrinter.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
@ -160,6 +161,28 @@ static cl::opt<bool>
|
||||
cl::desc("Enable polyhedral interface of Polly"),
|
||||
cl::Hidden, cl::init(false), cl::cat(PollyCategory));
|
||||
|
||||
static cl::opt<bool>
|
||||
DumpBefore("polly-dump-before",
|
||||
cl::desc("Dump module before Polly transformations into a file "
|
||||
"suffixed with \"-before\""),
|
||||
cl::init(false), cl::cat(PollyCategory));
|
||||
|
||||
static cl::list<std::string> DumpBeforeFile(
|
||||
"polly-dump-before-file",
|
||||
cl::desc("Dump module before Polly transformations to the given file"),
|
||||
cl::cat(PollyCategory));
|
||||
|
||||
static cl::opt<bool>
|
||||
DumpAfter("polly-dump-after",
|
||||
cl::desc("Dump module after Polly transformations into a file "
|
||||
"suffixed with \"-after\""),
|
||||
cl::init(false), cl::cat(PollyCategory));
|
||||
|
||||
static cl::list<std::string> DumpAfterFile(
|
||||
"polly-dump-after-file",
|
||||
cl::desc("Dump module after Polly transformations to the given file"),
|
||||
cl::ZeroOrMore, cl::cat(PollyCategory));
|
||||
|
||||
static cl::opt<bool>
|
||||
EnableDeLICM("polly-enable-delicm",
|
||||
cl::desc("Eliminate scalar loop carried dependences"),
|
||||
@ -188,6 +211,7 @@ void initializePollyPasses(PassRegistry &Registry) {
|
||||
initializeCodegenCleanupPass(Registry);
|
||||
initializeFlattenSchedulePass(Registry);
|
||||
initializeDeLICMPass(Registry);
|
||||
initializeDumpModulePass(Registry);
|
||||
}
|
||||
|
||||
/// Register Polly passes such that they form a polyhedral optimizer.
|
||||
@ -217,6 +241,11 @@ void initializePollyPasses(PassRegistry &Registry) {
|
||||
///
|
||||
/// Polly supports the isl internal code generator.
|
||||
void registerPollyPasses(llvm::legacy::PassManagerBase &PM) {
|
||||
if (DumpBefore)
|
||||
PM.add(polly::createDumpModulePass("-before", true));
|
||||
for (auto &Filename : DumpBeforeFile)
|
||||
PM.add(polly::createDumpModulePass(Filename, false));
|
||||
|
||||
PM.add(polly::createScopDetectionPass());
|
||||
|
||||
if (PollyDetectOnly)
|
||||
@ -282,6 +311,11 @@ void registerPollyPasses(llvm::legacy::PassManagerBase &PM) {
|
||||
// force all analysis results to be recomputed.
|
||||
PM.add(createBarrierNoopPass());
|
||||
|
||||
if (DumpAfter)
|
||||
PM.add(polly::createDumpModulePass("-after", true));
|
||||
for (auto &Filename : DumpAfterFile)
|
||||
PM.add(polly::createDumpModulePass(Filename, false));
|
||||
|
||||
if (CFGPrinter)
|
||||
PM.add(llvm::createCFGPrinterLegacyPassPass());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user