summaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/LoopLoadElimination.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
commiteb11fae6d08f479c0799db45860a98af528fa6e7 (patch)
tree44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Transforms/Scalar/LoopLoadElimination.cpp
parentb8a2042aa938069e862750553db0e4d82d25822c (diff)
Notes
Diffstat (limited to 'lib/Transforms/Scalar/LoopLoadElimination.cpp')
-rw-r--r--lib/Transforms/Scalar/LoopLoadElimination.cpp82
1 files changed, 44 insertions, 38 deletions
diff --git a/lib/Transforms/Scalar/LoopLoadElimination.cpp b/lib/Transforms/Scalar/LoopLoadElimination.cpp
index dfa5ec1f354d..19bd9ebcc15b 100644
--- a/lib/Transforms/Scalar/LoopLoadElimination.cpp
+++ b/lib/Transforms/Scalar/LoopLoadElimination.cpp
@@ -25,7 +25,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
@@ -52,6 +52,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils.h"
#include "llvm/Transforms/Utils/LoopVersioning.h"
#include <algorithm>
#include <cassert>
@@ -79,7 +80,7 @@ STATISTIC(NumLoopLoadEliminted, "Number of loads eliminated by LLE");
namespace {
-/// \brief Represent a store-to-forwarding candidate.
+/// Represent a store-to-forwarding candidate.
struct StoreToLoadForwardingCandidate {
LoadInst *Load;
StoreInst *Store;
@@ -87,7 +88,7 @@ struct StoreToLoadForwardingCandidate {
StoreToLoadForwardingCandidate(LoadInst *Load, StoreInst *Store)
: Load(Load), Store(Store) {}
- /// \brief Return true if the dependence from the store to the load has a
+ /// Return true if the dependence from the store to the load has a
/// distance of one. E.g. A[i+1] = A[i]
bool isDependenceDistanceOfOne(PredicatedScalarEvolution &PSE,
Loop *L) const {
@@ -136,7 +137,7 @@ struct StoreToLoadForwardingCandidate {
} // end anonymous namespace
-/// \brief Check if the store dominates all latches, so as long as there is no
+/// Check if the store dominates all latches, so as long as there is no
/// intervening store this value will be loaded in the next iteration.
static bool doesStoreDominatesAllLatches(BasicBlock *StoreBlock, Loop *L,
DominatorTree *DT) {
@@ -147,21 +148,21 @@ static bool doesStoreDominatesAllLatches(BasicBlock *StoreBlock, Loop *L,
});
}
-/// \brief Return true if the load is not executed on all paths in the loop.
+/// Return true if the load is not executed on all paths in the loop.
static bool isLoadConditional(LoadInst *Load, Loop *L) {
return Load->getParent() != L->getHeader();
}
namespace {
-/// \brief The per-loop class that does most of the work.
+/// The per-loop class that does most of the work.
class LoadEliminationForLoop {
public:
LoadEliminationForLoop(Loop *L, LoopInfo *LI, const LoopAccessInfo &LAI,
DominatorTree *DT)
: L(L), LI(LI), LAI(LAI), DT(DT), PSE(LAI.getPSE()) {}
- /// \brief Look through the loop-carried and loop-independent dependences in
+ /// Look through the loop-carried and loop-independent dependences in
/// this loop and find store->load dependences.
///
/// Note that no candidate is returned if LAA has failed to analyze the loop
@@ -178,7 +179,7 @@ public:
// forward and backward dependences qualify. Disqualify loads that have
// other unknown dependences.
- SmallSet<Instruction *, 4> LoadsWithUnknownDepedence;
+ SmallPtrSet<Instruction *, 4> LoadsWithUnknownDepedence;
for (const auto &Dep : *Deps) {
Instruction *Source = Dep.getSource(LAI);
@@ -222,14 +223,14 @@ public:
return Candidates;
}
- /// \brief Return the index of the instruction according to program order.
+ /// Return the index of the instruction according to program order.
unsigned getInstrIndex(Instruction *Inst) {
auto I = InstOrder.find(Inst);
assert(I != InstOrder.end() && "No index for instruction");
return I->second;
}
- /// \brief If a load has multiple candidates associated (i.e. different
+ /// If a load has multiple candidates associated (i.e. different
/// stores), it means that it could be forwarding from multiple stores
/// depending on control flow. Remove these candidates.
///
@@ -284,22 +285,24 @@ public:
Candidates.remove_if([&](const StoreToLoadForwardingCandidate &Cand) {
if (LoadToSingleCand[Cand.Load] != &Cand) {
- DEBUG(dbgs() << "Removing from candidates: \n" << Cand
- << " The load may have multiple stores forwarding to "
- << "it\n");
+ LLVM_DEBUG(
+ dbgs() << "Removing from candidates: \n"
+ << Cand
+ << " The load may have multiple stores forwarding to "
+ << "it\n");
return true;
}
return false;
});
}
- /// \brief Given two pointers operations by their RuntimePointerChecking
+ /// Given two pointers operations by their RuntimePointerChecking
/// indices, return true if they require an alias check.
///
/// We need a check if one is a pointer for a candidate load and the other is
/// a pointer for a possibly intervening store.
bool needsChecking(unsigned PtrIdx1, unsigned PtrIdx2,
- const SmallSet<Value *, 4> &PtrsWrittenOnFwdingPath,
+ const SmallPtrSet<Value *, 4> &PtrsWrittenOnFwdingPath,
const std::set<Value *> &CandLoadPtrs) {
Value *Ptr1 =
LAI.getRuntimePointerChecking()->getPointerInfo(PtrIdx1).PointerValue;
@@ -309,11 +312,11 @@ public:
(PtrsWrittenOnFwdingPath.count(Ptr2) && CandLoadPtrs.count(Ptr1)));
}
- /// \brief Return pointers that are possibly written to on the path from a
+ /// Return pointers that are possibly written to on the path from a
/// forwarding store to a load.
///
/// These pointers need to be alias-checked against the forwarding candidates.
- SmallSet<Value *, 4> findPointersWrittenOnForwardingPath(
+ SmallPtrSet<Value *, 4> findPointersWrittenOnForwardingPath(
const SmallVectorImpl<StoreToLoadForwardingCandidate> &Candidates) {
// From FirstStore to LastLoad neither of the elimination candidate loads
// should overlap with any of the stores.
@@ -351,7 +354,7 @@ public:
// We're looking for stores after the first forwarding store until the end
// of the loop, then from the beginning of the loop until the last
// forwarded-to load. Collect the pointer for the stores.
- SmallSet<Value *, 4> PtrsWrittenOnFwdingPath;
+ SmallPtrSet<Value *, 4> PtrsWrittenOnFwdingPath;
auto InsertStorePtr = [&](Instruction *I) {
if (auto *S = dyn_cast<StoreInst>(I))
@@ -366,16 +369,16 @@ public:
return PtrsWrittenOnFwdingPath;
}
- /// \brief Determine the pointer alias checks to prove that there are no
+ /// Determine the pointer alias checks to prove that there are no
/// intervening stores.
SmallVector<RuntimePointerChecking::PointerCheck, 4> collectMemchecks(
const SmallVectorImpl<StoreToLoadForwardingCandidate> &Candidates) {
- SmallSet<Value *, 4> PtrsWrittenOnFwdingPath =
+ SmallPtrSet<Value *, 4> PtrsWrittenOnFwdingPath =
findPointersWrittenOnForwardingPath(Candidates);
// Collect the pointers of the candidate loads.
- // FIXME: SmallSet does not work with std::inserter.
+ // FIXME: SmallPtrSet does not work with std::inserter.
std::set<Value *> CandLoadPtrs;
transform(Candidates,
std::inserter(CandLoadPtrs, CandLoadPtrs.begin()),
@@ -394,13 +397,14 @@ public:
return false;
});
- DEBUG(dbgs() << "\nPointer Checks (count: " << Checks.size() << "):\n");
- DEBUG(LAI.getRuntimePointerChecking()->printChecks(dbgs(), Checks));
+ LLVM_DEBUG(dbgs() << "\nPointer Checks (count: " << Checks.size()
+ << "):\n");
+ LLVM_DEBUG(LAI.getRuntimePointerChecking()->printChecks(dbgs(), Checks));
return Checks;
}
- /// \brief Perform the transformation for a candidate.
+ /// Perform the transformation for a candidate.
void
propagateStoredValueToLoadUsers(const StoreToLoadForwardingCandidate &Cand,
SCEVExpander &SEE) {
@@ -436,11 +440,11 @@ public:
Cand.Load->replaceAllUsesWith(PHI);
}
- /// \brief Top-level driver for each loop: find store->load forwarding
+ /// Top-level driver for each loop: find store->load forwarding
/// candidates, add run-time checks and perform transformation.
bool processLoop() {
- DEBUG(dbgs() << "\nIn \"" << L->getHeader()->getParent()->getName()
- << "\" checking " << *L << "\n");
+ LLVM_DEBUG(dbgs() << "\nIn \"" << L->getHeader()->getParent()->getName()
+ << "\" checking " << *L << "\n");
// Look for store-to-load forwarding cases across the
// backedge. E.g.:
@@ -479,7 +483,7 @@ public:
SmallVector<StoreToLoadForwardingCandidate, 4> Candidates;
unsigned NumForwarding = 0;
for (const StoreToLoadForwardingCandidate Cand : StoreToLoadDependences) {
- DEBUG(dbgs() << "Candidate " << Cand);
+ LLVM_DEBUG(dbgs() << "Candidate " << Cand);
// Make sure that the stored values is available everywhere in the loop in
// the next iteration.
@@ -498,9 +502,10 @@ public:
continue;
++NumForwarding;
- DEBUG(dbgs()
- << NumForwarding
- << ". Valid store-to-load forwarding across the loop backedge\n");
+ LLVM_DEBUG(
+ dbgs()
+ << NumForwarding
+ << ". Valid store-to-load forwarding across the loop backedge\n");
Candidates.push_back(Cand);
}
if (Candidates.empty())
@@ -513,25 +518,26 @@ public:
// Too many checks are likely to outweigh the benefits of forwarding.
if (Checks.size() > Candidates.size() * CheckPerElim) {
- DEBUG(dbgs() << "Too many run-time checks needed.\n");
+ LLVM_DEBUG(dbgs() << "Too many run-time checks needed.\n");
return false;
}
if (LAI.getPSE().getUnionPredicate().getComplexity() >
LoadElimSCEVCheckThreshold) {
- DEBUG(dbgs() << "Too many SCEV run-time checks needed.\n");
+ LLVM_DEBUG(dbgs() << "Too many SCEV run-time checks needed.\n");
return false;
}
if (!Checks.empty() || !LAI.getPSE().getUnionPredicate().isAlwaysTrue()) {
if (L->getHeader()->getParent()->optForSize()) {
- DEBUG(dbgs() << "Versioning is needed but not allowed when optimizing "
- "for size.\n");
+ LLVM_DEBUG(
+ dbgs() << "Versioning is needed but not allowed when optimizing "
+ "for size.\n");
return false;
}
if (!L->isLoopSimplifyForm()) {
- DEBUG(dbgs() << "Loop is not is loop-simplify form");
+ LLVM_DEBUG(dbgs() << "Loop is not is loop-simplify form");
return false;
}
@@ -558,7 +564,7 @@ public:
private:
Loop *L;
- /// \brief Maps the load/store instructions to their index according to
+ /// Maps the load/store instructions to their index according to
/// program order.
DenseMap<Instruction *, unsigned> InstOrder;
@@ -599,7 +605,7 @@ eliminateLoadsAcrossLoops(Function &F, LoopInfo &LI, DominatorTree &DT,
namespace {
-/// \brief The pass. Most of the work is delegated to the per-loop
+/// The pass. Most of the work is delegated to the per-loop
/// LoadEliminationForLoop class.
class LoopLoadElimination : public FunctionPass {
public: