Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Unified Diff: src/hydrogen-instructions.cc

Issue 12377072: Handling expression decomposition and array bounds check hoisting: working code with lots of debugg… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased on master and fixed conflicts. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen-instructions.cc
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 20e41bc79a72f80b4a41f326cf0cc6e345711992..2aab3696519f242d40280aedfe199da82e68c63e 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -167,6 +167,116 @@ void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) {
}
+// This method is recursive but it is guaranteed to terminate because
+// RedefinedOperand() always dominates "this".
+bool HValue::IsRelationTrue(NumericRelation relation,
+ HValue* other,
+ int offset,
+ int scale) {
+ if (this == other) {
+ return NumericRelation::Eq().Implies(relation);
+ }
+
+ // Test the direct relation.
+ if (IsRelationTrueInternal(relation, other, offset, scale)) return true;
+
+ // If scale is 0 try the reversed relation.
+ if (scale == 0 &&
+ // TODO(mmassi): do we need the full, recursive IsRelationTrue?
+ other->IsRelationTrueInternal(relation.Reversed(), this, -offset)) {
+ return true;
+ }
+
+ // Try decomposition (but do not accept scaled compounds).
+ DecompositionResult decomposition;
+ if (TryDecompose(&decomposition) &&
+ decomposition.scale() == 0 &&
+ decomposition.base()->IsRelationTrue(relation, other,
+ offset + decomposition.offset(),
+ scale)) {
+ return true;
+ }
+
+ // Pass the request to the redefined value.
+ HValue* redefined = RedefinedOperand();
+ return redefined != NULL && redefined->IsRelationTrue(relation, other,
+ offset, scale);
+}
+
+
+bool HValue::TryGuaranteeRange(HValue* upper_bound) {
+ RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound);
+ TryGuaranteeRangeRecursive(&context);
+ bool result = context.is_range_satisfied();
+ if (result) {
+ context.lower_bound_guarantee()->SetResponsibilityForRange(DIRECTION_LOWER);
+ context.upper_bound_guarantee()->SetResponsibilityForRange(DIRECTION_UPPER);
+ }
+ return result;
+}
+
+
+void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) {
+ // Check if we already know that this value satisfies the lower bound.
+ if (context->lower_bound_guarantee() == NULL) {
+ if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(),
+ context->offset(), context->scale())) {
+ context->set_lower_bound_guarantee(this);
+ }
+ }
+
+ // Check if we already know that this value satisfies the upper bound.
+ if (context->upper_bound_guarantee() == NULL) {
+ if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(),
+ context->offset(), context->scale()) ||
+ (context->scale() == 0 &&
+ context->upper_bound()->IsRelationTrue(NumericRelation::Gt(),
+ this, -context->offset()))) {
+ context->set_upper_bound_guarantee(this);
+ }
+ }
+
+ if (context->is_range_satisfied()) return;
+
+ // See if our RedefinedOperand() satisfies the constraints.
+ if (RedefinedOperand() != NULL) {
+ RedefinedOperand()->TryGuaranteeRangeRecursive(context);
+ }
+ if (context->is_range_satisfied()) return;
+
+ // See if the constraints can be satisfied by decomposition.
+ DecompositionResult decomposition;
+ if (TryDecompose(&decomposition)) {
+ context->swap_candidate(&decomposition);
+ context->candidate()->TryGuaranteeRangeRecursive(context);
+ context->swap_candidate(&decomposition);
+ }
+ if (context->is_range_satisfied()) return;
+
+ // Try to modify this to satisfy the constraint.
+
+ TryGuaranteeRangeChanging(context);
+}
+
+
+RangeEvaluationContext::RangeEvaluationContext(HValue* value, HValue* upper)
+ : lower_bound_(upper->block()->graph()->GetConstant0()),
+ lower_bound_guarantee_(NULL),
+ candidate_(value),
+ upper_bound_(upper),
+ upper_bound_guarantee_(NULL),
+ offset_(0),
+ scale_(0) {
+}
+
+
+HValue* RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) {
+ return guarantee->IsBoundsCheckBaseIndexInformation()
+ ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check()
+ : guarantee;
+}
+
+
static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
if (result > kMaxInt) {
*overflow = true;
@@ -888,25 +998,115 @@ void HBinaryCall::PrintDataTo(StringStream* stream) {
}
+void HBoundsCheck::TryGuaranteeRangeChanging(RangeEvaluationContext* context) {
+ if (context->candidate()->ActualValue() != base()->ActualValue() ||
+ context->scale() < scale()) {
+ return;
+ }
+
+ // TODO(mmassi)
+ // Instead of checking for "same basic block" we should check for
+ // "dominates and postdominates".
+ if (context->upper_bound() == length() &&
+ context->lower_bound_guarantee() != NULL &&
+ context->lower_bound_guarantee() != this &&
+ context->lower_bound_guarantee()->block() != block() &&
+ offset() < context->offset() &&
+ index_can_increase() &&
+ context->upper_bound_guarantee() == NULL) {
+ offset_ = context->offset();
+ SetResponsibilityForRange(DIRECTION_UPPER);
+ context->set_upper_bound_guarantee(this);
+ } else if (context->upper_bound_guarantee() != NULL &&
+ context->upper_bound_guarantee() != this &&
+ context->upper_bound_guarantee()->block() != block() &&
+ offset() > context->offset() &&
+ index_can_decrease() &&
+ context->lower_bound_guarantee() == NULL) {
+ offset_ = context->offset();
+ SetResponsibilityForRange(DIRECTION_LOWER);
+ context->set_lower_bound_guarantee(this);
+ }
+}
+
+
+void HBoundsCheck::ApplyIndexChange() {
+ if (skip_check()) return;
+
+ DecompositionResult decomposition;
+ bool index_is_decomposable = index()->TryDecompose(&decomposition);
+ if (index_is_decomposable) {
+ ASSERT(decomposition.base() == base());
+ if (decomposition.offset() == offset() &&
+ decomposition.scale() == scale()) return;
+ } else {
+ return;
+ }
+
+ ReplaceAllUsesWith(index());
+
+ HValue* current_index = decomposition.base();
+ int actual_offset = decomposition.offset() + offset();
+ int actual_scale = decomposition.scale() + scale();
+
+ if (actual_offset != 0) {
+ HConstant* add_offset = new(block()->graph()->zone()) HConstant(
+ actual_offset, index()->representation());
+ add_offset->InsertBefore(this);
+ HInstruction* add = HAdd::New(block()->graph()->zone(),
+ block()->graph()->GetInvalidContext(), current_index, add_offset);
+ add->InsertBefore(this);
+ add->AssumeRepresentation(index()->representation());
+ current_index = add;
+ }
+
+ if (actual_scale != 0) {
+ HConstant* sar_scale = new(block()->graph()->zone()) HConstant(
+ actual_scale, index()->representation());
+ sar_scale->InsertBefore(this);
+ HInstruction* sar = HSar::New(block()->graph()->zone(),
+ block()->graph()->GetInvalidContext(), current_index, sar_scale);
+ sar->InsertBefore(this);
+ sar->AssumeRepresentation(index()->representation());
+ current_index = sar;
+ }
+
+ SetOperandAt(0, current_index);
+
+ base_ = NULL;
+ offset_ = 0;
+ scale_ = 0;
+ responsibility_direction_ = DIRECTION_NONE;
+}
+
+
void HBoundsCheck::AddInformativeDefinitions() {
// TODO(mmassi): Executing this code during AddInformativeDefinitions
// is a hack. Move it to some other HPhase.
- if (index()->IsRelationTrue(NumericRelation::Ge(),
- block()->graph()->GetConstant0()) &&
- index()->IsRelationTrue(NumericRelation::Lt(), length())) {
- set_skip_check(true);
+ if (FLAG_array_bounds_checks_elimination) {
+ if (index()->TryGuaranteeRange(length())) {
+ set_skip_check(true);
+ }
+ if (DetectCompoundIndex()) {
+ HBoundsCheckBaseIndexInformation* base_index_info =
+ new(block()->graph()->zone())
+ HBoundsCheckBaseIndexInformation(this);
+ base_index_info->InsertAfter(this);
+ }
}
}
bool HBoundsCheck::IsRelationTrueInternal(NumericRelation relation,
- HValue* related_value) {
+ HValue* related_value,
+ int offset,
+ int scale) {
if (related_value == length()) {
// A HBoundsCheck is smaller than the length it compared against.
- return NumericRelation::Lt().Implies(relation);
+ return NumericRelation::Lt().CompoundImplies(relation, 0, 0, offset, scale);
} else if (related_value == block()->graph()->GetConstant0()) {
// A HBoundsCheck is greater than or equal to zero.
- return NumericRelation::Ge().Implies(relation);
+ return NumericRelation::Ge().CompoundImplies(relation, 0, 0, offset, scale);
} else {
return false;
}
@@ -917,6 +1117,15 @@ void HBoundsCheck::PrintDataTo(StringStream* stream) {
index()->PrintNameTo(stream);
stream->Add(" ");
length()->PrintNameTo(stream);
+ if (base() != NULL && (offset() != 0 || scale() != 0)) {
+ stream->Add(" base: ((");
+ if (base() != index()) {
+ index()->PrintNameTo(stream);
+ } else {
+ stream->Add("index");
+ }
+ stream->Add(" + %d) >> %d)", offset(), scale());
+ }
if (skip_check()) {
stream->Add(" [DISABLED]");
}
@@ -946,6 +1155,33 @@ void HBoundsCheck::InferRepresentation(HInferRepresentation* h_infer) {
}
+bool HBoundsCheckBaseIndexInformation::IsRelationTrueInternal(
+ NumericRelation relation,
+ HValue* related_value,
+ int offset,
+ int scale) {
+ if (related_value == bounds_check()->length()) {
+ return NumericRelation::Lt().CompoundImplies(
+ relation,
+ bounds_check()->offset(), bounds_check()->scale(), offset, scale);
+ } else if (related_value == block()->graph()->GetConstant0()) {
+ return NumericRelation::Ge().CompoundImplies(
+ relation,
+ bounds_check()->offset(), bounds_check()->scale(), offset, scale);
+ } else {
+ return false;
+ }
+}
+
+
+void HBoundsCheckBaseIndexInformation::PrintDataTo(StringStream* stream) {
+ stream->Add("base: ");
+ base_index()->PrintNameTo(stream);
+ stream->Add(", check: ");
+ base_index()->PrintNameTo(stream);
+}
+
+
void HCallConstantFunction::PrintDataTo(StringStream* stream) {
if (IsApplyFunction()) {
stream->Add("optimized apply ");
@@ -1611,7 +1847,10 @@ void HPhi::AddInformativeDefinitions() {
}
-bool HPhi::IsRelationTrueInternal(NumericRelation relation, HValue* other) {
+bool HPhi::IsRelationTrueInternal(NumericRelation relation,
+ HValue* other,
+ int offset,
+ int scale) {
if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false;
SetFlag(kNumericConstraintEvaluationInProgress);
@@ -1620,7 +1859,7 @@ bool HPhi::IsRelationTrueInternal(NumericRelation relation, HValue* other) {
// Skip OSR entry blocks
if (OperandAt(i)->block()->is_osr_entry()) continue;
- if (!OperandAt(i)->IsRelationTrue(relation, other)) {
+ if (!OperandAt(i)->IsRelationTrue(relation, other, offset, scale)) {
result = false;
break;
}
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698