Commit b1927655 authored by Kevin Modzelewski's avatar Kevin Modzelewski

DefinednessAnalysis uses vectors internally now

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