1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

Port print-must-be-executed-contexts and print-mustexecute to NPM

Reviewed By: asbirlea

Differential Revision: https://reviews.llvm.org/D90207
This commit is contained in:
Arthur Eubanks 2020-10-26 19:57:39 -07:00
parent de70f3e87f
commit e22b9f13f5
6 changed files with 142 additions and 75 deletions

View File

@ -27,6 +27,8 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/InstructionPrecedenceTracking.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
@ -541,6 +543,23 @@ private:
MustBeExecutedIterator EndIterator;
};
class MustExecutePrinterPass : public PassInfoMixin<MustExecutePrinterPass> {
raw_ostream &OS;
public:
MustExecutePrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
class MustBeExecutedContextPrinterPass
: public PassInfoMixin<MustBeExecutedContextPrinterPass> {
raw_ostream &OS;
public:
MustBeExecutedContextPrinterPass(raw_ostream &OS) : OS(OS) {}
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
};
} // namespace llvm
#endif

View File

@ -16,9 +16,11 @@
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
@ -300,30 +302,31 @@ bool ICFLoopSafetyInfo::doesNotWriteMemoryBefore(const Instruction &I,
}
namespace {
struct MustExecutePrinter : public FunctionPass {
struct MustExecutePrinter : public FunctionPass {
static char ID; // Pass identification, replacement for typeid
MustExecutePrinter() : FunctionPass(ID) {
initializeMustExecutePrinterPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
}
bool runOnFunction(Function &F) override;
};
struct MustBeExecutedContextPrinter : public ModulePass {
static char ID;
static char ID; // Pass identification, replacement for typeid
MustExecutePrinter() : FunctionPass(ID) {
initializeMustExecutePrinterPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<DominatorTreeWrapperPass>();
AU.addRequired<LoopInfoWrapperPass>();
}
bool runOnFunction(Function &F) override;
};
struct MustBeExecutedContextPrinter : public ModulePass {
static char ID;
MustBeExecutedContextPrinter() : ModulePass(ID) {
initializeMustBeExecutedContextPrinterPass(*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
bool runOnModule(Module &M) override;
};
MustBeExecutedContextPrinter() : ModulePass(ID) {
initializeMustBeExecutedContextPrinterPass(
*PassRegistry::getPassRegistry());
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
}
bool runOnModule(Module &M) override;
};
}
char MustExecutePrinter::ID = 0;
@ -339,15 +342,16 @@ FunctionPass *llvm::createMustExecutePrinter() {
}
char MustBeExecutedContextPrinter::ID = 0;
INITIALIZE_PASS_BEGIN(
MustBeExecutedContextPrinter, "print-must-be-executed-contexts",
"print the must-be-executed-contexed for all instructions", false, true)
INITIALIZE_PASS_BEGIN(MustBeExecutedContextPrinter,
"print-must-be-executed-contexts",
"print the must-be-executed-context for all instructions",
false, true)
INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
INITIALIZE_PASS_END(MustBeExecutedContextPrinter,
"print-must-be-executed-contexts",
"print the must-be-executed-contexed for all instructions",
"print the must-be-executed-context for all instructions",
false, true)
ModulePass *llvm::createMustBeExecutedContextPrinter() {
@ -835,3 +839,42 @@ const Instruction *MustBeExecutedIterator::advance() {
Tail = nullptr;
return nullptr;
}
PreservedAnalyses MustExecutePrinterPass::run(Function &F,
FunctionAnalysisManager &AM) {
auto &LI = AM.getResult<LoopAnalysis>(F);
auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
MustExecuteAnnotatedWriter Writer(F, DT, LI);
F.print(OS, &Writer);
return PreservedAnalyses::all();
}
PreservedAnalyses
MustBeExecutedContextPrinterPass::run(Module &M, ModuleAnalysisManager &AM) {
FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
GetterTy<const LoopInfo> LIGetter = [&](const Function &F) {
return &FAM.getResult<LoopAnalysis>(const_cast<Function &>(F));
};
GetterTy<const DominatorTree> DTGetter = [&](const Function &F) {
return &FAM.getResult<DominatorTreeAnalysis>(const_cast<Function &>(F));
};
GetterTy<const PostDominatorTree> PDTGetter = [&](const Function &F) {
return &FAM.getResult<PostDominatorTreeAnalysis>(const_cast<Function &>(F));
};
MustBeExecutedContextExplorer Explorer(
/* ExploreInterBlock */ true,
/* ExploreCFGForward */ true,
/* ExploreCFGBackward */ true, LIGetter, DTGetter, PDTGetter);
for (Function &F : M) {
for (Instruction &I : instructions(F)) {
OS << "-- Explore context of: " << I << "\n";
for (const Instruction *CI : Explorer.range(&I))
OS << " [F: " << CI->getFunction()->getName() << "] " << *CI << "\n";
}
}
return PreservedAnalyses::all();
}

View File

@ -51,6 +51,7 @@
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/ModuleDebugInfoPrinter.h"
#include "llvm/Analysis/ModuleSummaryAnalysis.h"
#include "llvm/Analysis/MustExecute.h"
#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/PhiValues.h"

View File

@ -86,6 +86,7 @@ MODULE_PASS("print-callgraph", CallGraphPrinterPass(dbgs()))
MODULE_PASS("print", PrintModulePass(dbgs()))
MODULE_PASS("print-lcg", LazyCallGraphPrinterPass(dbgs()))
MODULE_PASS("print-lcg-dot", LazyCallGraphDOTPrinterPass(dbgs()))
MODULE_PASS("print-must-be-executed-contexts", MustBeExecutedContextPrinterPass(dbgs()))
MODULE_PASS("print-stack-safety", StackSafetyGlobalPrinterPass(dbgs()))
MODULE_PASS("print<module-debuginfo>", ModuleDebugInfoPrinterPass(dbgs()))
MODULE_PASS("rewrite-statepoints-for-gc", RewriteStatepointsForGC())
@ -276,9 +277,10 @@ FUNCTION_PASS("print<phi-values>", PhiValuesPrinterPass(dbgs()))
FUNCTION_PASS("print<regions>", RegionInfoPrinterPass(dbgs()))
FUNCTION_PASS("print<scalar-evolution>", ScalarEvolutionPrinterPass(dbgs()))
FUNCTION_PASS("print<stack-safety-local>", StackSafetyPrinterPass(dbgs()))
// TODO: rename to print<alias-sets> after NPM switch
// TODO: rename to print<foo> after NPM switch
FUNCTION_PASS("print-alias-sets", AliasSetsPrinterPass(dbgs()))
FUNCTION_PASS("print-predicateinfo", PredicateInfoPrinterPass(dbgs()))
FUNCTION_PASS("print-mustexecute", MustExecutePrinterPass(dbgs()))
FUNCTION_PASS("reassociate", ReassociatePass())
FUNCTION_PASS("scalarizer", ScalarizerPass())
FUNCTION_PASS("sccp", SCCPPass())

View File

@ -1,46 +1,47 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -disable-output -print-mustexecute %s 2>&1 | FileCheck %s
; In general the CFG below is easily simplified but this is useful for
; pass ordering issue elimination.
define i1 @const_cond(i32 %high) {
; CHECK-LABEL: @const_cond(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] ; (mustexec in: loop)
; CHECK-NEXT: br i1 true, label [[NEXT:%.*]], label [[NEVER1:%.*]] ; (mustexec in: loop)
; CHECK: next:
; CHECK-NEXT: br i1 false, label [[NEVER2:%.*]], label [[BACKEDGE]] ; (mustexec in: loop)
; CHECK: backedge:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 ; (mustexec in: loop)
; CHECK-NEXT: [[EXIT_TEST:%.*]] = icmp slt i32 [[IV]], [[HIGH:%.*]] ; (mustexec in: loop)
; CHECK-NEXT: br i1 [[EXIT_TEST]], label [[LOOP]], label [[EXIT:%.*]] ; (mustexec in: loop)
; CHECK: exit:
; CHECK-NEXT: ret i1 false
; CHECK: never1:
; CHECK-NEXT: unreachable
; CHECK: never2:
; CHECK-NEXT: unreachable
;
entry:
br label %loop
loop:
%iv = phi i32 [0, %entry], [%iv.next, %backedge]
br i1 true, label %next, label %never1
next:
br i1 false, label %never2, label %backedge
backedge:
%iv.next = add nsw nuw i32 %iv, 1
%exit.test = icmp slt i32 %iv, %high
br i1 %exit.test, label %loop, label %exit
exit:
ret i1 false
never1:
unreachable
never2:
unreachable
}
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -disable-output -print-mustexecute %s 2>&1 | FileCheck %s
; RUN: opt -disable-output -passes=print-mustexecute %s 2>&1 | FileCheck %s
; In general the CFG below is easily simplified but this is useful for
; pass ordering issue elimination.
define i1 @const_cond(i32 %high) {
; CHECK-LABEL: @const_cond(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] ; (mustexec in: loop)
; CHECK-NEXT: br i1 true, label [[NEXT:%.*]], label [[NEVER1:%.*]] ; (mustexec in: loop)
; CHECK: next:
; CHECK-NEXT: br i1 false, label [[NEVER2:%.*]], label [[BACKEDGE]] ; (mustexec in: loop)
; CHECK: backedge:
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 ; (mustexec in: loop)
; CHECK-NEXT: [[EXIT_TEST:%.*]] = icmp slt i32 [[IV]], [[HIGH:%.*]] ; (mustexec in: loop)
; CHECK-NEXT: br i1 [[EXIT_TEST]], label [[LOOP]], label [[EXIT:%.*]] ; (mustexec in: loop)
; CHECK: exit:
; CHECK-NEXT: ret i1 false
; CHECK: never1:
; CHECK-NEXT: unreachable
; CHECK: never2:
; CHECK-NEXT: unreachable
;
entry:
br label %loop
loop:
%iv = phi i32 [0, %entry], [%iv.next, %backedge]
br i1 true, label %next, label %never1
next:
br i1 false, label %never2, label %backedge
backedge:
%iv.next = add nsw nuw i32 %iv, 1
%exit.test = icmp slt i32 %iv, %high
br i1 %exit.test, label %loop, label %exit
exit:
ret i1 false
never1:
unreachable
never2:
unreachable
}

View File

@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -print-mustexecute -analyze 2>&1 | FileCheck %s --check-prefix=ME
; RUN: opt < %s -print-must-be-executed-contexts -analyze 2>&1 | FileCheck %s --check-prefix=MBEC
; RUN: opt < %s -print-mustexecute -disable-output 2>&1 | FileCheck %s --check-prefix=ME
; RUN: opt < %s -print-must-be-executed-contexts -disable-output 2>&1 | FileCheck %s --check-prefix=MBEC
; RUN: opt < %s -passes=print-must-be-executed-contexts -disable-output 2>&1 | FileCheck %s --check-prefix=MBEC
;
; void simple_conditional(int c) {
; A();