Skip to content

Commit

Permalink
[LICM] Use ICFLoopSafetyInfo in LICM
Browse files Browse the repository at this point in the history
This patch makes LICM use `ICFLoopSafetyInfo` that is a smarter version
of LoopSafetyInfo that leverages power of Implicit Control Flow Tracking
to keep track of throwing instructions and give less pessimistic answers
to queries related to throws.

The ICFLoopSafetyInfo itself has been introduced in rL344601. This patch
enables it in LICM only.

Differential Revision: https://reviews.llvm.org/D50377
Reviewed By: apilipenko

llvm-svn: 346201
  • Loading branch information
Max Kazantsev committed Nov 6, 2018
1 parent 536a5c4 commit 69f6dfa
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 29 deletions.
7 changes: 4 additions & 3 deletions llvm/include/llvm/Transforms/Utils/LoopUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ bool formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI,
/// arguments. Diagnostics is emitted via \p ORE. It returns changed status.
bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
TargetLibraryInfo *, TargetTransformInfo *, Loop *,
AliasSetTracker *, LoopSafetyInfo *,
AliasSetTracker *, ICFLoopSafetyInfo *,
OptimizationRemarkEmitter *ORE);

/// Walk the specified region of the CFG (defined by all blocks
Expand All @@ -122,7 +122,7 @@ bool sinkRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
/// ORE. It returns changed status.
bool hoistRegion(DomTreeNode *, AliasAnalysis *, LoopInfo *, DominatorTree *,
TargetLibraryInfo *, Loop *, AliasSetTracker *,
LoopSafetyInfo *, OptimizationRemarkEmitter *ORE);
ICFLoopSafetyInfo *, OptimizationRemarkEmitter *ORE);

/// This function deletes dead loops. The caller of this function needs to
/// guarantee that the loop is infact dead.
Expand Down Expand Up @@ -151,7 +151,8 @@ bool promoteLoopAccessesToScalars(const SmallSetVector<Value *, 8> &,
SmallVectorImpl<Instruction *> &,
PredIteratorCache &, LoopInfo *,
DominatorTree *, const TargetLibraryInfo *,
Loop *, AliasSetTracker *, LoopSafetyInfo *,
Loop *, AliasSetTracker *,
ICFLoopSafetyInfo *,
OptimizationRemarkEmitter *);

/// Does a BFS from a given node to all of its children inside a given loop.
Expand Down
53 changes: 33 additions & 20 deletions llvm/lib/Transforms/Scalar/LICM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ static bool isNotUsedOrFreeInLoop(const Instruction &I, const Loop *CurLoop,
const LoopSafetyInfo *SafetyInfo,
TargetTransformInfo *TTI, bool &FreeInLoop);
static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
LoopSafetyInfo *SafetyInfo,
ICFLoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE);
static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
const Loop *CurLoop, LoopSafetyInfo *SafetyInfo,
const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE, bool FreeInLoop);
static bool isSafeToExecuteUnconditionally(Instruction &Inst,
const DominatorTree *DT,
Expand All @@ -123,7 +123,8 @@ CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
const LoopInfo *LI,
const LoopSafetyInfo *SafetyInfo);

static void eraseInstruction(Instruction &I, AliasSetTracker *AST);
static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo,
AliasSetTracker *AST);

namespace {
struct LoopInvariantCodeMotion {
Expand Down Expand Up @@ -269,7 +270,7 @@ bool LoopInvariantCodeMotion::runOnLoop(
BasicBlock *Preheader = L->getLoopPreheader();

// Compute loop safety information.
SimpleLoopSafetyInfo SafetyInfo;
ICFLoopSafetyInfo SafetyInfo(DT);
SafetyInfo.computeLoopSafetyInfo(L);

// We want to visit all of the instructions in this loop... that are not parts
Expand Down Expand Up @@ -376,7 +377,7 @@ bool LoopInvariantCodeMotion::runOnLoop(
bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
DominatorTree *DT, TargetLibraryInfo *TLI,
TargetTransformInfo *TTI, Loop *CurLoop,
AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo,
AliasSetTracker *CurAST, ICFLoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE) {

// Verify inputs.
Expand Down Expand Up @@ -406,7 +407,7 @@ bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
LLVM_DEBUG(dbgs() << "LICM deleting dead inst: " << I << '\n');
salvageDebugInfo(I);
++II;
eraseInstruction(I, CurAST);
eraseInstruction(I, *SafetyInfo, CurAST);
Changed = true;
continue;
}
Expand All @@ -423,7 +424,7 @@ bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
if (sink(I, LI, DT, CurLoop, SafetyInfo, ORE, FreeInLoop)) {
if (!FreeInLoop) {
++II;
eraseInstruction(I, CurAST);
eraseInstruction(I, *SafetyInfo, CurAST);
}
Changed = true;
}
Expand All @@ -440,7 +441,7 @@ bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
///
bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
DominatorTree *DT, TargetLibraryInfo *TLI, Loop *CurLoop,
AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo,
AliasSetTracker *CurAST, ICFLoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE) {
// Verify inputs.
assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&
Expand Down Expand Up @@ -481,7 +482,7 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
CurAST->copyValue(&I, C);
I.replaceAllUsesWith(C);
if (isInstructionTriviallyDead(&I, TLI))
eraseInstruction(I, CurAST);
eraseInstruction(I, *SafetyInfo, CurAST);
Changed = true;
continue;
}
Expand Down Expand Up @@ -510,14 +511,16 @@ bool llvm::hoistRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI,
auto One = llvm::ConstantFP::get(Divisor->getType(), 1.0);
auto ReciprocalDivisor = BinaryOperator::CreateFDiv(One, Divisor);
ReciprocalDivisor->setFastMathFlags(I.getFastMathFlags());
SafetyInfo->insertInstructionTo(I.getParent());
ReciprocalDivisor->insertBefore(&I);

auto Product =
BinaryOperator::CreateFMul(I.getOperand(0), ReciprocalDivisor);
Product->setFastMathFlags(I.getFastMathFlags());
SafetyInfo->insertInstructionTo(I.getParent());
Product->insertAfter(&I);
I.replaceAllUsesWith(Product);
eraseInstruction(I, CurAST);
eraseInstruction(I, *SafetyInfo, CurAST);

hoist(*ReciprocalDivisor, DT, CurLoop, SafetyInfo, ORE);
Changed = true;
Expand Down Expand Up @@ -886,9 +889,11 @@ CloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN,
return New;
}

static void eraseInstruction(Instruction &I, AliasSetTracker *AST) {
static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo,
AliasSetTracker *AST) {
if (AST)
AST->deleteValue(&I);
SafetyInfo.removeInstruction(&I);
I.eraseFromParent();
}

Expand Down Expand Up @@ -999,7 +1004,7 @@ static void splitPredecessorsOfLoopExit(PHINode *PN, DominatorTree *DT,
/// position, and may either delete it or move it to outside of the loop.
///
static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
const Loop *CurLoop, LoopSafetyInfo *SafetyInfo,
const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE, bool FreeInLoop) {
LLVM_DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n");
ORE->emit([&]() {
Expand Down Expand Up @@ -1090,7 +1095,7 @@ static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
Instruction *New = sinkThroughTriviallyReplaceablePHI(PN, &I, LI, SunkCopies,
SafetyInfo, CurLoop);
PN->replaceAllUsesWith(New);
eraseInstruction(*PN, nullptr);
eraseInstruction(*PN, *SafetyInfo, nullptr);
Changed = true;
}
return Changed;
Expand All @@ -1100,7 +1105,7 @@ static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT,
/// is safe to hoist, this instruction is called to do the dirty work.
///
static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE) {
ICFLoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE) {
auto *Preheader = CurLoop->getLoopPreheader();
LLVM_DEBUG(dbgs() << "LICM hoisting to " << Preheader->getName() << ": " << I
<< "\n");
Expand All @@ -1120,6 +1125,8 @@ static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop,
!SafetyInfo->isGuaranteedToExecute(I, DT, CurLoop))
I.dropUnknownNonDebugMetadata();

SafetyInfo->removeInstruction(&I);
SafetyInfo->insertInstructionTo(Preheader);
// Move the new node to the Preheader, before its terminator.
I.moveBefore(Preheader->getTerminator());

Expand Down Expand Up @@ -1180,6 +1187,7 @@ class LoopPromoter : public LoadAndStorePromoter {
int Alignment;
bool UnorderedAtomic;
AAMDNodes AATags;
ICFLoopSafetyInfo &SafetyInfo;

Value *maybeInsertLCSSAPHI(Value *V, BasicBlock *BB) const {
if (Instruction *I = dyn_cast<Instruction>(V))
Expand All @@ -1202,11 +1210,13 @@ class LoopPromoter : public LoadAndStorePromoter {
SmallVectorImpl<BasicBlock *> &LEB,
SmallVectorImpl<Instruction *> &LIP, PredIteratorCache &PIC,
AliasSetTracker &ast, LoopInfo &li, DebugLoc dl, int alignment,
bool UnorderedAtomic, const AAMDNodes &AATags)
bool UnorderedAtomic, const AAMDNodes &AATags,
ICFLoopSafetyInfo &SafetyInfo)
: LoadAndStorePromoter(Insts, S), SomePtr(SP), PointerMustAliases(PMA),
LoopExitBlocks(LEB), LoopInsertPts(LIP), PredCache(PIC), AST(ast),
LI(li), DL(std::move(dl)), Alignment(alignment),
UnorderedAtomic(UnorderedAtomic), AATags(AATags) {}
UnorderedAtomic(UnorderedAtomic), AATags(AATags), SafetyInfo(SafetyInfo)
{}

bool isInstInList(Instruction *I,
const SmallVectorImpl<Instruction *> &) const override {
Expand Down Expand Up @@ -1243,7 +1253,10 @@ class LoopPromoter : public LoadAndStorePromoter {
// Update alias analysis.
AST.copyValue(LI, V);
}
void instructionDeleted(Instruction *I) const override { AST.deleteValue(I); }
void instructionDeleted(Instruction *I) const override {
SafetyInfo.removeInstruction(I);
AST.deleteValue(I);
}
};


Expand Down Expand Up @@ -1281,7 +1294,7 @@ bool llvm::promoteLoopAccessesToScalars(
SmallVectorImpl<BasicBlock *> &ExitBlocks,
SmallVectorImpl<Instruction *> &InsertPts, PredIteratorCache &PIC,
LoopInfo *LI, DominatorTree *DT, const TargetLibraryInfo *TLI,
Loop *CurLoop, AliasSetTracker *CurAST, LoopSafetyInfo *SafetyInfo,
Loop *CurLoop, AliasSetTracker *CurAST, ICFLoopSafetyInfo *SafetyInfo,
OptimizationRemarkEmitter *ORE) {
// Verify inputs.
assert(LI != nullptr && DT != nullptr && CurLoop != nullptr &&
Expand Down Expand Up @@ -1500,7 +1513,7 @@ bool llvm::promoteLoopAccessesToScalars(
SSAUpdater SSA(&NewPHIs);
LoopPromoter Promoter(SomePtr, LoopUses, SSA, PointerMustAliases, ExitBlocks,
InsertPts, PIC, *CurAST, *LI, DL, Alignment,
SawUnorderedAtomic, AATags);
SawUnorderedAtomic, AATags, *SafetyInfo);

// Set up the preheader to have a definition of the value. It is the live-out
// value from the preheader that uses in the loop will use.
Expand All @@ -1520,7 +1533,7 @@ bool llvm::promoteLoopAccessesToScalars(

// If the SSAUpdater didn't use the load in the preheader, just zap it now.
if (PreheaderLoad->use_empty())
eraseInstruction(*PreheaderLoad, CurAST);
eraseInstruction(*PreheaderLoad, *SafetyInfo, CurAST);

return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ bb1:
%tmp4 = bitcast half %tmp3 to i16
%tmp5 = insertelement <2 x i16> <i16 0, i16 undef>, i16 %tmp4, i32 1
%tmp6 = bitcast i16* %arg to half*
store half %tmp2, half* %tmp6, align 2
store volatile half %tmp2, half* %tmp6, align 2
%tmp7 = bitcast <2 x i16> %tmp to <2 x half>
%tmp8 = extractelement <2 x half> %tmp7, i32 0
br label %bb1
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/Transforms/LICM/guards.ll
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ loop:
}


; TODO: We can also hoist this load and guard from mustexec non-header block.
; TODO: We can also hoist this guard from mustexec non-header block.
define void @test4(i1 %c, i32* %p) {

; CHECK-LABEL: @test4(
; CHECK-LABEL: entry:
; CHECK-LABEL: loop:
; CHECK-LABEL: backedge:
; CHECK: %a = load i32, i32* %p
; CHECK: %invariant_cond = icmp ne i32 %a, 100
; CHECK-LABEL: loop:
; CHECK-LABEL: backedge:
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond)

entry:
Expand Down
Loading

0 comments on commit 69f6dfa

Please sign in to comment.