Index: runtime/vm/flow_graph_optimizer.cc |
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc |
index 2b7eecc01579dd628e0973ae19db35e9fd6ac02c..2784d9696372aec32e278fe58d218496a6eff6da 100644 |
--- a/runtime/vm/flow_graph_optimizer.cc |
+++ b/runtime/vm/flow_graph_optimizer.cc |
@@ -28,6 +28,8 @@ DEFINE_FLAG(bool, load_cse, true, "Use redundant load elimination."); |
DEFINE_FLAG(bool, trace_range_analysis, false, "Trace range analysis progress"); |
DEFINE_FLAG(bool, trace_constant_propagation, false, |
"Print constant propagation and useless code elimination."); |
+DEFINE_FLAG(bool, array_bounds_check_elimination, true, |
+ "Eliminate redundant bounds checks."); |
void FlowGraphOptimizer::ApplyICData() { |
@@ -915,7 +917,8 @@ void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) { |
void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call, |
intptr_t length_offset, |
- bool is_immutable) { |
+ bool is_immutable, |
+ MethodRecognizer::Kind kind) { |
// Check receiver class. |
AddCheckClass(call, call->ArgumentAt(0)->value()->Copy()); |
@@ -925,6 +928,7 @@ void FlowGraphOptimizer::InlineArrayLengthGetter(InstanceCallInstr* call, |
Type::ZoneHandle(Type::SmiType()), |
is_immutable); |
load->set_result_cid(kSmiCid); |
+ load->set_recognized_kind(kind); |
call->ReplaceWith(load, current_iterator()); |
RemovePushArguments(call); |
} |
@@ -947,6 +951,7 @@ void FlowGraphOptimizer::InlineGArrayCapacityGetter(InstanceCallInstr* call) { |
Array::length_offset(), |
Type::ZoneHandle(Type::SmiType())); |
length_load->set_result_cid(kSmiCid); |
+ length_load->set_recognized_kind(MethodRecognizer::kObjectArrayLength); |
call->ReplaceWith(length_load, current_iterator()); |
RemovePushArguments(call); |
@@ -1027,12 +1032,16 @@ bool FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallInstr* call) { |
switch (recognized_kind) { |
case MethodRecognizer::kObjectArrayLength: |
case MethodRecognizer::kImmutableArrayLength: |
- InlineArrayLengthGetter(call, Array::length_offset(), true); |
+ InlineArrayLengthGetter(call, |
+ Array::length_offset(), |
+ true, |
+ recognized_kind); |
break; |
case MethodRecognizer::kGrowableArrayLength: |
InlineArrayLengthGetter(call, |
GrowableObjectArray::length_offset(), |
- false); |
+ false, |
+ recognized_kind); |
break; |
default: |
UNREACHABLE(); |
@@ -2100,11 +2109,17 @@ void RangeAnalysis::InferRangesRecursive(BlockEntryInstr* block) { |
} |
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
- Definition* defn = it.Current()->AsDefinition(); |
+ Instruction* current = it.Current(); |
+ |
+ Definition* defn = current->AsDefinition(); |
if ((defn != NULL) && |
(defn->ssa_temp_index() != -1) && |
smi_definitions_->Contains(defn->ssa_temp_index())) { |
defn->InferRange(); |
+ } else if (FLAG_array_bounds_check_elimination && |
+ current->IsCheckArrayBound() && |
+ current->AsCheckArrayBound()->IsRedundant()) { |
+ it.RemoveCurrentFromGraph(); |
} |
} |