mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-03-01 14:58:18 +00:00
[Polly] Add support for -polly-dump-before/after with NPM.
The new pass manager does not allow adding module passes at the -polly-position=before-vectorizer extension point. Introduce a DumpFunctionPass that dumps only current function. In contrast to the legacy pass manager's -polly-dump-before, each function will be dumped into its own file. -polly-dump-before-file is still not supported. The DumpFunctionPass uses llvm::CloneModule to copy the current function into a new module and then write it into a file.
This commit is contained in:
parent
a8de667af0
commit
9cfab5e249
@ -16,6 +16,7 @@
|
||||
|
||||
#include "polly/CodeGen/PPCGCodeGeneration.h"
|
||||
#include "polly/Config/config.h"
|
||||
#include "polly/Support/DumpFunctionPass.h"
|
||||
#include "polly/Support/DumpModulePass.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cstdlib>
|
||||
@ -100,6 +101,7 @@ struct PollyForcePassLinking {
|
||||
polly::createForwardOpTreeWrapperPass();
|
||||
polly::createDeLICMWrapperPass();
|
||||
polly::createDumpModuleWrapperPass("", true);
|
||||
polly::createDumpFunctionWrapperPass("");
|
||||
polly::createSimplifyWrapperPass(0);
|
||||
polly::createPruneUnprofitableWrapperPass();
|
||||
}
|
||||
|
43
polly/include/polly/Support/DumpFunctionPass.h
Normal file
43
polly/include/polly/Support/DumpFunctionPass.h
Normal file
@ -0,0 +1,43 @@
|
||||
//===------ DumpFunctionPass.cpp --------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Write a function to a file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef POLLY_SUPPORT_DUMPFUNCTIONPASS_H
|
||||
#define POLLY_SUPPORT_DUMPFUNCTIONPASS_H
|
||||
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
class ModulePass;
|
||||
} // namespace llvm
|
||||
|
||||
namespace polly {
|
||||
llvm::FunctionPass *createDumpFunctionWrapperPass(std::string Suffix);
|
||||
|
||||
/// A pass that isolates a function into a new Module and writes it into a file.
|
||||
struct DumpFunctionPass : llvm::PassInfoMixin<DumpFunctionPass> {
|
||||
std::string Suffix;
|
||||
|
||||
DumpFunctionPass(std::string Suffix) : Suffix(std::move(Suffix)) {}
|
||||
|
||||
llvm::PreservedAnalyses run(llvm::Function &F,
|
||||
llvm::FunctionAnalysisManager &AM);
|
||||
};
|
||||
|
||||
} // namespace polly
|
||||
|
||||
namespace llvm {
|
||||
class PassRegistry;
|
||||
void initializeDumpFunctionWrapperPassPass(llvm::PassRegistry &);
|
||||
} // namespace llvm
|
||||
|
||||
#endif /* POLLY_SUPPORT_DUMPFUNCTIONPASS_H */
|
@ -83,6 +83,7 @@ add_llvm_pass_plugin(Polly
|
||||
Support/ScopLocation.cpp
|
||||
Support/ISLTools.cpp
|
||||
Support/DumpModulePass.cpp
|
||||
Support/DumpFunctionPass.cpp
|
||||
Support/VirtualInstruction.cpp
|
||||
Transform/Canonicalization.cpp
|
||||
Transform/CodePreparation.cpp
|
||||
|
121
polly/lib/Support/DumpFunctionPass.cpp
Normal file
121
polly/lib/Support/DumpFunctionPass.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
//===------ DumpFunctionPass.cpp --------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Write a function to a file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "polly/Support/DumpFunctionPass.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 "llvm/Transforms/IPO/GlobalDCE.h"
|
||||
#include "llvm/Transforms/IPO/StripDeadPrototypes.h"
|
||||
#include "llvm/Transforms/Utils/Cloning.h"
|
||||
|
||||
#define DEBUG_TYPE "polly-dump-func"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace polly;
|
||||
|
||||
namespace {
|
||||
|
||||
static void runDumpFunction(llvm::Function &F, StringRef Suffix) {
|
||||
StringRef FName = F.getName();
|
||||
Module *M = F.getParent();
|
||||
|
||||
StringRef ModuleName = M->getName();
|
||||
StringRef Stem = sys::path::stem(ModuleName);
|
||||
std::string Dumpfile = (Twine(Stem) + "-" + FName + Suffix + ".ll").str();
|
||||
LLVM_DEBUG(dbgs() << "Dumping function '" << FName << "' to '" << Dumpfile
|
||||
<< "'...\n");
|
||||
|
||||
ValueToValueMapTy VMap;
|
||||
auto ShouldCloneDefinition = [&F](const GlobalValue *GV) -> bool {
|
||||
return GV == &F;
|
||||
};
|
||||
std::unique_ptr<Module> CM = CloneModule(*M, VMap, ShouldCloneDefinition);
|
||||
|
||||
LLVM_DEBUG(dbgs() << "Global DCE...\n");
|
||||
|
||||
{
|
||||
ModuleAnalysisManager MAM;
|
||||
ModulePassManager MPM;
|
||||
|
||||
PassInstrumentationCallbacks PIC;
|
||||
MAM.registerPass([&] { return PassInstrumentationAnalysis(&PIC); });
|
||||
|
||||
MPM.addPass(GlobalDCEPass());
|
||||
MPM.addPass(StripDeadPrototypesPass());
|
||||
MPM.run(*CM, MAM);
|
||||
}
|
||||
|
||||
LLVM_DEBUG(dbgs() << "Write to file '" << Dumpfile << "'...\n");
|
||||
|
||||
std::unique_ptr<ToolOutputFile> Out;
|
||||
std::error_code EC;
|
||||
Out.reset(new ToolOutputFile(Dumpfile, EC, sys::fs::OF_None));
|
||||
if (EC) {
|
||||
errs() << EC.message() << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
CM->print(Out->os(), nullptr);
|
||||
Out->keep();
|
||||
LLVM_DEBUG(dbgs() << "Dump file " << Dumpfile << " written successfully\n");
|
||||
}
|
||||
|
||||
class DumpFunctionWrapperPass : public FunctionPass {
|
||||
private:
|
||||
DumpFunctionWrapperPass(const DumpFunctionWrapperPass &) = delete;
|
||||
const DumpFunctionWrapperPass &
|
||||
operator=(const DumpFunctionWrapperPass &) = delete;
|
||||
|
||||
std::string Suffix;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
explicit DumpFunctionWrapperPass() : FunctionPass(ID), Suffix("-dump") {}
|
||||
|
||||
explicit DumpFunctionWrapperPass(std::string Suffix)
|
||||
: FunctionPass(ID), Suffix(std::move(Suffix)) {}
|
||||
|
||||
/// @name FunctionPass interface
|
||||
//@{
|
||||
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
virtual bool runOnFunction(llvm::Function &F) override {
|
||||
runDumpFunction(F, Suffix);
|
||||
return false;
|
||||
}
|
||||
//@}
|
||||
};
|
||||
|
||||
char DumpFunctionWrapperPass::ID;
|
||||
} // namespace
|
||||
|
||||
FunctionPass *polly::createDumpFunctionWrapperPass(std::string Suffix) {
|
||||
return new DumpFunctionWrapperPass(std::move(Suffix));
|
||||
}
|
||||
|
||||
llvm::PreservedAnalyses DumpFunctionPass::run(Function &F,
|
||||
FunctionAnalysisManager &AM) {
|
||||
runDumpFunction(F, Suffix);
|
||||
return PreservedAnalyses::all();
|
||||
}
|
||||
|
||||
INITIALIZE_PASS_BEGIN(DumpFunctionWrapperPass, "polly-dump-function",
|
||||
"Polly - Dump Function", false, false)
|
||||
INITIALIZE_PASS_END(DumpFunctionWrapperPass, "polly-dump-function",
|
||||
"Polly - Dump Function", false, false)
|
@ -36,6 +36,7 @@
|
||||
#include "polly/ScopDetection.h"
|
||||
#include "polly/ScopInfo.h"
|
||||
#include "polly/Simplify.h"
|
||||
#include "polly/Support/DumpFunctionPass.h"
|
||||
#include "polly/Support/DumpModulePass.h"
|
||||
#include "llvm/Analysis/CFGPrinter.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
@ -610,19 +611,19 @@ static void buildLatePollyPipeline(FunctionPassManager &PM,
|
||||
return;
|
||||
|
||||
if (DumpBefore)
|
||||
report_fatal_error("Option -polly-dump-before not supported with NPM",
|
||||
false);
|
||||
PM.addPass(DumpFunctionPass("-before"));
|
||||
if (!DumpBeforeFile.empty())
|
||||
report_fatal_error("Option -polly-dump-before-file not supported with NPM",
|
||||
report_fatal_error("Option -polly-dump-before-file at -polly-position=late "
|
||||
"not supported with NPM",
|
||||
false);
|
||||
|
||||
buildCommonPollyPipeline(PM, Level, EnableForOpt);
|
||||
|
||||
if (DumpAfter)
|
||||
report_fatal_error("Option -polly-dump-after not supported with NPM",
|
||||
false);
|
||||
PM.addPass(DumpFunctionPass("-after"));
|
||||
if (!DumpAfterFile.empty())
|
||||
report_fatal_error("Option -polly-dump-after-file not supported with NPM",
|
||||
report_fatal_error("Option -polly-dump-after-file at -polly-position=late "
|
||||
"not supported with NPM",
|
||||
false);
|
||||
}
|
||||
|
||||
|
94
polly/test/Support/dumpfunction.ll
Normal file
94
polly/test/Support/dumpfunction.ll
Normal file
@ -0,0 +1,94 @@
|
||||
; New pass manager
|
||||
; RUN: opt %loadPolly -enable-new-pm=1 -O3 -polly -polly-position=before-vectorizer -polly-dump-before --disable-output %s
|
||||
; RUN: FileCheck --input-file=dumpfunction-callee-before.ll --check-prefix=CHECK --check-prefix=CALLEE %s
|
||||
; RUN: FileCheck --input-file=dumpfunction-caller-before.ll --check-prefix=CHECK --check-prefix=CALLER %s
|
||||
;
|
||||
; RUN: opt %loadPolly -enable-new-pm=1 -O3 -polly -polly-position=before-vectorizer -polly-dump-after --disable-output %s
|
||||
; RUN: FileCheck --input-file=dumpfunction-callee-before.ll --check-prefix=CHECK --check-prefix=CALLEE %s
|
||||
; RUN: FileCheck --input-file=dumpfunction-caller-before.ll --check-prefix=CHECK --check-prefix=CALLER %s
|
||||
|
||||
; void callee(int n, double A[], int i) {
|
||||
; for (int j = 0; j < n; j += 1)
|
||||
; A[i+j] = 42.0;
|
||||
; }
|
||||
;
|
||||
; void caller(int n, double A[]) {
|
||||
; for (int i = 0; i < n; i += 1)
|
||||
; callee(n, A, i);
|
||||
; }
|
||||
|
||||
|
||||
%unrelated_type = type { i32 }
|
||||
|
||||
@callee_alias = dso_local unnamed_addr alias void(i32, double*, i32), void(i32, double*, i32 )* @callee
|
||||
|
||||
define void @callee(i32 %n, double* noalias nonnull %A, i32 %i) {
|
||||
entry:
|
||||
br label %for
|
||||
|
||||
for:
|
||||
%j = phi i32 [0, %entry], [%j.inc, %inc]
|
||||
%j.cmp = icmp slt i32 %j, %n
|
||||
br i1 %j.cmp, label %body, label %exit
|
||||
|
||||
body:
|
||||
%idx = add i32 %i, %j
|
||||
%arrayidx = getelementptr inbounds double, double* %A, i32 %idx
|
||||
store double 42.0, double* %arrayidx
|
||||
br label %inc
|
||||
|
||||
inc:
|
||||
%j.inc = add nuw nsw i32 %j, 1
|
||||
br label %for
|
||||
|
||||
exit:
|
||||
br label %return
|
||||
|
||||
return:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
define void @caller(i32 %n, double* noalias nonnull %A) {
|
||||
entry:
|
||||
br label %for
|
||||
|
||||
for:
|
||||
%i = phi i32 [0, %entry], [%j.inc, %inc]
|
||||
%i.cmp = icmp slt i32 %i, %n
|
||||
br i1 %i.cmp, label %body, label %exit
|
||||
|
||||
body:
|
||||
call void @callee_alias(i32 %n, double* %A, i32 %i)
|
||||
br label %inc
|
||||
|
||||
inc:
|
||||
%j.inc = add nuw nsw i32 %i, 1
|
||||
br label %for
|
||||
|
||||
exit:
|
||||
br label %return
|
||||
|
||||
return:
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
declare void @unrelated_decl()
|
||||
|
||||
|
||||
!llvm.ident = !{!8}
|
||||
!8 = !{!"xyxxy"}
|
||||
|
||||
|
||||
; CHECK-NOT: unrelated_type
|
||||
|
||||
; CALLEE-LABEL: @callee(
|
||||
; CALLEE-NOT: @caller
|
||||
; CALLEE-NOT: @unrelated_decl
|
||||
|
||||
; CALLER-NOT: @callee(
|
||||
; CALLER-LABEL: @caller(
|
||||
|
||||
; CHECK-NOT: @unrelated_decl
|
||||
; CHECK: xyxxy
|
Loading…
x
Reference in New Issue
Block a user