Skip to content

Commit

Permalink
[NFC] Make LazyLocalGraph even lazier (#6919)
Browse files Browse the repository at this point in the history
Do not even construct the Flower helper class until we actually need it.
This avoids even scanning the function and building the internal CFG if
we never get any API call that needs it.

This speeds up LICM by 50% (as now we never construct the CFG if we
don't find a loop), and Stack IR-enabled binary writing by 10% (as many
functions do not have locals in positions that can be optimized using
LocalGraph).

This moves |locations| from the base class to LocalGraph. It is not
needed in the lazy version, so that makes sense for now (we can't keep
it in the base, as then it would need to be mutable, which only makes
sense for laziness).
  • Loading branch information
kripken authored Sep 10, 2024
1 parent 0b07c1b commit 2467e70
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 6 deletions.
15 changes: 14 additions & 1 deletion src/ir/LocalGraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,14 @@ bool LocalGraph::isSSA(Index x) { return SSAIndexes.count(x); }
// LazyLocalGraph

LazyLocalGraph::LazyLocalGraph(Function* func, Module* module)
: LocalGraphBase(func, module) {
: LocalGraphBase(func, module) {}

void LazyLocalGraph::makeFlower() const {
// Lazy graphs do not provide |locations| publicly. TODO: perhaps refactor to
// avoid filling in this dummy data structure, but we may want to add a lazy
// version of it too, so see which makes sense first.
LocalGraph::Locations locations;

flower =
std::make_unique<LocalGraphFlower>(getSetsMap, locations, func, module);

Expand All @@ -578,10 +585,16 @@ LazyLocalGraph::~LazyLocalGraph() {
}

void LazyLocalGraph::computeGetSets(LocalGet* get) const {
if (!flower) {
makeFlower();
}
flower->computeGetSets(get);
}

void LazyLocalGraph::computeSetInfluences(LocalSet* set) const {
if (!flower) {
makeFlower();
}
flower->computeSetInfluences(set, setInfluences);
}

Expand Down
17 changes: 12 additions & 5 deletions src/ir/local-graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,8 @@ struct LocalGraphBase {
// get. Typically only one or two apply there, so this is a small set.
using Sets = SmallSet<LocalSet*, 2>;

// Where each get and set is. We compute this while doing the main computation
// and make it accessible for users, for easy replacing of things without
// extra work.
// Where each get and set is.
using Locations = std::map<Expression*, Expression**>;
Locations locations;

// A map of each get to the sets relevant to it (i.e., that it can read from).
using GetSetsMap = std::unordered_map<LocalGet*, Sets>;
Expand Down Expand Up @@ -104,6 +101,11 @@ struct LocalGraph : public LocalGraphBase {
return iter->second;
}

// We compute the locations of gets and sets while doing the main computation
// and make it accessible for users, for easy replacing of things without
// extra work.
Locations locations;

// Checks if two gets are equivalent, that is, definitely have the same
// value.
bool equivalent(LocalGet* a, LocalGet* b);
Expand Down Expand Up @@ -213,7 +215,12 @@ struct LazyLocalGraph : public LocalGraphBase {
void computeSetInfluences(LocalSet* set) const;

// This remains alive as long as we are, so that we can compute things lazily.
std::unique_ptr<LocalGraphFlower> flower;
// It is mutable as when we construct this is an internal detail, that does
// not cause observable differences in API calls.
mutable std::unique_ptr<LocalGraphFlower> flower;

// We create |flower| lazily.
void makeFlower() const;
};

} // namespace wasm
Expand Down

0 comments on commit 2467e70

Please sign in to comment.