Commit 9f17a19e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Switch PhiAnalysis to use VRegSets

parent 84b05dab
...@@ -378,32 +378,26 @@ void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const { ...@@ -378,32 +378,26 @@ void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
} }
} }
void DefinednessAnalysis::run(llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map, void DefinednessAnalysis::run(VRegMap<DefinednessAnalysis::DefinitionLevel> initial_map, CFGBlock* initial_block,
CFGBlock* initial_block, ScopeInfo* scope_info) { ScopeInfo* scope_info) {
Timer _t("DefinednessAnalysis()", 10); Timer _t("DefinednessAnalysis()", 10);
// Don't run this twice: // Don't run this twice:
assert(!defined_at_end.size()); assert(!defined_at_end.size());
auto cfg = initial_block->cfg; auto cfg = initial_block->cfg;
int nvregs = cfg->getVRegInfo().getTotalNumOfVRegs();
assert(initial_map.numVregs() == nvregs);
auto&& vreg_info = cfg->getVRegInfo(); auto&& vreg_info = cfg->getVRegInfo();
int nvregs = vreg_info.getTotalNumOfVRegs(); computeFixedPoint(std::move(initial_map), initial_block, DefinednessBBAnalyzer(scope_info), false,
ASSERT(nvregs == initial_map.size(), "%d %d", nvregs, initial_map.size());
VRegMap<DefinednessAnalysis::DefinitionLevel> real_initial_map(nvregs);
for (auto&& p : initial_map) {
real_initial_map[vreg_info.getVReg(p.first)] = p.second;
}
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.numVregs() == 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; VRegSet& required = defined_at_end_sets.insert(std::make_pair(p.first, VRegSet(nvregs))).first->second;
// required.resize(nvregs, /* value= */ false); // required.resize(nvregs, /* value= */ false);
...@@ -434,15 +428,14 @@ DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(Interne ...@@ -434,15 +428,14 @@ DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(Interne
return map[cfg->getVRegInfo().getVReg(name)]; return map[cfg->getVRegInfo().getVReg(name)];
} }
const DefinednessAnalysis::RequiredSet& DefinednessAnalysis::getDefinedNamesAtEnd(CFGBlock* block) { const VRegSet& DefinednessAnalysis::getDefinedVregsAtEnd(CFGBlock* block) {
assert(defined_at_end_sets.count(block)); assert(defined_at_end_sets.count(block));
return defined_at_end_sets.find(block)->second; return defined_at_end_sets.find(block)->second;
} }
PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map, PhiAnalysis::PhiAnalysis(VRegMap<DefinednessAnalysis::DefinitionLevel> initial_map, CFGBlock* initial_block,
CFGBlock* initial_block, bool initials_need_phis, LivenessAnalysis* liveness, bool initials_need_phis, LivenessAnalysis* liveness, ScopeInfo* scope_info)
ScopeInfo* scope_info) : definedness(), empty_set(initial_map.numVregs()), liveness(liveness) {
: definedness(), liveness(liveness) {
auto cfg = initial_block->cfg; auto cfg = initial_block->cfg;
auto&& vreg_info = cfg->getVRegInfo(); auto&& vreg_info = cfg->getVRegInfo();
...@@ -450,13 +443,17 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def ...@@ -450,13 +443,17 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
// then we should include the initial arguments as an extra entry point. // then we should include the initial arguments as an extra entry point.
assert(initials_need_phis == (initial_block->predecessors.size() > 0)); assert(initials_need_phis == (initial_block->predecessors.size() > 0));
int num_vregs = initial_map.numVregs();
assert(num_vregs == vreg_info.getTotalNumOfVRegs());
definedness.run(std::move(initial_map), initial_block, scope_info); definedness.run(std::move(initial_map), initial_block, scope_info);
Timer _t("PhiAnalysis()", 10); Timer _t("PhiAnalysis()", 10);
for (const auto& p : definedness.defined_at_end) { for (const auto& p : definedness.defined_at_end) {
CFGBlock* block = p.first; CFGBlock* block = p.first;
RequiredSet& required = required_phis[block]; assert(!required_phis.count(block));
VRegSet& required = required_phis.insert(std::make_pair(block, VRegSet(num_vregs))).first->second;
int npred = 0; int npred = 0;
for (CFGBlock* pred : block->predecessors) { for (CFGBlock* pred : block->predecessors) {
...@@ -469,13 +466,13 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def ...@@ -469,13 +466,13 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
if (!definedness.defined_at_end.count(pred)) if (!definedness.defined_at_end.count(pred))
continue; continue;
const VRegSet& defined = definedness.getDefinedNamesAtEnd(pred); const VRegSet& defined = definedness.getDefinedVregsAtEnd(pred);
for (int vreg : defined) { for (int vreg : defined) {
auto s = vreg_info.getName(vreg); auto s = vreg_info.getName(vreg);
if (required.count(s) == 0 && liveness->isLiveAtEnd(s, pred)) { if (!required[vreg] && liveness->isLiveAtEnd(s, pred)) {
// printf("%d-%d %s\n", pred->idx, block->idx, s.c_str()); // printf("%d-%d %s\n", pred->idx, block->idx, s.c_str());
required.insert(s); required.set(vreg);
} }
} }
} }
...@@ -486,23 +483,23 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def ...@@ -486,23 +483,23 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
us_phis.log(_t.end()); us_phis.log(_t.end());
} }
const PhiAnalysis::RequiredSet& PhiAnalysis::getAllRequiredAfter(CFGBlock* block) { const VRegSet& PhiAnalysis::getAllRequiredAfter(CFGBlock* block) {
static RequiredSet empty;
if (block->successors.size() == 0) if (block->successors.size() == 0)
return empty; return empty_set;
assert(required_phis.count(block->successors[0])); assert(required_phis.count(block->successors[0]));
return required_phis[block->successors[0]]; return required_phis.find(block->successors[0])->second;
} }
const PhiAnalysis::RequiredSet& PhiAnalysis::getAllRequiredFor(CFGBlock* block) { const VRegSet& PhiAnalysis::getAllRequiredFor(CFGBlock* block) {
assert(required_phis.count(block)); assert(required_phis.count(block));
return required_phis[block]; return required_phis.find(block)->second;
} }
// TODO: switch this to taking a vreg
bool PhiAnalysis::isRequired(InternedString name, CFGBlock* block) { bool PhiAnalysis::isRequired(InternedString name, CFGBlock* block) {
assert(!startswith(name.s(), "!")); assert(!startswith(name.s(), "!"));
assert(required_phis.count(block)); assert(required_phis.count(block));
return required_phis[block].count(name) != 0; return required_phis.find(block)->second[block->cfg->getVRegInfo().getVReg(name)];
} }
bool PhiAnalysis::isRequiredAfter(InternedString name, CFGBlock* block) { bool PhiAnalysis::isRequiredAfter(InternedString name, CFGBlock* block) {
...@@ -548,31 +545,34 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames& args, CFG* cf ...@@ -548,31 +545,34 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames& args, CFG* cf
static StatCounter counter("num_phi_analysis"); static StatCounter counter("num_phi_analysis");
counter.log(); counter.log();
llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map;
auto&& vreg_info = cfg->getVRegInfo(); auto&& vreg_info = cfg->getVRegInfo();
int num_vregs = vreg_info.getTotalNumOfVRegs();
VRegMap<DefinednessAnalysis::DefinitionLevel> initial_map(num_vregs);
assert(vreg_info.hasVRegsAssigned()); assert(vreg_info.hasVRegsAssigned());
for (auto p : vreg_info.getSymVRegMap()) for (int vreg = 0; vreg < num_vregs; vreg++) {
initial_map[p.first] = DefinednessAnalysis::Undefined; initial_map[vreg] = DefinednessAnalysis::Undefined;
}
auto maybe_add = [&](llvm::StringRef s) { auto maybe_add = [&](AST_Name* n) {
InternedString e = scope_info->internString(s); ScopeInfo::VarScopeType vst = n->lookup_type;
ScopeInfo::VarScopeType vst = scope_info->getScopeTypeOfName(e); assert(vst != ScopeInfo::VarScopeType::UNKNOWN);
assert(vst != ScopeInfo::VarScopeType::GLOBAL); assert(vst != ScopeInfo::VarScopeType::GLOBAL);
if (vst == ScopeInfo::VarScopeType::NAME) if (vst == ScopeInfo::VarScopeType::NAME)
return; return;
assert(vreg_info.getVReg(e) >= 0); // just run it through for the assertions assert(n->vreg >= 0);
initial_map[e] = DefinednessAnalysis::Defined; initial_map[n->vreg] = DefinednessAnalysis::Defined;
}; };
for (auto e : args.args) for (auto e : args.arg_names)
maybe_add(e); maybe_add(e);
if (args.vararg.size()) if (args.vararg_name)
maybe_add(args.vararg); maybe_add(args.vararg_name);
if (args.kwarg.size()) if (args.kwarg_name)
maybe_add(args.kwarg); maybe_add(args.kwarg_name);
assert(initial_map.size() == vreg_info.getTotalNumOfVRegs()); assert(initial_map.numVregs() == vreg_info.getTotalNumOfVRegs());
return std::unique_ptr<PhiAnalysis>( return std::unique_ptr<PhiAnalysis>(
new PhiAnalysis(std::move(initial_map), cfg->getStartingBlock(), false, liveness, scope_info)); new PhiAnalysis(std::move(initial_map), cfg->getStartingBlock(), false, liveness, scope_info));
...@@ -583,10 +583,12 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry ...@@ -583,10 +583,12 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry
static StatCounter counter("num_phi_analysis"); static StatCounter counter("num_phi_analysis");
counter.log(); counter.log();
llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map; auto cfg = entry_descriptor->md->source->cfg;
int num_vregs = cfg->getVRegInfo().getTotalNumOfVRegs();
VRegMap<DefinednessAnalysis::DefinitionLevel> initial_map(num_vregs);
for (auto p : entry_descriptor->md->source->cfg->getVRegInfo().getSymVRegMap()) { for (int vreg = 0; vreg < num_vregs; vreg++) {
initial_map[p.first] = DefinednessAnalysis::Undefined; initial_map[vreg] = DefinednessAnalysis::Undefined;
} }
llvm::StringSet<> potentially_undefined; llvm::StringSet<> potentially_undefined;
...@@ -602,11 +604,12 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry ...@@ -602,11 +604,12 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry
if (p.first.s() == PASSED_CLOSURE_NAME || p.first.s() == FRAME_INFO_PTR_NAME if (p.first.s() == PASSED_CLOSURE_NAME || p.first.s() == FRAME_INFO_PTR_NAME
|| p.first.s() == PASSED_GENERATOR_NAME || p.first.s() == CREATED_CLOSURE_NAME) || p.first.s() == PASSED_GENERATOR_NAME || p.first.s() == CREATED_CLOSURE_NAME)
continue; continue;
ASSERT(initial_map.count(p.first), "%s", p.first.c_str()); int vreg = cfg->getVRegInfo().getVReg(p.first);
ASSERT(initial_map[vreg] == DefinednessAnalysis::Undefined, "%s %d", p.first.c_str(), initial_map[vreg]);
if (potentially_undefined.count(p.first.s())) if (potentially_undefined.count(p.first.s()))
initial_map[p.first] = DefinednessAnalysis::PotentiallyDefined; initial_map[vreg] = DefinednessAnalysis::PotentiallyDefined;
else else
initial_map[p.first] = DefinednessAnalysis::Defined; initial_map[vreg] = DefinednessAnalysis::Defined;
} }
return std::unique_ptr<PhiAnalysis>( return std::unique_ptr<PhiAnalysis>(
......
...@@ -63,7 +63,15 @@ private: ...@@ -63,7 +63,15 @@ private:
public: public:
VRegSet(int num_vregs) : v(num_vregs, false) {} VRegSet(int num_vregs) : v(num_vregs, false) {}
void set(int vreg) { v[vreg] = true; } // TODO: what is the referenc type here?
bool operator[](int vreg) {
assert(vreg >= 0 && vreg < v.size());
return v[vreg];
}
void set(int vreg) {
assert(vreg >= 0 && vreg < v.size());
v[vreg] = true;
}
class iterator { class iterator {
public: public:
...@@ -145,44 +153,44 @@ public: ...@@ -145,44 +153,44 @@ public:
PotentiallyDefined, PotentiallyDefined,
Defined, Defined,
}; };
typedef VRegSet RequiredSet;
private: private:
llvm::DenseMap<CFGBlock*, VRegMap<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*, VRegSet> defined_at_end_sets;
public: public:
DefinednessAnalysis() {} DefinednessAnalysis() {}
void run(llvm::DenseMap<InternedString, DefinitionLevel> initial_map, CFGBlock* initial_block, void run(VRegMap<DefinitionLevel> initial_map, CFGBlock* initial_block, ScopeInfo* scope_info);
ScopeInfo* scope_info);
DefinitionLevel isDefinedAtEnd(InternedString name, CFGBlock* block); DefinitionLevel isDefinedAtEnd(InternedString name, CFGBlock* block);
const RequiredSet& getDefinedNamesAtEnd(CFGBlock* block); const VRegSet& getDefinedVregsAtEnd(CFGBlock* block);
friend class PhiAnalysis; friend class PhiAnalysis;
}; };
class PhiAnalysis { class PhiAnalysis {
public: public:
typedef llvm::DenseSet<InternedString> RequiredSet;
DefinednessAnalysis definedness; DefinednessAnalysis definedness;
VRegSet empty_set;
private: private:
LivenessAnalysis* liveness; LivenessAnalysis* liveness;
llvm::DenseMap<CFGBlock*, RequiredSet> required_phis; llvm::DenseMap<CFGBlock*, VRegSet> required_phis;
public: public:
// Initials_need_phis specifies that initial_map should count as an additional entry point // Initials_need_phis specifies that initial_map should count as an additional entry point
// that may require phis. // that may require phis.
PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::DefinitionLevel> initial_map, PhiAnalysis(VRegMap<DefinednessAnalysis::DefinitionLevel> initial_map, CFGBlock* initial_block,
CFGBlock* initial_block, bool initials_need_phis, LivenessAnalysis* liveness, ScopeInfo* scope_info); bool initials_need_phis, LivenessAnalysis* liveness, ScopeInfo* scope_info);
// TODO: convert these to taking vregs
bool isRequired(InternedString name, CFGBlock* block); bool isRequired(InternedString name, CFGBlock* block);
bool isRequiredAfter(InternedString name, CFGBlock* block); bool isRequiredAfter(InternedString name, CFGBlock* block);
const RequiredSet& getAllRequiredAfter(CFGBlock* block); const VRegSet& getAllRequiredAfter(CFGBlock* block);
const RequiredSet& getAllRequiredFor(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": // If "name" may be undefined at the beginning of any immediate successor block of "block":
bool isPotentiallyUndefinedAfter(InternedString name, CFGBlock* block); bool isPotentiallyUndefinedAfter(InternedString name, CFGBlock* block);
// If "name" may be undefined at the beginning of "block" // If "name" may be undefined at the beginning of "block"
......
...@@ -155,7 +155,7 @@ public: ...@@ -155,7 +155,7 @@ public:
~ASTInterpreter() { Py_XDECREF(this->created_closure); } ~ASTInterpreter() { Py_XDECREF(this->created_closure); }
const VRegInfo& getVRegInfo() const { return source_info->cfg->getVRegInfo(); } const VRegInfo& getVRegInfo() const { return source_info->cfg->getVRegInfo(); }
const llvm::DenseMap<InternedString, int>& getSymVRegMap() const { const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getSymVRegMap() const {
return source_info->cfg->getVRegInfo().getSymVRegMap(); return source_info->cfg->getVRegInfo().getSymVRegMap();
} }
...@@ -745,7 +745,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) { ...@@ -745,7 +745,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
// Currently we pass None because the LLVM jit will decref this value even though it may not be set. // Currently we pass None because the LLVM jit will decref this value even though it may not be set.
static Box* const VAL_UNDEFINED = (Box*)None; static Box* const VAL_UNDEFINED = (Box*)None;
const VRegSet& defined = phis->definedness.getDefinedNamesAtEnd(current_block); const VRegSet& defined = phis->definedness.getDefinedVregsAtEnd(current_block);
for (int vreg : defined) { for (int vreg : defined) {
InternedString name = source_info->cfg->getVRegInfo().getName(vreg); InternedString name = source_info->cfg->getVRegInfo().getName(vreg);
......
...@@ -361,12 +361,14 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -361,12 +361,14 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
PhiAnalysis* phi_analysis = irstate->getPhis(); PhiAnalysis* phi_analysis = irstate->getPhis();
assert(phi_analysis); assert(phi_analysis);
CFG* cfg = source->cfg;
if (entry_descriptor != NULL) if (entry_descriptor != NULL)
assert(blocks.count(source->cfg->getStartingBlock()) == 0); assert(blocks.count(cfg->getStartingBlock()) == 0);
// We need the entry blocks pre-allocated so that we can jump forward to them. // We need the entry blocks pre-allocated so that we can jump forward to them.
std::unordered_map<CFGBlock*, llvm::BasicBlock*> llvm_entry_blocks; std::unordered_map<CFGBlock*, llvm::BasicBlock*> llvm_entry_blocks;
for (CFGBlock* block : source->cfg->blocks) { for (CFGBlock* block : cfg->blocks) {
if (blocks.count(block) == 0) { if (blocks.count(block) == 0) {
llvm_entry_blocks[block] = NULL; llvm_entry_blocks[block] = NULL;
continue; continue;
...@@ -514,8 +516,8 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -514,8 +516,8 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
CFGBlock* initial_block = NULL; CFGBlock* initial_block = NULL;
if (entry_descriptor) { if (entry_descriptor) {
initial_block = entry_descriptor->backedge->target; initial_block = entry_descriptor->backedge->target;
} else if (blocks.count(source->cfg->getStartingBlock())) { } else if (blocks.count(cfg->getStartingBlock())) {
initial_block = source->cfg->getStartingBlock(); initial_block = cfg->getStartingBlock();
} }
// The rest of this code assumes that for each non-entry block that gets evaluated, // The rest of this code assumes that for each non-entry block that gets evaluated,
...@@ -548,14 +550,13 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -548,14 +550,13 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// Set initial symbol table: // Set initial symbol table:
// If we're in the starting block, no phis or symbol table changes for us. // If we're in the starting block, no phis or symbol table changes for us.
// Generate function entry code instead. // Generate function entry code instead.
if (block == source->cfg->getStartingBlock()) { if (block == cfg->getStartingBlock()) {
assert(entry_descriptor == NULL); assert(entry_descriptor == NULL);
if (ENABLE_REOPT && effort < EffortLevel::MAXIMAL && source->ast != NULL if (ENABLE_REOPT && effort < EffortLevel::MAXIMAL && source->ast != NULL
&& source->ast->type != AST_TYPE::Module) { && source->ast->type != AST_TYPE::Module) {
llvm::BasicBlock* preentry_bb llvm::BasicBlock* preentry_bb = llvm::BasicBlock::Create(
= llvm::BasicBlock::Create(g.context, "pre_entry", irstate->getLLVMFunction(), g.context, "pre_entry", irstate->getLLVMFunction(), llvm_entry_blocks[cfg->getStartingBlock()]);
llvm_entry_blocks[source->cfg->getStartingBlock()]);
llvm::BasicBlock* reopt_bb = llvm::BasicBlock::Create(g.context, "reopt", irstate->getLLVMFunction()); llvm::BasicBlock* reopt_bb = llvm::BasicBlock::Create(g.context, "reopt", irstate->getLLVMFunction());
emitter->getBuilder()->SetInsertPoint(preentry_bb); emitter->getBuilder()->SetInsertPoint(preentry_bb);
...@@ -580,7 +581,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -580,7 +581,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
llvm::MDNode* branch_weights = llvm::MDNode::get(g.context, llvm::ArrayRef<llvm::Metadata*>(md_vals)); llvm::MDNode* branch_weights = llvm::MDNode::get(g.context, llvm::ArrayRef<llvm::Metadata*>(md_vals));
llvm::BranchInst* guard = emitter->getBuilder()->CreateCondBr( llvm::BranchInst* guard = emitter->getBuilder()->CreateCondBr(
reopt_test, reopt_bb, llvm_entry_blocks[source->cfg->getStartingBlock()], branch_weights); reopt_test, reopt_bb, llvm_entry_blocks[cfg->getStartingBlock()], branch_weights);
emitter->getBuilder()->SetInsertPoint(reopt_bb); emitter->getBuilder()->SetInsertPoint(reopt_bb);
// emitter->getBuilder()->CreateCall(g.funcs.my_assert, getConstantInt(0, g.i1)); // emitter->getBuilder()->CreateCall(g.funcs.my_assert, getConstantInt(0, g.i1));
...@@ -603,7 +604,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -603,7 +604,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
postcall->setTailCall(true); postcall->setTailCall(true);
emitter->getBuilder()->CreateRet(postcall); emitter->getBuilder()->CreateRet(postcall);
emitter->getBuilder()->SetInsertPoint(llvm_entry_blocks[source->cfg->getStartingBlock()]); emitter->getBuilder()->SetInsertPoint(llvm_entry_blocks[cfg->getStartingBlock()]);
} }
generator->doFunctionEntry(*irstate->getParamNames(), cf->spec->arg_types); generator->doFunctionEntry(*irstate->getParamNames(), cf->spec->arg_types);
...@@ -640,7 +641,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -640,7 +641,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
(*phis)[p.first] = std::make_pair(analyzed_type, phi); (*phis)[p.first] = std::make_pair(analyzed_type, phi);
} }
} else if (pred == NULL) { } else if (pred == NULL) {
assert(traversal_order.size() < source->cfg->blocks.size()); assert(traversal_order.size() < cfg->blocks.size());
assert(phis); assert(phis);
assert(block->predecessors.size()); assert(block->predecessors.size());
for (int i = 0; i < block->predecessors.size(); i++) { for (int i = 0; i < block->predecessors.size(); i++) {
...@@ -651,7 +652,8 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -651,7 +652,8 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
std::set<InternedString> names; std::set<InternedString> names;
for (const auto& s : phi_analysis->getAllRequiredFor(block)) { for (const int vreg : phi_analysis->getAllRequiredFor(block)) {
auto s = cfg->getVRegInfo().getName(vreg);
names.insert(s); names.insert(s);
if (phi_analysis->isPotentiallyUndefinedAfter(s, block->predecessors[0])) { if (phi_analysis->isPotentiallyUndefinedAfter(s, block->predecessors[0])) {
names.insert(getIsDefinedName(s, source->getInternedStrings())); names.insert(getIsDefinedName(s, source->getInternedStrings()));
...@@ -832,7 +834,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -832,7 +834,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// the relevant IR, so after we have done all of it, go back through and populate the phi nodes. // the relevant IR, so after we have done all of it, go back through and populate the phi nodes.
// Also, do some checking to make sure that the phi analysis stuff worked out, and that all blocks // Also, do some checking to make sure that the phi analysis stuff worked out, and that all blocks
// agreed on what symbols + types they should be propagating for the phis. // agreed on what symbols + types they should be propagating for the phis.
for (CFGBlock* b : source->cfg->blocks) { for (CFGBlock* b : cfg->blocks) {
PHITable* phis = created_phis[b]; PHITable* phis = created_phis[b];
if (phis == NULL) if (phis == NULL)
continue; continue;
...@@ -910,7 +912,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc ...@@ -910,7 +912,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
} }
// deallocate/dereference memory // deallocate/dereference memory
for (CFGBlock* b : source->cfg->blocks) { for (CFGBlock* b : cfg->blocks) {
if (ending_symbol_tables[b] == NULL) if (ending_symbol_tables[b] == NULL)
continue; continue;
......
...@@ -2682,8 +2682,9 @@ private: ...@@ -2682,8 +2682,9 @@ private:
} }
} }
const PhiAnalysis::RequiredSet& all_phis = irstate->getPhis()->getAllRequiredAfter(myblock); for (int vreg : irstate->getPhis()->getAllRequiredAfter(myblock)) {
for (PhiAnalysis::RequiredSet::const_iterator it = all_phis.begin(), end = all_phis.end(); it != end; ++it) { auto name = irstate->getCFG()->getVRegInfo().getName(vreg);
auto it = &name; // hack, remove
if (VERBOSITY() >= 3) if (VERBOSITY() >= 3)
printf("phi will be required for %s\n", it->c_str()); printf("phi will be required for %s\n", it->c_str());
assert(scope_info->getScopeTypeOfName(*it) != ScopeInfo::VarScopeType::GLOBAL); assert(scope_info->getScopeTypeOfName(*it) != ScopeInfo::VarScopeType::GLOBAL);
......
...@@ -82,6 +82,8 @@ public: ...@@ -82,6 +82,8 @@ public:
ParamNames* param_names, GCBuilder* gc, llvm::MDNode* func_dbg_info, RefcountTracker* refcount_tracker); ParamNames* param_names, GCBuilder* gc, llvm::MDNode* func_dbg_info, RefcountTracker* refcount_tracker);
~IRGenState(); ~IRGenState();
CFG* getCFG() { return getSourceInfo()->cfg; }
CompiledFunction* getCurFunction() { return cf; } CompiledFunction* getCurFunction() { return cf; }
FunctionMetadata* getMD() { return md; } FunctionMetadata* getMD() { return md; }
......
...@@ -2677,7 +2677,7 @@ public: ...@@ -2677,7 +2677,7 @@ public:
ScopeInfo* scope_info; ScopeInfo* scope_info;
CFGBlock* current_block; CFGBlock* current_block;
int next_vreg; int next_vreg;
llvm::DenseMap<InternedString, int> sym_vreg_map; llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map;
llvm::DenseMap<InternedString, std::unordered_set<CFGBlock*>> sym_blocks_map; llvm::DenseMap<InternedString, std::unordered_set<CFGBlock*>> sym_blocks_map;
std::vector<InternedString> vreg_sym_map; std::vector<InternedString> vreg_sym_map;
...@@ -2685,9 +2685,7 @@ public: ...@@ -2685,9 +2685,7 @@ 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 { bool visit_alias(AST_alias* node) override { RELEASE_ASSERT(0, "these should be removed by the cfg"); }
RELEASE_ASSERT(0, "these should be removed by the cfg");
}
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)
......
...@@ -42,6 +42,26 @@ class CFG; ...@@ -42,6 +42,26 @@ class CFG;
class ParamNames; class ParamNames;
class ScopeInfo; class ScopeInfo;
// Simple class to override the default value of an int.
template <int D = -1> class DefaultedInt {
private:
int x;
public:
DefaultedInt() : x(D) {}
DefaultedInt(int x) : x(x) {}
DefaultedInt(const DefaultedInt& rhs) : x(rhs.x) {}
DefaultedInt(DefaultedInt&& rhs) : x(rhs.x) {}
void operator=(const DefaultedInt& rhs) { x = rhs.x; }
void operator=(DefaultedInt&& rhs) { x = rhs.x; }
template <typename T> bool operator<(T rhs) const { return x < rhs; }
template <typename T> bool operator>(T rhs) const { return x > rhs; }
template <typename T> bool operator<=(T rhs) const { return x <= rhs; }
template <typename T> bool operator>=(T rhs) const { return x >= rhs; }
operator int() const { return x; }
};
class CFGBlock { class CFGBlock {
public: public:
CFG* cfg; CFG* cfg;
...@@ -85,8 +105,8 @@ public: ...@@ -85,8 +105,8 @@ public:
// llvm jit : [user visible] // llvm jit : [user visible]
class VRegInfo { class VRegInfo {
private: private:
llvm::DenseMap<InternedString, int> sym_vreg_map_user_visible; llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map_user_visible;
llvm::DenseMap<InternedString, int> sym_vreg_map; llvm::DenseMap<InternedString, DefaultedInt<-1>> sym_vreg_map;
// Reverse map, from vreg->symbol name. // Reverse map, from vreg->symbol name.
std::vector<InternedString> vreg_sym_map; std::vector<InternedString> vreg_sym_map;
...@@ -97,8 +117,10 @@ private: ...@@ -97,8 +117,10 @@ private:
public: public:
// map of all assigned names. if the name is block local the vreg number is not unique because this vregs get reused // map of all assigned names. if the name is block local the vreg number is not unique because this vregs get reused
// between blocks. // between blocks.
const llvm::DenseMap<InternedString, int>& getSymVRegMap() { return sym_vreg_map; } const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getSymVRegMap() { return sym_vreg_map; }
const llvm::DenseMap<InternedString, int>& getUserVisibleSymVRegMap() { return sym_vreg_map_user_visible; } const llvm::DenseMap<InternedString, DefaultedInt<-1>>& getUserVisibleSymVRegMap() {
return sym_vreg_map_user_visible;
}
int getVReg(InternedString name) const { int getVReg(InternedString name) const {
assert(hasVRegsAssigned()); assert(hasVRegsAssigned());
......
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