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 @@ ...@@ -18,6 +18,9 @@
#include <unordered_set> #include <unordered_set>
#include <deque> #include <deque>
#include <llvm/ADT/SetVector.h>
#include <llvm/ADT/SmallSet.h>
#include "core/common.h" #include "core/common.h"
#include "core/ast.h" #include "core/ast.h"
...@@ -32,7 +35,7 @@ namespace pyston { ...@@ -32,7 +35,7 @@ namespace pyston {
class LivenessBBVisitor : public NoopASTVisitor { class LivenessBBVisitor : public NoopASTVisitor {
public: public:
typedef std::unordered_set<std::string> StrSet; typedef llvm::SmallSet<std::string, 4> StrSet;
private: private:
StrSet _loads; StrSet _loads;
...@@ -91,10 +94,11 @@ bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) { ...@@ -91,10 +94,11 @@ bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) {
// for each query, trace forward through all possible control flow paths. // 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 store to the name, stop tracing that path
// if we hit a load to the name, return true. // 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; std::deque<CFGBlock*> q;
for (int i = 0; i < block->successors.size(); i++) { for (CFGBlock* successor : block->successors) {
q.push_back(block->successors[i]); q.push_back(successor);
} }
while (q.size()) { while (q.size()) {
...@@ -102,22 +106,29 @@ bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) { ...@@ -102,22 +106,29 @@ bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) {
q.pop_front(); q.pop_front();
if (visited.count(thisblock)) if (visited.count(thisblock))
continue; continue;
visited.insert(thisblock);
LivenessBBVisitor visitor; LivenessBBVisitor* visitor = nullptr;
for (int i = 0; i < thisblock->body.size(); i++) { LivenessCacheMap::iterator it = livenessCache.find(thisblock);
thisblock->body[i]->accept(&visitor); 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)) { if (visitor->loads().count(name)) {
assert(!visitor.stores().count(name)); assert(!visitor->stores().count(name));
return true; return true;
} }
if (!visitor.stores().count(name)) { if (!visitor->stores().count(name)) {
assert(!visitor.loads().count(name)); assert(!visitor->loads().count(name));
for (int i = 0; i < thisblock->successors.size(); i++) { for (CFGBlock* successor : thisblock->successors) {
q.push_back(thisblock->successors[i]); q.push_back(successor);
} }
} }
} }
......
...@@ -25,10 +25,15 @@ class AST_Jump; ...@@ -25,10 +25,15 @@ class AST_Jump;
class CFG; class CFG;
class CFGBlock; class CFGBlock;
class ScopeInfo; class ScopeInfo;
class LivenessBBVisitor;
class LivenessAnalysis { class LivenessAnalysis {
public: public:
bool isLiveAtEnd(const std::string& name, CFGBlock* block); bool isLiveAtEnd(const std::string& name, CFGBlock* block);
private:
typedef std::unordered_map<CFGBlock*, std::unique_ptr<LivenessBBVisitor> > LivenessCacheMap;
LivenessCacheMap livenessCache;
}; };
class DefinednessAnalysis { class DefinednessAnalysis {
public: 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