Commit 0004d9cc authored by Marius Wachtler's avatar Marius Wachtler

LivenessAnalysis: Cache BB liveness info to improve performance

Brings down runtime of gcj_2014_1c_b.py from 2secs to 0.7
parent 96cc5efa
......@@ -18,6 +18,9 @@
#include <unordered_set>
#include <deque>
#include <llvm/ADT/SetVector.h>
#include <llvm/ADT/SmallSet.h>
#include "core/common.h"
#include "core/ast.h"
......@@ -32,7 +35,7 @@ namespace pyston {
class LivenessBBVisitor : public NoopASTVisitor {
public:
typedef std::unordered_set<std::string> StrSet;
typedef llvm::SmallSet<std::string, 4> StrSet;
private:
StrSet _loads;
......@@ -91,10 +94,11 @@ bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) {
// for each query, trace forward through all possible control flow paths.
// if we hit a store to the name, stop tracing that path
// if we hit a load to the name, return true.
std::unordered_set<CFGBlock*> visited;
// to improve performance we cache the liveness result of every visited BB.
llvm::SmallPtrSet<CFGBlock*, 1> visited;
std::deque<CFGBlock*> q;
for (int i = 0; i < block->successors.size(); i++) {
q.push_back(block->successors[i]);
for (CFGBlock* successor : block->successors) {
q.push_back(successor);
}
while (q.size()) {
......@@ -102,22 +106,29 @@ bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) {
q.pop_front();
if (visited.count(thisblock))
continue;
visited.insert(thisblock);
LivenessBBVisitor visitor;
for (int i = 0; i < thisblock->body.size(); i++) {
thisblock->body[i]->accept(&visitor);
LivenessBBVisitor* visitor = nullptr;
LivenessCacheMap::iterator it = livenessCache.find(thisblock);
if (it != livenessCache.end()) {
visitor = it->second.get();
} else {
visitor = new LivenessBBVisitor; // livenessCache unique_ptr will delete it.
for (AST_stmt* stmt : thisblock->body) {
stmt->accept(visitor);
}
livenessCache.insert(std::make_pair(thisblock, std::unique_ptr<LivenessBBVisitor>(visitor)));
}
visited.insert(thisblock);
if (visitor.loads().count(name)) {
assert(!visitor.stores().count(name));
if (visitor->loads().count(name)) {
assert(!visitor->stores().count(name));
return true;
}
if (!visitor.stores().count(name)) {
assert(!visitor.loads().count(name));
for (int i = 0; i < thisblock->successors.size(); i++) {
q.push_back(thisblock->successors[i]);
if (!visitor->stores().count(name)) {
assert(!visitor->loads().count(name));
for (CFGBlock* successor : thisblock->successors) {
q.push_back(successor);
}
}
}
......
......@@ -25,10 +25,15 @@ class AST_Jump;
class CFG;
class CFGBlock;
class ScopeInfo;
class LivenessBBVisitor;
class LivenessAnalysis {
public:
bool isLiveAtEnd(const std::string& name, CFGBlock* block);
private:
typedef std::unordered_map<CFGBlock*, std::unique_ptr<LivenessBBVisitor> > LivenessCacheMap;
LivenessCacheMap livenessCache;
};
class DefinednessAnalysis {
public:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment