Commit b1927655 authored by Kevin Modzelewski's avatar Kevin Modzelewski

DefinednessAnalysis uses vectors internally now

parent 742dc66c
......@@ -337,7 +337,7 @@ STDOBJECT_SRCS := \
iterobject.c \
bufferobject.c \
cobject.c \
dictproxy.c \
descrobject.c \
$(EXTRA_STDOBJECT_SRCS)
STDPYTHON_SRCS := \
......
......@@ -21,6 +21,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "analysis/function_analysis.h"
#include "core/cfg.h"
#include "core/common.h"
#include "core/options.h"
......@@ -29,7 +30,7 @@ namespace pyston {
template <typename T> class BBAnalyzer {
public:
typedef llvm::DenseMap<InternedString, T> Map;
typedef VRegMap<T> Map;
typedef llvm::DenseMap<CFGBlock*, Map> AllMap;
virtual ~BBAnalyzer() {}
......@@ -56,10 +57,12 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
assert(!starting_states.size());
assert(!ending_states.size());
int num_vregs = initial_map.numVregs();
llvm::SmallPtrSet<CFGBlock*, 32> in_queue;
std::priority_queue<CFGBlock*, llvm::SmallVector<CFGBlock*, 32>, CFGBlockMinIndex> q;
starting_states.insert(make_pair(initial_block, std::move(initial_map)));
starting_states.insert(std::make_pair(initial_block, std::move(initial_map)));
q.push(initial_block);
in_queue.insert(initial_block);
......@@ -70,9 +73,10 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
q.pop();
in_queue.erase(block);
Map& initial = starting_states[block];
assert(starting_states.count(block));
Map& initial = starting_states.find(block)->second;
if (VERBOSITY("analysis") >= 2)
printf("fpc on block %d - %d entries\n", block->idx, initial.size());
printf("fpc on block %d - %d entries\n", block->idx, initial.numVregs());
Map ending = Map(initial);
......@@ -87,20 +91,17 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
initial = true;
}
Map& next = starting_states[next_block];
auto it = starting_states.find(next_block);
if (it == starting_states.end())
it = starting_states.insert(std::make_pair(next_block, Map(num_vregs))).first;
Map& next = it->second;
// merge ending->next
for (const auto& p : ending) {
bool existed = next.count(p.first);
T& next_elt = next[p.first];
T new_elt = analyzer.merge(p.second, next_elt);
if (!existed) {
assert(new_elt != next_elt);
if (initial)
assert(new_elt == p.second);
}
if (next_elt != new_elt) {
next_elt = new_elt;
changed = true;
......@@ -108,10 +109,7 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
}
#ifndef NDEBUG
for (const auto& p : next) {
assert(ending.count(p.first));
}
assert(next.size() == ending.size());
assert(next.numVregs() == ending.numVregs());
#endif
if (changed && in_queue.insert(next_block).second) {
......@@ -119,7 +117,8 @@ void computeFixedPoint(typename BBAnalyzer<T>::Map&& initial_map, CFGBlock* init
}
}
ending_states[block] = std::move(ending);
ending_states.erase(block);
ending_states.insert(std::make_pair(block, std::move(ending)));
}
if (VERBOSITY("analysis")) {
......
......@@ -243,9 +243,9 @@ private:
typedef DefinednessBBAnalyzer::Map Map;
Map& state;
void _doSet(InternedString s) {
ASSERT(state.count(s), "%s", s.c_str());
state[s] = DefinednessAnalysis::Defined;
void _doSet(int vreg) {
assert(vreg >= 0 && vreg < state.numVregs());
state[vreg] = DefinednessAnalysis::Defined;
}
void _doSet(AST* t) {
......@@ -258,12 +258,10 @@ private:
if (name->lookup_type == ScopeInfo::VarScopeType::FAST
|| name->lookup_type == ScopeInfo::VarScopeType::CLOSURE) {
assert(name->vreg != -1);
assert(state.count(name->id));
_doSet(name->id);
_doSet(name->vreg);
} else if (name->lookup_type == ScopeInfo::VarScopeType::GLOBAL
|| name->lookup_type == ScopeInfo::VarScopeType::NAME) {
assert(name->vreg == -1);
assert(!state.count(name->id));
// skip
} else {
RELEASE_ASSERT(0, "%d", name->lookup_type);
......@@ -304,8 +302,8 @@ public:
AST_Name* name = ast_cast<AST_Name>(t);
if (name->lookup_type != ScopeInfo::VarScopeType::GLOBAL
&& name->lookup_type != ScopeInfo::VarScopeType::NAME) {
ASSERT(state.count(name->id), "%s", name->id.c_str());
state[name->id] = DefinednessAnalysis::Undefined;
assert(name->vreg != -1);
state[name->vreg] = DefinednessAnalysis::Undefined;
}
} else {
// The CFG pass should reduce all deletes to the "basic" deletes on names/attributes/subscripts.
......@@ -318,21 +316,23 @@ public:
}
virtual bool visit_classdef(AST_ClassDef* node) {
_doSet(node->name);
assert(0 && "I think this isn't needed");
//_doSet(node->name);
return true;
}
virtual bool visit_functiondef(AST_FunctionDef* node) {
_doSet(node->name);
assert(0 && "I think this isn't needed");
//_doSet(node->name);
return true;
}
virtual bool visit_alias(AST_alias* node) {
InternedString name = node->name;
int vreg = node->name_vreg;
if (node->asname.s().size())
name = node->asname;
vreg = node->asname_vreg;
_doSet(name);
_doSet(vreg);
return true;
}
virtual bool visit_import(AST_Import* node) { return false; }
......@@ -347,9 +347,9 @@ public:
virtual bool visit_arguments(AST_arguments* node) {
if (node->kwarg.s().size())
_doSet(node->kwarg);
_doSet(node->kwarg_vreg);
if (node->vararg.s().size())
_doSet(node->vararg);
_doSet(node->vararg_vreg);
for (int i = 0; i < node->args.size(); i++) {
_doSet(node->args[i]);
}
......@@ -371,7 +371,8 @@ void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
if (VERBOSITY("analysis") >= 3) {
printf("At end of block %d:\n", block->idx);
for (const auto& p : starting) {
printf("%s: %d\n", p.first.c_str(), p.second);
if (p.second != DefinednessAnalysis::Undefined)
printf("%s: %d\n", block->cfg->getVRegInfo().getName(p.first).c_str(), p.second);
}
}
}
......@@ -388,33 +389,33 @@ void DefinednessAnalysis::run(llvm::DenseMap<InternedString, DefinednessAnalysis
auto&& vreg_info = cfg->getVRegInfo();
int nvregs = vreg_info.getTotalNumOfVRegs();
ASSERT(nvregs == initial_map.size(), "%d %d", nvregs, initial_map.size());
VRegMap<DefinednessAnalysis::DefinitionLevel> real_initial_map(nvregs);
for (auto&& p : initial_map) {
// Run it through getVReg to make sure that the vreg exists
ASSERT(vreg_info.getVReg(p.first) >= 0, "%s", p.first.c_str());
real_initial_map[vreg_info.getVReg(p.first)] = p.second;
}
computeFixedPoint(std::move(initial_map), initial_block, DefinednessBBAnalyzer(scope_info), false,
computeFixedPoint(std::move(real_initial_map), initial_block, DefinednessBBAnalyzer(scope_info), false,
defined_at_beginning, defined_at_end);
for (const auto& p : defined_at_end) {
assert(p.second.size() == nvregs);
assert(p.second.numVregs() == nvregs);
assert(!defined_at_end_sets.count(p.first));
RequiredSet& required = defined_at_end_sets.insert(std::make_pair(p.first, RequiredSet(nvregs))).first->second;
//required.resize(nvregs, /* value= */ false);
// required.resize(nvregs, /* value= */ false);
for (int vreg = 0; vreg < nvregs; vreg++) {
// TODO shouldn't have to use name at all
InternedString name = vreg_info.getName(vreg);
#ifndef NDEBUG
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(name);
assert(vst != ScopeInfo::VarScopeType::GLOBAL && vst != ScopeInfo::VarScopeType::NAME);
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(vreg_info.getName(vreg));
ASSERT(vst != ScopeInfo::VarScopeType::GLOBAL && vst != ScopeInfo::VarScopeType::NAME, "%s",
vreg_info.getName(vreg).c_str());
#endif
assert(p.second.count(name));
auto status = p.second.find(name)->second;
auto status = p.second[vreg];
// assert(p.second.count(name));
// auto status = p.second.find(name)->second;
assert(status != DefinednessAnalysis::Unknown);
if (status != DefinednessAnalysis::Undefined)
required.set(vreg);
......@@ -427,10 +428,9 @@ void DefinednessAnalysis::run(llvm::DenseMap<InternedString, DefinednessAnalysis
DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(InternedString name, CFGBlock* block) {
assert(defined_at_end.count(block));
auto& map = defined_at_end[block];
if (map.count(name) == 0)
return Undefined;
return map[name];
auto&& map = defined_at_end.find(block)->second;
auto cfg = block->cfg;
return map[cfg->getVRegInfo().getVReg(name)];
}
const DefinednessAnalysis::RequiredSet& DefinednessAnalysis::getDefinedNamesAtEnd(CFGBlock* block) {
......@@ -528,8 +528,11 @@ bool PhiAnalysis::isPotentiallyUndefinedAfter(InternedString name, CFGBlock* blo
bool PhiAnalysis::isPotentiallyUndefinedAt(InternedString name, CFGBlock* block) {
assert(!startswith(name.s(), "!"));
auto cfg = block->cfg;
int vreg = cfg->getVRegInfo().getVReg(name);
assert(definedness.defined_at_beginning.count(block));
return definedness.defined_at_beginning[block][name] != DefinednessAnalysis::Defined;
return definedness.defined_at_beginning.find(block)->second[vreg] != DefinednessAnalysis::Defined;
}
std::unique_ptr<LivenessAnalysis> computeLivenessInfo(CFG* cfg) {
......
......@@ -81,9 +81,7 @@ public:
bool operator==(const iterator& rhs) const { return i == rhs.i; }
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
int operator*() {
return i;
}
int operator*() { return i; }
};
iterator begin() const {
......@@ -94,9 +92,49 @@ public:
return iterator(*this, this->v.size());
}
iterator end() const {
return iterator(*this, this->v.size());
iterator end() const { return iterator(*this, this->v.size()); }
};
template <typename T> class VRegMap {
private:
// TODO: switch just to a T*
std::vector<T> v;
public:
VRegMap(int num_vregs) : v(num_vregs) {}
T& operator[](int vreg) {
assert(vreg >= 0 && vreg < v.size());
return v[vreg];
}
const T& operator[](int vreg) const {
assert(vreg >= 0 && vreg < v.size());
return v[vreg];
}
class iterator {
public:
const VRegMap<T>& map;
int i;
iterator(const VRegMap<T>& map, int i) : map(map), i(i) {}
iterator& operator++() {
i++;
return *this;
}
bool operator==(const iterator& rhs) const { return i == rhs.i; }
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
std::pair<int, const T&> operator*() { return std::pair<int, const T&>(i, map[i]); }
};
int numVregs() const { return v.size(); }
iterator begin() const { return iterator(*this, 0); }
iterator end() const { return iterator(*this, this->v.size()); }
};
class DefinednessAnalysis {
......@@ -110,7 +148,7 @@ public:
typedef VRegSet RequiredSet;
private:
llvm::DenseMap<CFGBlock*, llvm::DenseMap<InternedString, DefinitionLevel>> defined_at_beginning, defined_at_end;
llvm::DenseMap<CFGBlock*, VRegMap<DefinitionLevel>> defined_at_beginning, defined_at_end;
llvm::DenseMap<CFGBlock*, RequiredSet> defined_at_end_sets;
public:
......
......@@ -217,6 +217,7 @@ public:
class AST_alias : public AST {
public:
InternedString name, asname;
int name_vreg = -1, asname_vreg = -1;
virtual void accept(ASTVisitor* v);
......@@ -233,6 +234,7 @@ public:
// These are represented as strings, not names; not sure why.
// If they don't exist, the string is empty.
InternedString kwarg, vararg;
int kwarg_vreg = -1, vararg_vreg = -1;
virtual void accept(ASTVisitor* v);
......
......@@ -1613,7 +1613,6 @@ public:
auto tmp = nodeName();
pushAssign(tmp, new AST_MakeClass(def));
// is this name mangling correct?
pushAssign(source->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, 0, true));
return true;
......@@ -1635,7 +1634,6 @@ public:
auto tmp = nodeName();
pushAssign(tmp, new AST_MakeFunction(def));
// is this name mangling correct?
pushAssign(source->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, node->col_offset, true));
return true;
......@@ -2687,9 +2685,21 @@ public:
AssignVRegsVisitor(ScopeInfo* scope_info) : scope_info(scope_info), current_block(0), next_vreg(0) {}
bool visit_alias(AST_alias* node) override {
if (node->asname.s().size())
node->asname_vreg = assignVReg(node->asname);
else
node->name_vreg = assignVReg(node->name);
return true;
}
bool visit_arguments(AST_arguments* node) override {
for (AST_expr* d : node->defaults)
d->accept(this);
if (node->kwarg.s().size())
node->kwarg_vreg = assignVReg(node->kwarg);
if (node->vararg.s().size())
node->vararg_vreg = assignVReg(node->vararg);
return true;
}
......@@ -2749,6 +2759,8 @@ public:
}
int assignVReg(InternedString id) {
assert(id.s().size());
auto it = sym_vreg_map.find(id);
if (sym_vreg_map.end() == it) {
ASSERT(next_vreg == sym_vreg_map.size(), "%d %d", next_vreg, sym_vreg_map.size());
......
# Some corner cases around name scopes
def f1():
exec ""
from os import path as os_path
print os_path.join("a", "b")
f1()
def f2():
exec ""
def f3(*args, **kw):
exec ""
print args, kw
f3(*[1, 2], **dict(a=1, b=2))
f2()
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