Commit 8052061e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Change analysis APIs to take vregs

parent 18c6b30c
......@@ -415,11 +415,10 @@ void DefinednessAnalysis::run(VRegMap<DefinednessAnalysis::DefinitionLevel> init
us_definedness.log(_t.end());
}
DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(InternedString name, CFGBlock* block) {
DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(int vreg, CFGBlock* block) {
assert(defined_at_end.count(block));
auto&& map = defined_at_end.find(block)->second;
auto cfg = block->cfg;
return map[cfg->getVRegInfo().getVReg(name)];
return map[vreg];
}
const VRegSet& DefinednessAnalysis::getDefinedVregsAtEnd(CFGBlock* block) {
......@@ -488,40 +487,30 @@ const VRegSet& PhiAnalysis::getAllRequiredFor(CFGBlock* block) {
return required_phis.find(block)->second;
}
// TODO: switch this to taking a vreg
bool PhiAnalysis::isRequired(InternedString name, CFGBlock* block) {
assert(!startswith(name.s(), "!"));
bool PhiAnalysis::isRequired(int vreg, CFGBlock* block) {
assert(required_phis.count(block));
return required_phis.find(block)->second[block->cfg->getVRegInfo().getVReg(name)];
return required_phis.find(block)->second[vreg];
}
bool PhiAnalysis::isRequiredAfter(InternedString name, CFGBlock* block) {
assert(!startswith(name.s(), "!"));
bool PhiAnalysis::isRequiredAfter(int vreg, CFGBlock* block) {
// If there are multiple successors, then none of them are allowed
// to require any phi nodes
if (block->successors.size() != 1)
return false;
// Fall back to the other method:
return isRequired(name, block->successors[0]);
return isRequired(vreg, block->successors[0]);
}
bool PhiAnalysis::isPotentiallyUndefinedAfter(InternedString name, CFGBlock* block) {
assert(!startswith(name.s(), "!"));
bool PhiAnalysis::isPotentiallyUndefinedAfter(int vreg, CFGBlock* block) {
for (auto b : block->successors) {
if (isPotentiallyUndefinedAt(name, b))
if (isPotentiallyUndefinedAt(vreg, b))
return true;
}
return false;
}
bool PhiAnalysis::isPotentiallyUndefinedAt(InternedString name, CFGBlock* block) {
assert(!startswith(name.s(), "!"));
auto cfg = block->cfg;
int vreg = cfg->getVRegInfo().getVReg(name);
bool PhiAnalysis::isPotentiallyUndefinedAt(int vreg, CFGBlock* block) {
assert(definedness.defined_at_beginning.count(block));
return definedness.defined_at_beginning.find(block)->second[vreg] != DefinednessAnalysis::Defined;
}
......
......@@ -163,7 +163,7 @@ public:
void run(VRegMap<DefinitionLevel> initial_map, CFGBlock* initial_block, ScopeInfo* scope_info);
DefinitionLevel isDefinedAtEnd(InternedString name, CFGBlock* block);
DefinitionLevel isDefinedAtEnd(int vreg, CFGBlock* block);
const VRegSet& getDefinedVregsAtEnd(CFGBlock* block);
friend class PhiAnalysis;
......@@ -186,15 +186,15 @@ public:
bool initials_need_phis, LivenessAnalysis* liveness, ScopeInfo* scope_info);
// TODO: convert these to taking vregs
bool isRequired(InternedString name, CFGBlock* block);
bool isRequiredAfter(InternedString name, CFGBlock* block);
bool isRequired(int vreg, CFGBlock* block);
bool isRequiredAfter(int vreg, CFGBlock* block);
const VRegSet& getAllRequiredAfter(CFGBlock* block);
const VRegSet& getAllRequiredFor(CFGBlock* block);
// TODO: convert these to taking vregs
// If "name" may be undefined at the beginning of any immediate successor block of "block":
bool isPotentiallyUndefinedAfter(InternedString name, CFGBlock* block);
bool isPotentiallyUndefinedAfter(int vreg, CFGBlock* block);
// If "name" may be undefined at the beginning of "block"
bool isPotentiallyUndefinedAt(InternedString name, CFGBlock* block);
bool isPotentiallyUndefinedAt(int vreg, CFGBlock* block);
};
std::unique_ptr<LivenessAnalysis> computeLivenessInfo(CFG*);
......
......@@ -40,20 +40,20 @@ namespace pyston {
class NullTypeAnalysis : public TypeAnalysis {
public:
ConcreteCompilerType* getTypeAtBlockStart(InternedString name, CFGBlock* block) override;
ConcreteCompilerType* getTypeAtBlockEnd(InternedString name, CFGBlock* block) override;
ConcreteCompilerType* getTypeAtBlockStart(int vreg, CFGBlock* block) override;
ConcreteCompilerType* getTypeAtBlockEnd(int vreg, CFGBlock* block) override;
BoxedClass* speculatedExprClass(AST_expr*) override { return NULL; }
BoxedClass* speculatedExprClass(AST_slice*) override { return NULL; }
};
ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockStart(InternedString name, CFGBlock* block) {
ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockStart(int vreg, CFGBlock* block) {
return UNKNOWN;
}
ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockEnd(InternedString name, CFGBlock* block) {
ConcreteCompilerType* NullTypeAnalysis::getTypeAtBlockEnd(int vreg, CFGBlock* block) {
assert(block->successors.size() > 0);
return getTypeAtBlockStart(name, block->successors[0]);
return getTypeAtBlockStart(vreg, block->successors[0]);
}
......@@ -695,19 +695,17 @@ private:
speculation(speculation) {}
public:
ConcreteCompilerType* getTypeAtBlockEnd(InternedString name, CFGBlock* block) override {
ConcreteCompilerType* getTypeAtBlockEnd(int vreg, CFGBlock* block) override {
assert(block->successors.size() > 0);
return getTypeAtBlockStart(name, block->successors[0]);
return getTypeAtBlockStart(vreg, block->successors[0]);
}
ConcreteCompilerType* getTypeAtBlockStart(InternedString name, CFGBlock* block) override {
int vreg = block->cfg->getVRegInfo().getVReg(name);
ConcreteCompilerType* getTypeAtBlockStart(int vreg, CFGBlock* block) override {
assert(starting_types.count(block));
CompilerType* base = starting_types.find(block)->second[vreg];
ASSERT(base != NULL, "%s %d", name.c_str(), block->idx);
ASSERT(base != NULL, "%s %d", block->cfg->getVRegInfo().getName(vreg).c_str(), block->idx);
ConcreteCompilerType* rtn = base->getConcreteType();
ASSERT(rtn != NULL, "%s %d", name.c_str(), block->idx);
ASSERT(rtn != NULL, "%s %d", block->cfg->getVRegInfo().getName(vreg).c_str(), block->idx);
return rtn;
}
......
......@@ -39,8 +39,8 @@ public:
virtual ~TypeAnalysis() {}
virtual ConcreteCompilerType* getTypeAtBlockStart(InternedString name, CFGBlock* block) = 0;
virtual ConcreteCompilerType* getTypeAtBlockEnd(InternedString name, CFGBlock* block) = 0;
virtual ConcreteCompilerType* getTypeAtBlockStart(int vreg, CFGBlock* block) = 0;
virtual ConcreteCompilerType* getTypeAtBlockEnd(int vreg, CFGBlock* block) = 0;
virtual BoxedClass* speculatedExprClass(AST_expr*) = 0;
virtual BoxedClass* speculatedExprClass(AST_slice*) = 0;
};
......
......@@ -722,7 +722,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
for (auto&& sym : getSymVRegMap()) {
if (!liveness->isLiveAtEnd(sym.second, current_block)) {
dead_vregs.push_back(sym.second);
} else if (phis->isRequiredAfter(sym.first, current_block)) {
} else if (phis->isRequiredAfter(sym.second, current_block)) {
assert(scope_info->getScopeTypeOfName(sym.first) != ScopeInfo::VarScopeType::GLOBAL);
} else {
}
......@@ -753,7 +753,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
InternedString name = source_info->cfg->getVRegInfo().getName(vreg);
Box* val = vregs[vreg];
if (phis->isPotentiallyUndefinedAfter(name, current_block)) {
if (phis->isPotentiallyUndefinedAfter(vreg, current_block)) {
bool is_defined = val != NULL;
// TODO only mangle once
sorted_symbol_table[getIsDefinedName(name, source_info->getInternedStrings())] = (Box*)is_defined;
......
......@@ -286,7 +286,8 @@ static std::vector<std::pair<CFGBlock*, CFGBlock*>> computeBlockTraversalOrder(c
return rtn;
}
static ConcreteCompilerType* getTypeAtBlockStart(TypeAnalysis* types, InternedString name, CFGBlock* block) {
static ConcreteCompilerType* getTypeAtBlockStart(TypeAnalysis* types, InternedString name, const VRegInfo& vreg_info,
CFGBlock* block) {
if (isIsDefinedName(name))
return BOOL;
else if (name.s() == PASSED_GENERATOR_NAME)
......@@ -295,8 +296,11 @@ static ConcreteCompilerType* getTypeAtBlockStart(TypeAnalysis* types, InternedSt
return CLOSURE;
else if (name.s() == CREATED_CLOSURE_NAME)
return CLOSURE;
else
return types->getTypeAtBlockStart(name, block);
else {
// This could crash if we call getTypeAtBlockStart on something that doesn't have a type or vreg.
// Luckily it looks like we don't do that.
return types->getTypeAtBlockStart(vreg_info.getVReg(name), block);
}
}
static bool shouldPhisOwnThisSym(llvm::StringRef name) {
......@@ -362,6 +366,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
assert(phi_analysis);
CFG* cfg = source->cfg;
auto&& vreg_info = cfg->getVRegInfo();
if (entry_descriptor != NULL)
assert(blocks.count(cfg->getStartingBlock()) == 0);
......@@ -456,7 +461,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
}
ConcreteCompilerType* phi_type;
phi_type = getTypeAtBlockStart(types, p.first, target_block);
phi_type = getTypeAtBlockStart(types, p.first, vreg_info, target_block);
irstate->getRefcounts()->setType(from_arg, RefType::BORROWED);
......@@ -625,7 +630,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
if (p.first.s() == FRAME_INFO_PTR_NAME)
continue;
ConcreteCompilerType* analyzed_type = getTypeAtBlockStart(types, p.first, block);
ConcreteCompilerType* analyzed_type = getTypeAtBlockStart(types, p.first, vreg_info, block);
// printf("For %s, given %s, analyzed for %s\n", p.first.c_str(), p.second->debugName().c_str(),
// analyzed_type->debugName().c_str());
......@@ -655,7 +660,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
for (const int vreg : phi_analysis->getAllRequiredFor(block)) {
auto s = cfg->getVRegInfo().getName(vreg);
names.insert(s);
if (phi_analysis->isPotentiallyUndefinedAfter(s, block->predecessors[0])) {
if (phi_analysis->isPotentiallyUndefinedAfter(vreg, block->predecessors[0])) {
names.insert(getIsDefinedName(s, source->getInternedStrings()));
}
}
......@@ -673,7 +678,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
for (const InternedString& s : names) {
// printf("adding guessed phi for %s\n", s.c_str());
ConcreteCompilerType* type = getTypeAtBlockStart(types, s, block);
ConcreteCompilerType* type = getTypeAtBlockStart(types, s, vreg_info, block);
llvm::PHINode* phi
= emitter->getBuilder()->CreatePHI(type->llvmType(), block->predecessors.size(), s.s());
if (type->getBoxType() == type) {
......
......@@ -2657,12 +2657,13 @@ private:
// ASSERT(p.first[0] != '!' || isIsDefinedName(p.first), "left a fake variable in the real
// symbol table? '%s'", p.first.c_str());
if (!irstate->getLiveness()->isLiveAtEnd(cfg->getVRegInfo().getVReg(p.first), myblock)) {
int vreg = cfg->getVRegInfo().getVReg(p.first);
if (!irstate->getLiveness()->isLiveAtEnd(vreg, myblock)) {
symbol_table.erase(getIsDefinedName(p.first));
symbol_table.erase(p.first);
} else if (irstate->getPhis()->isRequiredAfter(p.first, myblock)) {
} else if (irstate->getPhis()->isRequiredAfter(vreg, myblock)) {
assert(scope_info->getScopeTypeOfName(p.first) != ScopeInfo::VarScopeType::GLOBAL);
ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(p.first, myblock);
ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(vreg, myblock);
assert(phi_type->isUsable());
// printf("Converting %s from %s to %s\n", p.first.c_str(),
// p.second->getType()->debugName().c_str(), phi_type->debugName().c_str());
......@@ -2675,7 +2676,7 @@ private:
// TODO getTypeAtBlockEnd will automatically convert up to the concrete type, which we don't
// want
// here, but this is just for debugging so I guess let it happen for now:
ConcreteCompilerType* ending_type = types->getTypeAtBlockEnd(p.first, myblock);
ConcreteCompilerType* ending_type = types->getTypeAtBlockEnd(vreg, myblock);
RELEASE_ASSERT(p.second->canConvertTo(ending_type), "%s is supposed to be %s, but somehow is %s",
p.first.c_str(), ending_type->debugName().c_str(),
p.second->getType()->debugName().c_str());
......@@ -2685,13 +2686,12 @@ private:
for (int vreg : irstate->getPhis()->getAllRequiredAfter(myblock)) {
auto name = irstate->getCFG()->getVRegInfo().getName(vreg);
auto it = &name; // hack, remove
if (VERBOSITY() >= 3)
printf("phi will be required for %s\n", it->c_str());
assert(scope_info->getScopeTypeOfName(*it) != ScopeInfo::VarScopeType::GLOBAL);
CompilerVariable*& cur = symbol_table[*it];
printf("phi will be required for %s\n", name.c_str());
assert(scope_info->getScopeTypeOfName(name) != ScopeInfo::VarScopeType::GLOBAL);
CompilerVariable*& cur = symbol_table[name];
InternedString defined_name = getIsDefinedName(*it);
InternedString defined_name = getIsDefinedName(name);
if (cur != NULL) {
// printf("defined on this path; ");
......@@ -2699,7 +2699,7 @@ private:
ConcreteCompilerVariable* is_defined
= static_cast<ConcreteCompilerVariable*>(_popFake(defined_name, true));
if (irstate->getPhis()->isPotentiallyUndefinedAfter(*it, myblock)) {
if (irstate->getPhis()->isPotentiallyUndefinedAfter(vreg, myblock)) {
// printf("is potentially undefined later, so marking it defined\n");
if (is_defined) {
_setFake(defined_name, is_defined);
......@@ -2712,7 +2712,7 @@ private:
}
} else {
// printf("no st entry, setting undefined\n");
ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(*it, myblock);
ConcreteCompilerType* phi_type = types->getTypeAtBlockEnd(vreg, myblock);
assert(phi_type->isUsable());
// Forward an incref'd None instead of a NULL.
......@@ -2769,6 +2769,9 @@ public:
SymbolTable* st = new SymbolTable(symbol_table);
ConcreteSymbolTable* phi_st = new ConcreteSymbolTable();
auto cfg = source->cfg;
auto&& vreg_info = cfg->getVRegInfo();
// This should have been consumed:
assert(incoming_exc_state.empty());
......@@ -2799,7 +2802,8 @@ public:
// We have one successor, but they have more than one predecessor.
// We're going to sort out which symbols need to go in phi_st and which belong inst.
for (SymbolTable::iterator it = st->begin(); it != st->end();) {
if (allowableFakeEndingSymbol(it->first) || irstate->getPhis()->isRequiredAfter(it->first, myblock)) {
if (allowableFakeEndingSymbol(it->first)
|| irstate->getPhis()->isRequiredAfter(cfg->getVRegInfo().getVReg(it->first), myblock)) {
// this conversion should have already happened... should refactor this.
ConcreteCompilerType* ending_type;
if (isIsDefinedName(it->first.s())) {
......@@ -2814,7 +2818,7 @@ public:
} else if (it->first.s() == FRAME_INFO_PTR_NAME) {
ending_type = FRAME_INFO;
} else {
ending_type = types->getTypeAtBlockEnd(it->first, myblock);
ending_type = types->getTypeAtBlockEnd(vreg_info.getVReg(it->first), myblock);
}
assert(ending_type->isUsable());
//(*phi_st)[it->first] = it->second->makeConverted(emitter, it->second->getConcreteType());
......
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