Skip to content

Commit

Permalink
Merged master:8260db752c91 into amd-gfx:362b06229d79
Browse files Browse the repository at this point in the history
Local branch amd-gfx 362b062 Merged master:7ba3293691be into amd-gfx:f2bcfb477c22
Remote branch master 8260db7 [mlir][Python] Return and accept OpView for all functions.
  • Loading branch information
Sw authored and Sw committed Nov 4, 2020
2 parents 362b062 + 8260db7 commit d382ea1
Show file tree
Hide file tree
Showing 39 changed files with 1,040 additions and 250 deletions.
19 changes: 19 additions & 0 deletions llvm/include/llvm/Analysis/MustExecute.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -541,6 +543,23 @@ struct MustBeExecutedContextExplorer {
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
95 changes: 69 additions & 26 deletions llvm/lib/Analysis/MustExecute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand All @@ -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() {
Expand Down Expand Up @@ -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();
}
1 change: 1 addition & 0 deletions llvm/lib/Passes/PassBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Passes/PassRegistry.def
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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())
Expand Down
51 changes: 20 additions & 31 deletions llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ using namespace PatternMatch;
STATISTIC(NumAnyOrAllBitsSet, "Number of any/all-bits-set patterns folded");
STATISTIC(NumGuardedRotates,
"Number of guarded rotates transformed into funnel shifts");
STATISTIC(NumGuardedFunnelShifts,
"Number of guarded funnel shifts transformed into funnel shifts");
STATISTIC(NumPopCountRecognized, "Number of popcount idioms recognized");

namespace {
Expand Down Expand Up @@ -69,17 +67,17 @@ class AggressiveInstCombinerLegacyPass : public FunctionPass {
};
} // namespace

/// Match a pattern for a bitwise funnel/rotate operation that partially guards
/// against undefined behavior by branching around the funnel-shift/rotation
/// when the shift amount is 0.
static bool foldGuardedFunnelShift(Instruction &I) {
/// Match a pattern for a bitwise rotate operation that partially guards
/// against undefined behavior by branching around the rotation when the shift
/// amount is 0.
static bool foldGuardedRotateToFunnelShift(Instruction &I) {
if (I.getOpcode() != Instruction::PHI || I.getNumOperands() != 2)
return false;

// As with the one-use checks below, this is not strictly necessary, but we
// are being cautious to avoid potential perf regressions on targets that
// do not actually have a funnel/rotate instruction (where the funnel shift
// would be expanded back into math/shift/logic ops).
// do not actually have a rotate instruction (where the funnel shift would be
// expanded back into math/shift/logic ops).
if (!isPowerOf2_32(I.getType()->getScalarSizeInBits()))
return false;

Expand Down Expand Up @@ -113,33 +111,27 @@ static bool foldGuardedFunnelShift(Instruction &I) {
return Intrinsic::not_intrinsic;
};

// One phi operand must be a funnel/rotate operation, and the other phi
// operand must be the source value of that funnel/rotate operation:
// One phi operand must be a rotate operation, and the other phi operand must
// be the source value of that rotate operation:
// phi [ rotate(RotSrc, ShAmt), FunnelBB ], [ RotSrc, GuardBB ]
// phi [ fshl(ShlVal0, ShlVal1, ShAmt), FunnelBB ], [ ShlVal0, GuardBB ]
// phi [ fshr(ShlVal0, ShlVal1, ShAmt), FunnelBB ], [ ShlVal1, GuardBB ]
PHINode &Phi = cast<PHINode>(I);
unsigned FunnelOp = 0, GuardOp = 1;
Value *P0 = Phi.getOperand(0), *P1 = Phi.getOperand(1);
Value *ShVal0, *ShVal1, *ShAmt;
Intrinsic::ID IID = matchFunnelShift(P0, ShVal0, ShVal1, ShAmt);
if (IID == Intrinsic::not_intrinsic ||
(IID == Intrinsic::fshl && ShVal0 != P1) ||
(IID == Intrinsic::fshr && ShVal1 != P1)) {
if (IID == Intrinsic::not_intrinsic || ShVal0 != ShVal1 || ShVal0 != P1) {
IID = matchFunnelShift(P1, ShVal0, ShVal1, ShAmt);
if (IID == Intrinsic::not_intrinsic ||
(IID == Intrinsic::fshl && ShVal0 != P0) ||
(IID == Intrinsic::fshr && ShVal1 != P0))
if (IID == Intrinsic::not_intrinsic || ShVal0 != ShVal1 || ShVal0 != P0)
return false;
assert((IID == Intrinsic::fshl || IID == Intrinsic::fshr) &&
"Pattern must match funnel shift left or right");
std::swap(FunnelOp, GuardOp);
}
assert(ShVal0 == ShVal1 && "Rotation funnel shift pattern expected");

// The incoming block with our source operand must be the "guard" block.
// That must contain a cmp+branch to avoid the funnel/rotate when the shift
// amount is equal to 0. The other incoming block is the block with the
// funnel/rotate.
// That must contain a cmp+branch to avoid the rotate when the shift amount
// is equal to 0. The other incoming block is the block with the rotate.
BasicBlock *GuardBB = Phi.getIncomingBlock(GuardOp);
BasicBlock *FunnelBB = Phi.getIncomingBlock(FunnelOp);
Instruction *TermI = GuardBB->getTerminator();
Expand All @@ -158,21 +150,18 @@ static bool foldGuardedFunnelShift(Instruction &I) {
// br i1 %cmp, label %PhiBB, label %FunnelBB
// FunnelBB:
// %sub = sub i32 32, %ShAmt
// %shr = lshr i32 %ShVal1, %sub
// %shl = shl i32 %ShVal0, %ShAmt
// %fsh = or i32 %shr, %shl
// %shr = lshr i32 %RotSrc, %sub
// %shl = shl i32 %RotSrc, %ShAmt
// %rot = or i32 %shr, %shl
// br label %PhiBB
// PhiBB:
// %cond = phi i32 [ %fsh, %FunnelBB ], [ %ShVal0, %GuardBB ]
// %cond = phi i32 [ %RotSrc, %FunnelBB ], [ %RotSrc, %GuardBB ]
// -->
// llvm.fshl.i32(i32 %ShVal0, i32 %ShVal1, i32 %ShAmt)
// llvm.fshl.i32(i32 %RotSrc, i32 %RotSrc, i32 %ShAmt)
IRBuilder<> Builder(PhiBB, PhiBB->getFirstInsertionPt());
Function *F = Intrinsic::getDeclaration(Phi.getModule(), IID, Phi.getType());
Phi.replaceAllUsesWith(Builder.CreateCall(F, {ShVal0, ShVal1, ShAmt}));
if (ShVal0 == ShVal1)
++NumGuardedRotates;
else
++NumGuardedFunnelShifts;
++NumGuardedRotates;
return true;
}

Expand Down Expand Up @@ -361,7 +350,7 @@ static bool foldUnusualPatterns(Function &F, DominatorTree &DT) {
// iteratively in this loop rather than waiting until the end.
for (Instruction &I : make_range(BB.rbegin(), BB.rend())) {
MadeChange |= foldAnyOrAllBitsSet(I);
MadeChange |= foldGuardedFunnelShift(I);
MadeChange |= foldGuardedRotateToFunnelShift(I);
MadeChange |= tryToRecognizePopCount(I);
}
}
Expand Down
93 changes: 47 additions & 46 deletions llvm/test/Analysis/MustExecute/const-cond.ll
Original file line number Diff line number Diff line change
@@ -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
}

Loading

0 comments on commit d382ea1

Please sign in to comment.