Chromium Code Reviews| Index: src/hydrogen.cc |
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
| index a179e808a3f63a11b6ab784e02b6bce06e597670..dfebc164fa50433babc778fb1f363d913e6043cf 100644 |
| --- a/src/hydrogen.cc |
| +++ b/src/hydrogen.cc |
| @@ -2758,6 +2758,7 @@ HGraph* HGraphBuilder::CreateGraph() { |
| sce.Process(); |
| graph()->EliminateRedundantBoundsChecks(); |
| + graph()->DehoistSimpleArrayIndexComputations(); |
| return graph(); |
| } |
| @@ -3082,6 +3083,131 @@ void HGraph::EliminateRedundantBoundsChecks() { |
| } |
| +static bool DehoistArrayIndex(HInstruction* array_operation, |
| + HValue* index, |
| + int32_t index_position, |
| + int32_t* offset_value, |
| + Counters* counters) { |
| + HConstant* constant; |
| + HValue* subexpression; |
| + int32_t sign; |
| + if (index->IsAdd()) { |
| + sign = 1; |
| + HAdd* add = HAdd::cast(index); |
| + if (add->left()->IsConstant()) { |
| + subexpression = add->right(); |
| + constant = HConstant::cast(add->left()); |
| + } else if (add->right()->IsConstant()) { |
| + subexpression = add->left(); |
| + constant = HConstant::cast(add->right()); |
| + } else { |
| + return false; |
| + } |
| + } else if (index->IsSub()) { |
| + sign = -1; |
| + HSub* sub = HSub::cast(index); |
| + if (sub->left()->IsConstant()) { |
| + subexpression = sub->right(); |
| + constant = HConstant::cast(sub->left()); |
| + } else if (sub->right()->IsConstant()) { |
| + subexpression = sub->left(); |
| + constant = HConstant::cast(sub->right()); |
| + } return false; |
| + } else { |
| + return false; |
| + } |
| + |
| + if (!constant->HasInteger32Value()) return false; |
| + (*offset_value) = constant->Integer32Value() * sign; |
| + // FIXME(mmassi): decide meaningful bound |
|
Jakob Kummerow
2012/05/08 13:46:26
fix this before landing? :-)
Massi
2012/05/14 13:48:52
Done.
|
| + if ((*offset_value) >= 1 << 8 || (*offset_value) < 0) return false; |
| + array_operation->SetOperandAt(index_position, subexpression); |
| + if (index->HasNoUses()) { |
| + index->DeleteAndReplaceWith(NULL); |
| + counters->array_indexes_removed()->Increment(); |
|
Jakob Kummerow
2012/05/08 13:46:26
Is it useful to keep those counters, or have they
Massi
2012/05/14 13:48:52
Done.
|
| + } |
| + counters->array_indexes_dehoisted()->Increment(); |
| + return true; |
| +} |
| + |
| + |
| +void HGraph::DehoistSimpleArrayIndexComputations() { |
| + if (!FLAG_array_index_dehoisting) return; |
| + |
| + HPhase phase("H_Dehoist index computations", this); |
| + for (int i = 0; i < blocks()->length(); ++i) { |
| + for (HInstruction* instr = blocks()->at(i)->first(); |
| + instr != NULL; |
| + instr = instr->next()) { |
| + int32_t index_offset = 0; |
| + if (instr->IsLoadKeyedFastElement()) { |
|
Jakob Kummerow
2012/05/08 13:46:26
This is a lot of duplicate code...
Suggestion:
c
Massi
2012/05/14 13:48:52
Oddly enough, this was my original idea but Sven d
|
| + HLoadKeyedFastElement* operation = |
| + HLoadKeyedFastElement::cast(instr); |
| + if (DehoistArrayIndex(operation, |
| + operation->key(), |
| + 1, |
| + &index_offset, |
| + isolate()->counters())) { |
| + operation->SetIndexOffset(index_offset); |
| + } |
| + } else if (instr->IsLoadKeyedFastDoubleElement()) { |
| + HLoadKeyedFastDoubleElement* operation = |
| + HLoadKeyedFastDoubleElement::cast(instr); |
| + if (DehoistArrayIndex(operation, |
| + operation->key(), |
| + 1, |
| + &index_offset, |
| + isolate()->counters())) { |
| + operation->SetIndexOffset(index_offset); |
| + } |
| + } else if (instr->IsLoadKeyedSpecializedArrayElement()) { |
| + HLoadKeyedSpecializedArrayElement* operation = |
| + HLoadKeyedSpecializedArrayElement::cast(instr); |
| + if (DehoistArrayIndex(operation, |
| + operation->key(), |
| + 1, |
| + &index_offset, |
| + isolate()->counters())) { |
| + operation->SetIndexOffset(index_offset); |
| + } |
| + } else if (instr->IsStoreKeyedFastElement()) { |
| + HStoreKeyedFastElement* operation = |
| + HStoreKeyedFastElement::cast(instr); |
| + if (DehoistArrayIndex(operation, |
| + operation->key(), |
| + 1, |
| + &index_offset, |
| + isolate()->counters())) { |
| + operation->SetIndexOffset(index_offset); |
| + } |
| + } else if (instr->IsStoreKeyedFastDoubleElement()) { |
| + HStoreKeyedFastDoubleElement* operation = |
| + HStoreKeyedFastDoubleElement::cast(instr); |
| + if (DehoistArrayIndex(operation, |
| + operation->key(), |
| + 1, |
| + &index_offset, |
| + isolate()->counters())) { |
| + operation->SetIndexOffset(index_offset); |
| + } |
| + } else if (instr->IsStoreKeyedSpecializedArrayElement()) { |
| + HStoreKeyedSpecializedArrayElement* operation = |
| + HStoreKeyedSpecializedArrayElement::cast(instr); |
| + if (DehoistArrayIndex(operation, |
| + operation->key(), |
| + 1, |
| + &index_offset, |
| + isolate()->counters())) { |
| + operation->SetIndexOffset(index_offset); |
| + } |
| + } else { |
| + continue; |
| + } |
| + } |
| + } |
| +} |
| + |
| + |
| HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| ASSERT(current_block() != NULL); |
| current_block()->AddInstruction(instr); |