Commit 3691c258 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Improve the speed of some static analyses

Before was using some bad iteration strategies for
fixed-point computation: LIFO for definedness analysis
(very bad), and FIFO for type analysis (bad).

Switch both of them to use a priority queue that picks the
block with the lowest index; this is an order of magnitude
better on the new gcj test but still is fairly slow.
parent 9a79b92c
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#include "core/cfg.h" #include "core/cfg.h"
#include <queue>
namespace pyston { namespace pyston {
template <typename T> class BBAnalyzer { template <typename T> class BBAnalyzer {
...@@ -34,6 +36,13 @@ public: ...@@ -34,6 +36,13 @@ public:
virtual void processBB(Map& starting, CFGBlock* block) const = 0; virtual void processBB(Map& starting, CFGBlock* block) const = 0;
}; };
class CFGBlockMinIndex {
public:
bool operator()(const CFGBlock* lhs, const CFGBlock* rhs) {
return lhs->idx > rhs->idx;
}
};
template <typename T> template <typename T>
typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>& analyzer, bool reverse) { typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>& analyzer, bool reverse) {
assert(!reverse); assert(!reverse);
...@@ -42,20 +51,23 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>& ...@@ -42,20 +51,23 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>&
typedef typename BBAnalyzer<T>::AllMap AllMap; typedef typename BBAnalyzer<T>::AllMap AllMap;
AllMap states; AllMap states;
std::vector<CFGBlock*> q; std::priority_queue<CFGBlock*, std::vector<CFGBlock*>, CFGBlockMinIndex> q;
states.insert(make_pair(cfg->getStartingBlock(), Map())); states.insert(make_pair(cfg->getStartingBlock(), Map()));
q.push_back(cfg->getStartingBlock()); q.push(cfg->getStartingBlock());
int num_evaluations = 0;
while (q.size()) { while (q.size()) {
CFGBlock* block = q.back(); num_evaluations++;
q.pop_back(); CFGBlock* block = q.top();
q.pop();
Map initial = states[block]; Map initial = states[block];
if (VERBOSITY("analysis") >= 2) if (VERBOSITY("analysis") >= 2)
printf("fpc on block %d - %ld entries\n", block->idx, initial.size()); printf("fpc on block %d - %ld entries\n", block->idx, initial.size());
Map ending = Map(initial); Map ending = Map(initial);
analyzer.processBB(ending, block); analyzer.processBB(ending, block);
for (int i = 0; i < block->successors.size(); i++) { for (int i = 0; i < block->successors.size(); i++) {
...@@ -87,7 +99,7 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>& ...@@ -87,7 +99,7 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>&
} }
} }
for (const auto& p : ending) { for (const auto& p : next) {
if (ending.count(p.first)) if (ending.count(p.first))
continue; continue;
...@@ -99,13 +111,18 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>& ...@@ -99,13 +111,18 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>&
} }
if (changed) if (changed)
q.push_back(next_block); q.push(next_block);
} }
states.erase(block); states.erase(block);
states.insert(make_pair(block, ending)); states.insert(make_pair(block, ending));
} }
if (VERBOSITY("analysis")) {
printf("%ld BBs, %d evaluations = %.1f evaluations/block\n", cfg->blocks.size(), num_evaluations, 1.0 * num_evaluations / cfg->blocks.size());
}
return states; return states;
} }
} }
......
...@@ -73,6 +73,14 @@ public: ...@@ -73,6 +73,14 @@ public:
} }
return true; return true;
} }
bool visit_alias(AST_alias* node) {
const std::string* name = &node->name;
if (node->asname.size())
name = &node->asname;
_doStore(*name);
return true;
}
}; };
bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) { bool LivenessAnalysis::isLiveAtEnd(const std::string& name, CFGBlock* block) {
......
...@@ -12,22 +12,20 @@ ...@@ -12,22 +12,20 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#include <cstdio> #include "analysis/type_analysis.h"
#include <deque>
#include <unordered_set>
#include "core/options.h"
#include "analysis/fpc.h"
#include "analysis/scoping_analysis.h"
#include "codegen/type_recording.h"
#include "core/ast.h" #include "core/ast.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "core/options.h"
#include "codegen/type_recording.h"
#include "analysis/scoping_analysis.h"
#include "analysis/type_analysis.h"
#include "runtime/types.h" #include "runtime/types.h"
#include <cstdio>
#include <deque>
#include <unordered_set>
//#undef VERBOSITY //#undef VERBOSITY
//#define VERBOSITY(x) 2 //#define VERBOSITY(x) 2
...@@ -602,12 +600,16 @@ public: ...@@ -602,12 +600,16 @@ public:
} }
std::unordered_set<CFGBlock*> in_queue; std::unordered_set<CFGBlock*> in_queue;
std::deque<CFGBlock*> queue; std::priority_queue<CFGBlock*, std::vector<CFGBlock*>, CFGBlockMinIndex> queue;
queue.push_back(cfg->getStartingBlock()); queue.push(cfg->getStartingBlock());
in_queue.insert(cfg->getStartingBlock());
int num_evaluations = 0;
while (queue.size()) { while (queue.size()) {
CFGBlock* block = queue.front(); ASSERT(queue.size() == in_queue.size(), "%ld %ld", queue.size(), in_queue.size());
queue.pop_front(); num_evaluations++;
CFGBlock* block = queue.top();
queue.pop();
in_queue.erase(block); in_queue.erase(block);
TypeMap ending; TypeMap ending;
...@@ -646,11 +648,15 @@ public: ...@@ -646,11 +648,15 @@ public:
bool first = (starting_types.count(next_block) == 0); bool first = (starting_types.count(next_block) == 0);
bool changed = merge(ending, starting_types[next_block]); bool changed = merge(ending, starting_types[next_block]);
if ((first || changed) && in_queue.insert(next_block).second) { if ((first || changed) && in_queue.insert(next_block).second) {
queue.push_back(next_block); queue.push(next_block);
} }
} }
} }
if (VERBOSITY("types")) {
printf("%ld BBs, %d evaluations = %.1f evaluations/block\n", cfg->blocks.size(), num_evaluations, 1.0 * num_evaluations / cfg->blocks.size());
}
if (VERBOSITY("types") >= 2) { if (VERBOSITY("types") >= 2) {
for (CFGBlock* b : cfg->blocks) { for (CFGBlock* b : cfg->blocks) {
printf("Types at beginning of block %d:\n", b->idx); printf("Types at beginning of block %d:\n", b->idx);
......
...@@ -18,12 +18,15 @@ ...@@ -18,12 +18,15 @@
#include <vector> #include <vector>
#include <unordered_map> #include <unordered_map>
//#include "ast.h" #include "core/types.h"
#include "codegen/compvars.h" #include "codegen/compvars.h"
namespace pyston { namespace pyston {
class ScopeInfo; class ScopeInfo;
class CFGBlock;
class BoxedClass;
class AST_expr;
class TypeAnalysis { class TypeAnalysis {
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