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:
fschneider@chromium.org 2011-06-09 15:49:21 +00:00
parent 9f432cd159
commit 424407c727
3 changed files with 28 additions and 36 deletions

View File

@ -137,8 +137,6 @@ DEFINE_int(deopt_every_n_times,
DEFINE_bool(trap_on_deopt, false, "put a break point before deoptimizing")
DEFINE_bool(deoptimize_uncommon_cases, true, "deoptimize uncommon cases")
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(trace_osr, false, "trace on-stack replacement")

View File

@ -68,7 +68,8 @@ HBasicBlock::HBasicBlock(HGraph* graph)
last_instruction_index_(-1),
deleted_phis_(4),
parent_loop_header_(NULL),
is_inline_return_target_(false) { }
is_inline_return_target_(false),
is_deoptimizing_(false) { }
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() {
HPhase phase("Redundant phi elimination", this);
@ -897,7 +910,7 @@ void HRangeAnalysis::TraceRange(const char* msg, ...) {
void HRangeAnalysis::Analyze() {
HPhase phase("Range analysis", graph_);
Analyze(graph_->blocks()->at(0));
Analyze(graph_->entry_block());
}
@ -1355,7 +1368,7 @@ void HGlobalValueNumberer::Analyze() {
LoopInvariantCodeMotion();
}
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,
HBasicBlock* loop_header) {
// If we've disabled code motion, don't move any instructions.
if (!AllowCodeMotion()) return false;
// 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;
// If we've disabled code motion or we're in a block that unconditionally
// deoptimizes, don't move any instructions.
return AllowCodeMotion() && !instr->block()->IsDeoptimizing();
}
@ -4854,6 +4839,7 @@ void HGraphBuilder::VisitSub(UnaryOperation* expr) {
TypeInfo info = oracle()->UnaryType(expr);
if (info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
info = TypeInfo::Unknown();
}
Representation rep = ToRepresentation(info);
@ -4869,6 +4855,7 @@ void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
TypeInfo info = oracle()->UnaryType(expr);
if (info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
}
HInstruction* instr = new(zone()) HBitNot(value);
ast_context()->ReturnInstruction(instr, expr->id());
@ -5104,6 +5091,7 @@ HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
TypeInfo info = oracle()->BinaryType(expr);
if (info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
info = TypeInfo::Unknown();
}
HInstruction* instr = NULL;
@ -5373,6 +5361,7 @@ void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
// Check if this expression was ever executed according to type feedback.
if (type_info.IsUninitialized()) {
AddInstruction(new(zone()) HSoftDeoptimize);
current_block()->MarkAsDeoptimizing();
type_info = TypeInfo::Unknown();
}

View File

@ -143,6 +143,9 @@ class HBasicBlock: public ZoneObject {
bool IsInlineReturnTarget() const { return is_inline_return_target_; }
void MarkAsInlineReturnTarget() { is_inline_return_target_ = true; }
bool IsDeoptimizing() const { return is_deoptimizing_; }
void MarkAsDeoptimizing() { is_deoptimizing_ = true; }
inline Zone* zone();
#ifdef DEBUG
@ -175,6 +178,7 @@ class HBasicBlock: public ZoneObject {
ZoneList<int> deleted_phis_;
HBasicBlock* parent_loop_header_;
bool is_inline_return_target_;
bool is_deoptimizing_;
};
@ -225,6 +229,7 @@ class HGraph: public ZoneObject {
void OrderBlocks();
void AssignDominators();
void ReplaceCheckedValues();
void MarkAsDeoptimizingRecursively(HBasicBlock* block);
// Returns false if there are phi-uses of the arguments-object
// which are not supported by the optimizing compiler.