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 @@
#include "core/cfg.h"
#include <queue>
namespace pyston {
template <typename T> class BBAnalyzer {
......@@ -34,6 +36,13 @@ public:
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>
typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>& analyzer, bool reverse) {
assert(!reverse);
......@@ -42,20 +51,23 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>&
typedef typename BBAnalyzer<T>::AllMap AllMap;
AllMap states;
std::vector<CFGBlock*> q;
std::priority_queue<CFGBlock*, std::vector<CFGBlock*>, CFGBlockMinIndex> q;
states.insert(make_pair(cfg->getStartingBlock(), Map()));
q.push_back(cfg->getStartingBlock());
q.push(cfg->getStartingBlock());
int num_evaluations = 0;
while (q.size()) {
CFGBlock* block = q.back();
q.pop_back();
num_evaluations++;
CFGBlock* block = q.top();
q.pop();
Map initial = states[block];
if (VERBOSITY("analysis") >= 2)
printf("fpc on block %d - %ld entries\n", block->idx, initial.size());
Map ending = Map(initial);
analyzer.processBB(ending, block);
for (int i = 0; i < block->successors.size(); i++) {
......@@ -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))
continue;
......@@ -99,13 +111,18 @@ typename BBAnalyzer<T>::AllMap computeFixedPoint(CFG* cfg, const BBAnalyzer<T>&
}
if (changed)
q.push_back(next_block);
q.push(next_block);
}
states.erase(block);
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;
}
}
......
......@@ -73,6 +73,14 @@ public:
}
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) {
......
......@@ -12,22 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <cstdio>
#include <deque>
#include <unordered_set>
#include "core/options.h"
#include "analysis/type_analysis.h"
#include "analysis/fpc.h"
#include "analysis/scoping_analysis.h"
#include "codegen/type_recording.h"
#include "core/ast.h"
#include "core/cfg.h"
#include "codegen/type_recording.h"
#include "analysis/scoping_analysis.h"
#include "analysis/type_analysis.h"
#include "core/options.h"
#include "runtime/types.h"
#include <cstdio>
#include <deque>
#include <unordered_set>
//#undef VERBOSITY
//#define VERBOSITY(x) 2
......@@ -602,12 +600,16 @@ public:
}
std::unordered_set<CFGBlock*> in_queue;
std::deque<CFGBlock*> queue;
queue.push_back(cfg->getStartingBlock());
std::priority_queue<CFGBlock*, std::vector<CFGBlock*>, CFGBlockMinIndex> queue;
queue.push(cfg->getStartingBlock());
in_queue.insert(cfg->getStartingBlock());
int num_evaluations = 0;
while (queue.size()) {
CFGBlock* block = queue.front();
queue.pop_front();
ASSERT(queue.size() == in_queue.size(), "%ld %ld", queue.size(), in_queue.size());
num_evaluations++;
CFGBlock* block = queue.top();
queue.pop();
in_queue.erase(block);
TypeMap ending;
......@@ -646,11 +648,15 @@ public:
bool first = (starting_types.count(next_block) == 0);
bool changed = merge(ending, starting_types[next_block]);
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) {
for (CFGBlock* b : cfg->blocks) {
printf("Types at beginning of block %d:\n", b->idx);
......
......@@ -18,12 +18,15 @@
#include <vector>
#include <unordered_map>
//#include "ast.h"
#include "core/types.h"
#include "codegen/compvars.h"
namespace pyston {
class ScopeInfo;
class CFGBlock;
class BoxedClass;
class AST_expr;
class TypeAnalysis {
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