Simplify the check when to perform loop invariant code motion.
Allow HChange instructions to be hoisted out of loops. To avoid unnecessary code motion we don't hoist instructions from blocks that have been marked containing an unconditional deoptimization. Review URL: http://codereview.chromium.org/7003087 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8245 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9f432cd159
commit
424407c727
@ -137,8 +137,6 @@ DEFINE_int(deopt_every_n_times,
|
|||||||
DEFINE_bool(trap_on_deopt, false, "put a break point before deoptimizing")
|
DEFINE_bool(trap_on_deopt, false, "put a break point before deoptimizing")
|
||||||
DEFINE_bool(deoptimize_uncommon_cases, true, "deoptimize uncommon cases")
|
DEFINE_bool(deoptimize_uncommon_cases, true, "deoptimize uncommon cases")
|
||||||
DEFINE_bool(polymorphic_inlining, true, "polymorphic inlining")
|
DEFINE_bool(polymorphic_inlining, true, "polymorphic inlining")
|
||||||
DEFINE_bool(aggressive_loop_invariant_motion, true,
|
|
||||||
"aggressive motion of instructions out of loops")
|
|
||||||
DEFINE_bool(use_osr, true, "use on-stack replacement")
|
DEFINE_bool(use_osr, true, "use on-stack replacement")
|
||||||
|
|
||||||
DEFINE_bool(trace_osr, false, "trace on-stack replacement")
|
DEFINE_bool(trace_osr, false, "trace on-stack replacement")
|
||||||
|
@ -68,7 +68,8 @@ HBasicBlock::HBasicBlock(HGraph* graph)
|
|||||||
last_instruction_index_(-1),
|
last_instruction_index_(-1),
|
||||||
deleted_phis_(4),
|
deleted_phis_(4),
|
||||||
parent_loop_header_(NULL),
|
parent_loop_header_(NULL),
|
||||||
is_inline_return_target_(false) { }
|
is_inline_return_target_(false),
|
||||||
|
is_deoptimizing_(false) { }
|
||||||
|
|
||||||
|
|
||||||
void HBasicBlock::AttachLoopInformation() {
|
void HBasicBlock::AttachLoopInformation() {
|
||||||
@ -741,9 +742,21 @@ void HGraph::AssignDominators() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Propagate flag marking blocks containing unconditional deoptimize.
|
||||||
|
MarkAsDeoptimizingRecursively(entry_block());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Mark all blocks that are dominated by an unconditional deoptimize.
|
||||||
|
void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
|
||||||
|
for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
|
||||||
|
HBasicBlock* dominated = block->dominated_blocks()->at(i);
|
||||||
|
if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
|
||||||
|
MarkAsDeoptimizingRecursively(dominated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HGraph::EliminateRedundantPhis() {
|
void HGraph::EliminateRedundantPhis() {
|
||||||
HPhase phase("Redundant phi elimination", this);
|
HPhase phase("Redundant phi elimination", this);
|
||||||
|
|
||||||
@ -897,7 +910,7 @@ void HRangeAnalysis::TraceRange(const char* msg, ...) {
|
|||||||
|
|
||||||
void HRangeAnalysis::Analyze() {
|
void HRangeAnalysis::Analyze() {
|
||||||
HPhase phase("Range analysis", graph_);
|
HPhase phase("Range analysis", graph_);
|
||||||
Analyze(graph_->blocks()->at(0));
|
Analyze(graph_->entry_block());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1355,7 +1368,7 @@ void HGlobalValueNumberer::Analyze() {
|
|||||||
LoopInvariantCodeMotion();
|
LoopInvariantCodeMotion();
|
||||||
}
|
}
|
||||||
HValueMap* map = new(zone()) HValueMap();
|
HValueMap* map = new(zone()) HValueMap();
|
||||||
AnalyzeBlock(graph_->blocks()->at(0), map);
|
AnalyzeBlock(graph_->entry_block(), map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1447,37 +1460,9 @@ bool HGlobalValueNumberer::AllowCodeMotion() {
|
|||||||
|
|
||||||
bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
|
bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
|
||||||
HBasicBlock* loop_header) {
|
HBasicBlock* loop_header) {
|
||||||
// If we've disabled code motion, don't move any instructions.
|
// If we've disabled code motion or we're in a block that unconditionally
|
||||||
if (!AllowCodeMotion()) return false;
|
// deoptimizes, don't move any instructions.
|
||||||
|
return AllowCodeMotion() && !instr->block()->IsDeoptimizing();
|
||||||
// If --aggressive-loop-invariant-motion, move everything except change
|
|
||||||
// instructions.
|
|
||||||
if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise only move instructions that postdominate the loop header
|
|
||||||
// (i.e. are always executed inside the loop). This is to avoid
|
|
||||||
// unnecessary deoptimizations assuming the loop is executed at least
|
|
||||||
// once. TODO(fschneider): Better type feedback should give us
|
|
||||||
// information about code that was never executed.
|
|
||||||
HBasicBlock* block = instr->block();
|
|
||||||
bool result = true;
|
|
||||||
if (block != loop_header) {
|
|
||||||
for (int i = 1; i < loop_header->predecessors()->length(); ++i) {
|
|
||||||
bool found = false;
|
|
||||||
HBasicBlock* pred = loop_header->predecessors()->at(i);
|
|
||||||
while (pred != loop_header) {
|
|
||||||
if (pred == block) found = true;
|
|
||||||
pred = pred->dominator();
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
result = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4854,6 +4839,7 @@ void HGraphBuilder::VisitSub(UnaryOperation* expr) {
|
|||||||
TypeInfo info = oracle()->UnaryType(expr);
|
TypeInfo info = oracle()->UnaryType(expr);
|
||||||
if (info.IsUninitialized()) {
|
if (info.IsUninitialized()) {
|
||||||
AddInstruction(new(zone()) HSoftDeoptimize);
|
AddInstruction(new(zone()) HSoftDeoptimize);
|
||||||
|
current_block()->MarkAsDeoptimizing();
|
||||||
info = TypeInfo::Unknown();
|
info = TypeInfo::Unknown();
|
||||||
}
|
}
|
||||||
Representation rep = ToRepresentation(info);
|
Representation rep = ToRepresentation(info);
|
||||||
@ -4869,6 +4855,7 @@ void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
|
|||||||
TypeInfo info = oracle()->UnaryType(expr);
|
TypeInfo info = oracle()->UnaryType(expr);
|
||||||
if (info.IsUninitialized()) {
|
if (info.IsUninitialized()) {
|
||||||
AddInstruction(new(zone()) HSoftDeoptimize);
|
AddInstruction(new(zone()) HSoftDeoptimize);
|
||||||
|
current_block()->MarkAsDeoptimizing();
|
||||||
}
|
}
|
||||||
HInstruction* instr = new(zone()) HBitNot(value);
|
HInstruction* instr = new(zone()) HBitNot(value);
|
||||||
ast_context()->ReturnInstruction(instr, expr->id());
|
ast_context()->ReturnInstruction(instr, expr->id());
|
||||||
@ -5104,6 +5091,7 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
|
|||||||
TypeInfo info = oracle()->BinaryType(expr);
|
TypeInfo info = oracle()->BinaryType(expr);
|
||||||
if (info.IsUninitialized()) {
|
if (info.IsUninitialized()) {
|
||||||
AddInstruction(new(zone()) HSoftDeoptimize);
|
AddInstruction(new(zone()) HSoftDeoptimize);
|
||||||
|
current_block()->MarkAsDeoptimizing();
|
||||||
info = TypeInfo::Unknown();
|
info = TypeInfo::Unknown();
|
||||||
}
|
}
|
||||||
HInstruction* instr = NULL;
|
HInstruction* instr = NULL;
|
||||||
@ -5373,6 +5361,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
|||||||
// Check if this expression was ever executed according to type feedback.
|
// Check if this expression was ever executed according to type feedback.
|
||||||
if (type_info.IsUninitialized()) {
|
if (type_info.IsUninitialized()) {
|
||||||
AddInstruction(new(zone()) HSoftDeoptimize);
|
AddInstruction(new(zone()) HSoftDeoptimize);
|
||||||
|
current_block()->MarkAsDeoptimizing();
|
||||||
type_info = TypeInfo::Unknown();
|
type_info = TypeInfo::Unknown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +143,9 @@ class HBasicBlock: public ZoneObject {
|
|||||||
bool IsInlineReturnTarget() const { return is_inline_return_target_; }
|
bool IsInlineReturnTarget() const { return is_inline_return_target_; }
|
||||||
void MarkAsInlineReturnTarget() { is_inline_return_target_ = true; }
|
void MarkAsInlineReturnTarget() { is_inline_return_target_ = true; }
|
||||||
|
|
||||||
|
bool IsDeoptimizing() const { return is_deoptimizing_; }
|
||||||
|
void MarkAsDeoptimizing() { is_deoptimizing_ = true; }
|
||||||
|
|
||||||
inline Zone* zone();
|
inline Zone* zone();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -175,6 +178,7 @@ class HBasicBlock: public ZoneObject {
|
|||||||
ZoneList<int> deleted_phis_;
|
ZoneList<int> deleted_phis_;
|
||||||
HBasicBlock* parent_loop_header_;
|
HBasicBlock* parent_loop_header_;
|
||||||
bool is_inline_return_target_;
|
bool is_inline_return_target_;
|
||||||
|
bool is_deoptimizing_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -225,6 +229,7 @@ class HGraph: public ZoneObject {
|
|||||||
void OrderBlocks();
|
void OrderBlocks();
|
||||||
void AssignDominators();
|
void AssignDominators();
|
||||||
void ReplaceCheckedValues();
|
void ReplaceCheckedValues();
|
||||||
|
void MarkAsDeoptimizingRecursively(HBasicBlock* block);
|
||||||
|
|
||||||
// Returns false if there are phi-uses of the arguments-object
|
// Returns false if there are phi-uses of the arguments-object
|
||||||
// which are not supported by the optimizing compiler.
|
// which are not supported by the optimizing compiler.
|
||||||
|
Loading…
Reference in New Issue
Block a user