Commit ea673dfd authored by Kevin Modzelewski's avatar Kevin Modzelewski

For OSRs, do type analysis starting from OSR edge

Before we would do type analysis starting from the function entry
(using the specialization of the previous function).  This makes things
pretty complicated because we can infer different types than we are OSRing
with!  Ex if the type analysis determines that we should speculate in an
earlier BB, the types we have now might not reflect that speculation.

So instead, start the type analysis starting from the BB that the OSR starts at.
Should also have the side-benefit of requiring less type analysis work.

But this should let us get rid of the OSR-entry guarding, and the rest of
the old deopt system!
parent 222f5a70
......@@ -22,6 +22,7 @@
#include "analysis/scoping_analysis.h"
#include "codegen/codegen.h"
#include "codegen/compvars.h"
#include "codegen/osrentry.h"
#include "codegen/type_recording.h"
#include "core/ast.h"
#include "core/cfg.h"
......@@ -622,6 +623,7 @@ public:
return getTypeAtBlockStart(name, block->successors[0]);
}
ConcreteCompilerType* getTypeAtBlockStart(InternedString name, CFGBlock* block) override {
assert(starting_types.count(block));
CompilerType* base = starting_types[block][name];
ASSERT(base != NULL, "%s %d", name.c_str(), block->idx);
......@@ -672,40 +674,20 @@ public:
return changed;
}
static PropagatingTypeAnalysis* doAnalysis(CFG* cfg, const ParamNames& arg_names,
const std::vector<ConcreteCompilerType*>& arg_types,
SpeculationLevel speculation, ScopeInfo* scope_info) {
static PropagatingTypeAnalysis* doAnalysis(CFG* cfg, SpeculationLevel speculation, ScopeInfo* scope_info,
TypeMap&& initial_types, CFGBlock* initial_block) {
Timer _t("PropagatingTypeAnalysis::doAnalysis()");
AllTypeMap starting_types;
ExprTypeMap expr_types;
TypeSpeculations type_speculations;
assert(arg_names.totalParameters() == arg_types.size());
TypeMap& initial_types = starting_types[cfg->getStartingBlock()];
int i = 0;
for (; i < arg_names.args.size(); i++) {
initial_types[scope_info->internString(arg_names.args[i])] = unboxedType(arg_types[i]);
}
if (arg_names.vararg.size()) {
initial_types[scope_info->internString(arg_names.vararg)] = unboxedType(arg_types[i]);
i++;
}
if (arg_names.kwarg.size()) {
initial_types[scope_info->internString(arg_names.kwarg)] = unboxedType(arg_types[i]);
i++;
}
assert(i == arg_types.size());
std::unordered_set<CFGBlock*> in_queue;
std::priority_queue<CFGBlock*, std::vector<CFGBlock*>, CFGBlockMinIndex> queue;
queue.push(cfg->getStartingBlock());
in_queue.insert(cfg->getStartingBlock());
starting_types[initial_block] = std::move(initial_types);
queue.push(initial_block);
in_queue.insert(initial_block);
int num_evaluations = 0;
while (!queue.empty()) {
......@@ -787,6 +769,38 @@ TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& arg_names, const std::v
// if (effort == EffortLevel::INTERPRETED) {
// return new NullTypeAnalysis();
//}
return PropagatingTypeAnalysis::doAnalysis(cfg, arg_names, arg_types, speculation, scope_info);
assert(arg_names.totalParameters() == arg_types.size());
TypeMap initial_types;
int i = 0;
for (; i < arg_names.args.size(); i++) {
initial_types[scope_info->internString(arg_names.args[i])] = unboxedType(arg_types[i]);
}
if (arg_names.vararg.size()) {
initial_types[scope_info->internString(arg_names.vararg)] = unboxedType(arg_types[i]);
i++;
}
if (arg_names.kwarg.size()) {
initial_types[scope_info->internString(arg_names.kwarg)] = unboxedType(arg_types[i]);
i++;
}
assert(i == arg_types.size());
return PropagatingTypeAnalysis::doAnalysis(cfg, speculation, scope_info, std::move(initial_types),
cfg->getStartingBlock());
}
TypeAnalysis* doTypeAnalysis(CFG* cfg, const OSREntryDescriptor* entry_descriptor, EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info) {
// if (effort == EffortLevel::INTERPRETED) {
// return new NullTypeAnalysis();
//}
TypeMap initial_types(entry_descriptor->args.begin(), entry_descriptor->args.end());
return PropagatingTypeAnalysis::doAnalysis(cfg, speculation, scope_info, std::move(initial_types),
entry_descriptor->backedge->target);
}
}
......@@ -27,6 +27,7 @@ class ScopeInfo;
class CFGBlock;
class BoxedClass;
class AST_expr;
class OSREntryDescriptor;
class TypeAnalysis {
public:
......@@ -45,6 +46,8 @@ public:
TypeAnalysis* doTypeAnalysis(CFG* cfg, const ParamNames& param_names,
const std::vector<ConcreteCompilerType*>& arg_types, EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info);
TypeAnalysis* doTypeAnalysis(CFG* cfg, const OSREntryDescriptor* entry_descriptor, EffortLevel effort,
TypeAnalysis::SpeculationLevel speculation, ScopeInfo* scope_info);
}
#endif
......@@ -439,6 +439,10 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
v = converted->getValue();
delete converted;
} else {
printf("OSR'd with a %s into a partial compile that expects a %s?\n", p.second->debugName().c_str(),
phi_type->debugName().c_str());
RELEASE_ASSERT(0, "whyy");
#if 0
ASSERT(p.second == UNKNOWN, "%s", p.second->debugName().c_str());
BoxedClass* speculated_class = NULL;
if (phi_type == INT) {
......@@ -516,6 +520,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
assert(phi_type == typeFromClass(speculated_class));
v = from_arg;
}
#endif
}
if (VERBOSITY("irgen"))
......@@ -525,6 +530,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
}
if (guard_val) {
abort();
// Create the guard with both branches leading to the success_bb,
// and let the deopt path change the failure case to point to the
// as-yet-unknown deopt block.
......@@ -532,7 +538,7 @@ static void emitBBs(IRGenState* irstate, const char* bb_type, GuardList& out_gua
// the guard will just silently be ignored.
llvm::BranchInst* br
= entry_emitter->getBuilder()->CreateCondBr(guard_val, osr_unbox_block, osr_unbox_block);
out_guards.registerGuardForBlockEntry(target_block, br, *initial_syms);
// out_guards.registerGuardForBlockEntry(target_block, br, *initial_syms);
} else {
entry_emitter->getBuilder()->CreateBr(osr_unbox_block);
}
......@@ -1168,8 +1174,13 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
EffortLevel min_speculation_level = EffortLevel::MAXIMAL;
if (ENABLE_SPECULATION && effort >= min_speculation_level)
speculation_level = TypeAnalysis::SOME;
TypeAnalysis* types
= doTypeAnalysis(source->cfg, *param_names, spec->arg_types, effort, speculation_level, source->getScopeInfo());
TypeAnalysis* types;
if (entry_descriptor)
types = doTypeAnalysis(source->cfg, entry_descriptor, effort, speculation_level, source->getScopeInfo());
else
types = doTypeAnalysis(source->cfg, *param_names, spec->arg_types, effort, speculation_level,
source->getScopeInfo());
_t2.split();
......@@ -1192,6 +1203,7 @@ CompiledFunction* doCompile(SourceInfo* source, ParamNames* param_names, const O
// De-opt handling:
if (!guards.isEmpty()) {
RELEASE_ASSERT(0, "should not be any guards any more!");
BlockSet deopt_full_blocks, deopt_partial_blocks;
GuardList deopt_guards;
// typedef std::unordered_map<CFGBlock*, std::unordered_map<AST_expr*, GuardList::ExprTypeGuard*> > Worklist;
......
......@@ -130,11 +130,11 @@ public:
bool isEmpty() const { return block_begin_guards.size() == 0; }
void registerGuardForBlockEntry(CFGBlock* cfg_block, llvm::BranchInst* branch, const SymbolTable& st) {
// printf("Adding guard for block %p, in %p\n", cfg_block, this);
std::vector<BlockEntryGuard*>& v = block_begin_guards[cfg_block];
v.push_back(new BlockEntryGuard(cfg_block, branch, st));
}
// void registerGuardForBlockEntry(CFGBlock* cfg_block, llvm::BranchInst* branch, const SymbolTable& st) {
//// printf("Adding guard for block %p, in %p\n", cfg_block, this);
// std::vector<BlockEntryGuard*>& v = block_begin_guards[cfg_block];
// v.push_back(new BlockEntryGuard(cfg_block, branch, st));
//}
const std::vector<BlockEntryGuard*>& getGuardsForBlock(CFGBlock* block) const {
std::unordered_map<CFGBlock*, std::vector<BlockEntryGuard*>>::const_iterator it
......
......@@ -15,6 +15,7 @@
#ifndef PYSTON_CODEGEN_OSRENTRY_H
#define PYSTON_CODEGEN_OSRENTRY_H
#include <map>
#include <vector>
#include "core/stringpool.h"
......
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