Skip to content

Commit

Permalink
[MemorySSA] Teach LoopSimplify to preserve MemorySSA.
Browse files Browse the repository at this point in the history
Summary:
Preserve MemorySSA in LoopSimplify, in the old pass manager, if the analysis is available.
Do not preserve it in the new pass manager.
Update tests.

Subscribers: nemanjai, jlebar, javed.absar, Prazek, kbarton, zzheng, jsji, llvm-commits, george.burgess.iv, chandlerc

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D60833

llvm-svn: 360270
  • Loading branch information
alinas committed May 8, 2019
1 parent 9f15718 commit f31eba6
Show file tree
Hide file tree
Showing 18 changed files with 228 additions and 60 deletions.
7 changes: 5 additions & 2 deletions llvm/include/llvm/Analysis/LoopInfo.h
Expand Up @@ -55,6 +55,7 @@ class DominatorTree;
class LoopInfo;
class Loop;
class MDNode;
class MemorySSAUpdater;
class PHINode;
class raw_ostream;
template <class N, bool IsPostDom> class DominatorTreeBase;
Expand Down Expand Up @@ -498,7 +499,8 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// If InsertPt is specified, it is the point to hoist instructions to.
/// If null, the terminator of the loop preheader is used.
bool makeLoopInvariant(Value *V, bool &Changed,
Instruction *InsertPt = nullptr) const;
Instruction *InsertPt = nullptr,
MemorySSAUpdater *MSSAU = nullptr) const;

/// If the given instruction is inside of the loop and it can be hoisted, do
/// so to make it trivially loop-invariant.
Expand All @@ -510,7 +512,8 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// If null, the terminator of the loop preheader is used.
///
bool makeLoopInvariant(Instruction *I, bool &Changed,
Instruction *InsertPt = nullptr) const;
Instruction *InsertPt = nullptr,
MemorySSAUpdater *MSSAU = nullptr) const;

/// Check to see if the loop has a canonical induction variable: an integer
/// recurrence that starts at 0 and increments by one each time through the
Expand Down
17 changes: 16 additions & 1 deletion llvm/include/llvm/Analysis/MemorySSAUpdater.h
Expand Up @@ -105,7 +105,12 @@ class MemorySSAUpdater {
/// Update the MemoryPhi in `To` to have a single incoming edge from `From`,
/// following a CFG change that replaced multiple edges (switch) with a direct
/// branch.
void removeDuplicatePhiEdgesBetween(BasicBlock *From, BasicBlock *To);
void removeDuplicatePhiEdgesBetween(const BasicBlock *From,
const BasicBlock *To);
/// Update MemorySSA when inserting a unique backedge block for a loop.
void updatePhisWhenInsertingUniqueBackedgeBlock(BasicBlock *LoopHeader,
BasicBlock *LoopPreheader,
BasicBlock *BackedgeBlock);
/// Update MemorySSA after a loop was cloned, given the blocks in RPO order,
/// the exit blocks and a 1:1 mapping of all blocks and instructions
/// cloned. This involves duplicating all defs and uses in the cloned blocks
Expand Down Expand Up @@ -240,6 +245,16 @@ class MemorySSAUpdater {
/// deleted after this call.
void removeBlocks(const SmallPtrSetImpl<BasicBlock *> &DeadBlocks);

/// Instruction I will be changed to an unreachable. Remove all accesses in
/// I's block that follow I (inclusive), and update the Phis in the blocks'
/// successors.
void changeToUnreachable(const Instruction *I);

/// Conditional branch BI is changed or replaced with an unconditional branch
/// to `To`. Update Phis in BI's successors to remove BI's BB.
void changeCondBranchToUnconditionalTo(const BranchInst *BI,
const BasicBlock *To);

/// Get handle on MemorySSA.
MemorySSA* getMemorySSA() const { return MSSA; }

Expand Down
6 changes: 4 additions & 2 deletions llvm/include/llvm/Transforms/Utils/Local.h
Expand Up @@ -231,7 +231,8 @@ bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = nullptr);
/// If this basic block is ONLY a setcc and a branch, and if a predecessor
/// branches to us and one of our successors, fold the setcc into the
/// predecessor and use logical operations to pick the right destination.
bool FoldBranchToCommonDest(BranchInst *BI, unsigned BonusInstThreshold = 1);
bool FoldBranchToCommonDest(BranchInst *BI, MemorySSAUpdater *MSSAU = nullptr,
unsigned BonusInstThreshold = 1);

/// This function takes a virtual register computed by an Instruction and
/// replaces it with a slot in the stack frame, allocated via alloca.
Expand Down Expand Up @@ -381,7 +382,8 @@ unsigned removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB);
/// instruction, making it and the rest of the code in the block dead.
unsigned changeToUnreachable(Instruction *I, bool UseLLVMTrap,
bool PreserveLCSSA = false,
DomTreeUpdater *DTU = nullptr);
DomTreeUpdater *DTU = nullptr,
MemorySSAUpdater *MSSAU = nullptr);

/// Convert the CallInst to InvokeInst with the specified unwind edge basic
/// block. This also splits the basic block where CI is located, because
Expand Down
8 changes: 6 additions & 2 deletions llvm/include/llvm/Transforms/Utils/LoopSimplify.h
Expand Up @@ -45,6 +45,8 @@

namespace llvm {

class MemorySSAUpdater;

/// This pass is responsible for loop canonicalization.
class LoopSimplifyPass : public PassInfoMixin<LoopSimplifyPass> {
public:
Expand All @@ -55,9 +57,11 @@ class LoopSimplifyPass : public PassInfoMixin<LoopSimplifyPass> {
///
/// This takes a potentially un-simplified loop L (and its children) and turns
/// it into a simplified loop nest with preheaders and single backedges. It will
/// update \c AliasAnalysis and \c ScalarEvolution analyses if they're non-null.
/// update \c DominatorTree, \c LoopInfo, \c ScalarEvolution and \c MemorySSA
/// analyses if they're non-null, and LCSSA if \c PreserveLCSSA is true.
bool simplifyLoop(Loop *L, DominatorTree *DT, LoopInfo *LI, ScalarEvolution *SE,
AssumptionCache *AC, bool PreserveLCSSA);
AssumptionCache *AC, MemorySSAUpdater *MSSAU,
bool PreserveLCSSA);

} // end namespace llvm

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Transforms/Utils/LoopUtils.h
Expand Up @@ -51,7 +51,7 @@ class TargetLibraryInfo;
class TargetTransformInfo;

BasicBlock *InsertPreheaderForLoop(Loop *L, DominatorTree *DT, LoopInfo *LI,
bool PreserveLCSSA);
MemorySSAUpdater *MSSAU, bool PreserveLCSSA);

/// Ensure that all exit blocks of the loop are dedicated exits.
///
Expand Down
16 changes: 11 additions & 5 deletions llvm/lib/Analysis/LoopInfo.cpp
Expand Up @@ -19,6 +19,8 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfoImpl.h"
#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/MemorySSA.h"
#include "llvm/Analysis/MemorySSAUpdater.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/CFG.h"
Expand Down Expand Up @@ -64,15 +66,16 @@ bool Loop::hasLoopInvariantOperands(const Instruction *I) const {
return all_of(I->operands(), [this](Value *V) { return isLoopInvariant(V); });
}

bool Loop::makeLoopInvariant(Value *V, bool &Changed,
Instruction *InsertPt) const {
bool Loop::makeLoopInvariant(Value *V, bool &Changed, Instruction *InsertPt,
MemorySSAUpdater *MSSAU) const {
if (Instruction *I = dyn_cast<Instruction>(V))
return makeLoopInvariant(I, Changed, InsertPt);
return makeLoopInvariant(I, Changed, InsertPt, MSSAU);
return true; // All non-instructions are loop-invariant.
}

bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
Instruction *InsertPt) const {
Instruction *InsertPt,
MemorySSAUpdater *MSSAU) const {
// Test if the value is already loop-invariant.
if (isLoopInvariant(I))
return true;
Expand All @@ -93,11 +96,14 @@ bool Loop::makeLoopInvariant(Instruction *I, bool &Changed,
}
// Don't hoist instructions with loop-variant operands.
for (Value *Operand : I->operands())
if (!makeLoopInvariant(Operand, Changed, InsertPt))
if (!makeLoopInvariant(Operand, Changed, InsertPt, MSSAU))
return false;

// Hoist.
I->moveBefore(InsertPt);
if (MSSAU)
if (auto *MUD = MSSAU->getMemorySSA()->getMemoryAccess(I))
MSSAU->moveToPlace(MUD, InsertPt->getParent(), MemorySSA::End);

// There is possibility of hoisting this instruction above some arbitrary
// condition. Any metadata defined on it can be control dependent on this
Expand Down
81 changes: 79 additions & 2 deletions llvm/lib/Analysis/MemorySSAUpdater.cpp
Expand Up @@ -463,8 +463,8 @@ void MemorySSAUpdater::removeEdge(BasicBlock *From, BasicBlock *To) {
}
}

void MemorySSAUpdater::removeDuplicatePhiEdgesBetween(BasicBlock *From,
BasicBlock *To) {
void MemorySSAUpdater::removeDuplicatePhiEdgesBetween(const BasicBlock *From,
const BasicBlock *To) {
if (MemoryPhi *MPhi = MSSA->getMemoryAccess(To)) {
bool Found = false;
MPhi->unorderedDeleteIncomingIf([&](const MemoryAccess *, BasicBlock *B) {
Expand Down Expand Up @@ -522,6 +522,46 @@ void MemorySSAUpdater::cloneUsesAndDefs(BasicBlock *BB, BasicBlock *NewBB,
}
}

void MemorySSAUpdater::updatePhisWhenInsertingUniqueBackedgeBlock(
BasicBlock *Header, BasicBlock *Preheader, BasicBlock *BEBlock) {
auto *MPhi = MSSA->getMemoryAccess(Header);
if (!MPhi)
return;

// Create phi node in the backedge block and populate it with the same
// incoming values as MPhi. Skip incoming values coming from Preheader.
auto *NewMPhi = MSSA->createMemoryPhi(BEBlock);
bool HasUniqueIncomingValue = true;
MemoryAccess *UniqueValue = nullptr;
for (unsigned I = 0, E = MPhi->getNumIncomingValues(); I != E; ++I) {
BasicBlock *IBB = MPhi->getIncomingBlock(I);
MemoryAccess *IV = MPhi->getIncomingValue(I);
if (IBB != Preheader) {
NewMPhi->addIncoming(IV, IBB);
if (HasUniqueIncomingValue) {
if (!UniqueValue)
UniqueValue = IV;
else if (UniqueValue != IV)
HasUniqueIncomingValue = false;
}
}
}

// Update incoming edges into MPhi. Remove all but the incoming edge from
// Preheader. Add an edge from NewMPhi
auto *AccFromPreheader = MPhi->getIncomingValueForBlock(Preheader);
MPhi->setIncomingValue(0, AccFromPreheader);
MPhi->setIncomingBlock(0, Preheader);
for (unsigned I = MPhi->getNumIncomingValues() - 1; I >= 1; --I)
MPhi->unorderedDeleteIncoming(I);
MPhi->addIncoming(NewMPhi, BEBlock);

// If NewMPhi is a trivial phi, remove it. Its use in the header MPhi will be
// replaced with the unique value.
if (HasUniqueIncomingValue)
removeMemoryAccess(NewMPhi);
}

void MemorySSAUpdater::updateForClonedLoop(const LoopBlocksRPO &LoopBlocks,
ArrayRef<BasicBlock *> ExitBlocks,
const ValueToValueMapTy &VMap,
Expand Down Expand Up @@ -1223,6 +1263,43 @@ void MemorySSAUpdater::tryRemoveTrivialPhis(ArrayRef<WeakVH> UpdatedPHIs) {
}
}

void MemorySSAUpdater::changeToUnreachable(const Instruction *I) {
const BasicBlock *BB = I->getParent();
// Remove memory accesses in BB for I and all following instructions.
auto BBI = I->getIterator(), BBE = BB->end();
// FIXME: If this becomes too expensive, iterate until the first instruction
// with a memory access, then iterate over MemoryAccesses.
while (BBI != BBE)
removeMemoryAccess(&*(BBI++));
// Update phis in BB's successors to remove BB.
SmallVector<WeakVH, 16> UpdatedPHIs;
for (const BasicBlock *Successor : successors(BB)) {
removeDuplicatePhiEdgesBetween(BB, Successor);
if (MemoryPhi *MPhi = MSSA->getMemoryAccess(Successor)) {
MPhi->unorderedDeleteIncomingBlock(BB);
UpdatedPHIs.push_back(MPhi);
}
}
// Optimize trivial phis.
tryRemoveTrivialPhis(UpdatedPHIs);
}

void MemorySSAUpdater::changeCondBranchToUnconditionalTo(const BranchInst *BI,
const BasicBlock *To) {
const BasicBlock *BB = BI->getParent();
SmallVector<WeakVH, 16> UpdatedPHIs;
for (const BasicBlock *Succ : successors(BB)) {
removeDuplicatePhiEdgesBetween(BB, Succ);
if (Succ != To)
if (auto *MPhi = MSSA->getMemoryAccess(Succ)) {
MPhi->unorderedDeleteIncomingBlock(BB);
UpdatedPHIs.push_back(MPhi);
}
}
// Optimize trivial phis.
tryRemoveTrivialPhis(UpdatedPHIs);
}

MemoryAccess *MemorySSAUpdater::createMemoryAccessInBB(
Instruction *I, MemoryAccess *Definition, const BasicBlock *BB,
MemorySSA::InsertionPlace Point) {
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/PowerPC/PPCCTRLoops.cpp
Expand Up @@ -631,7 +631,7 @@ bool PPCCTRLoops::convertToCTRLoop(Loop *L) {
// the CTR register because some such uses might be reordered by the
// selection DAG after the mtctr instruction).
if (!Preheader || mightUseCTR(Preheader))
Preheader = InsertPreheaderForLoop(L, DT, LI, PreserveLCSSA);
Preheader = InsertPreheaderForLoop(L, DT, LI, nullptr, PreserveLCSSA);
if (!Preheader)
return MadeChange;

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/PowerPC/PPCLoopPreIncPrep.cpp
Expand Up @@ -331,7 +331,7 @@ bool PPCLoopPreIncPrep::runOnLoop(Loop *L) {
// iteration space), insert a new preheader for the loop.
if (!LoopPredecessor ||
!LoopPredecessor->getTerminator()->getType()->isVoidTy()) {
LoopPredecessor = InsertPreheaderForLoop(L, DT, LI, PreserveLCSSA);
LoopPredecessor = InsertPreheaderForLoop(L, DT, LI, nullptr, PreserveLCSSA);
if (LoopPredecessor)
MadeChange = true;
}
Expand Down
Expand Up @@ -1545,7 +1545,7 @@ bool LoopConstrainer::run() {
// This function canonicalizes the loop into Loop-Simplify and LCSSA forms.
auto CanonicalizeLoop = [&] (Loop *L, bool IsOriginalLoop) {
formLCSSARecursively(*L, DT, &LI, &SE);
simplifyLoop(L, &DT, &LI, &SE, nullptr, true);
simplifyLoop(L, &DT, &LI, &SE, nullptr, nullptr, true);
// Pre/post loops are slow paths, we do not need to perform any loop
// optimizations on them.
if (!IsOriginalLoop)
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/Transforms/Scalar/LoopInterchange.cpp
Expand Up @@ -1362,9 +1362,11 @@ bool LoopInterchangeTransform::adjustLoopBranches() {
// preheaders do not satisfy those conditions.
if (isa<PHINode>(OuterLoopPreHeader->begin()) ||
!OuterLoopPreHeader->getUniquePredecessor())
OuterLoopPreHeader = InsertPreheaderForLoop(OuterLoop, DT, LI, true);
OuterLoopPreHeader =
InsertPreheaderForLoop(OuterLoop, DT, LI, nullptr, true);
if (InnerLoopPreHeader == OuterLoop->getHeader())
InnerLoopPreHeader = InsertPreheaderForLoop(InnerLoop, DT, LI, true);
InnerLoopPreHeader =
InsertPreheaderForLoop(InnerLoop, DT, LI, nullptr, true);

// Adjust the loop preheader
BasicBlock *InnerLoopHeader = InnerLoop->getHeader();
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
Expand Up @@ -1393,7 +1393,8 @@ PreservedAnalyses LoopUnrollPass::run(Function &F,
// will simplify all loops, regardless of whether anything end up being
// unrolled.
for (auto &L : LI) {
Changed |= simplifyLoop(L, &DT, &LI, &SE, &AC, false /* PreserveLCSSA */);
Changed |=
simplifyLoop(L, &DT, &LI, &SE, &AC, nullptr, false /* PreserveLCSSA */);
Changed |= formLCSSARecursively(*L, DT, &LI, &SE);
}

Expand Down
6 changes: 5 additions & 1 deletion llvm/lib/Transforms/Utils/Local.cpp
Expand Up @@ -1894,10 +1894,14 @@ unsigned llvm::removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB) {
}

unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap,
bool PreserveLCSSA, DomTreeUpdater *DTU) {
bool PreserveLCSSA, DomTreeUpdater *DTU,
MemorySSAUpdater *MSSAU) {
BasicBlock *BB = I->getParent();
std::vector <DominatorTree::UpdateType> Updates;

if (MSSAU)
MSSAU->changeToUnreachable(I);

// Loop over all of the successors, removing BB's entry from any PHI
// nodes.
if (DTU)
Expand Down

0 comments on commit f31eba6

Please sign in to comment.