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

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: Created 7 years, 10 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
Index: src/hydrogen-instructions.cc
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 52eada41f5df8213abaaa369fcd8aa1f9d549ea5..34a59848579e7ee995ebe72688f238280b4bf510 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -160,6 +160,122 @@ void HValue::AddDependantsToWorklist(HInferRepresentation* h_infer) {
}
+bool HValue::TryGuaranteeRange(HValue* upper_bound) {
+ RangeEvaluationContext context = RangeEvaluationContext(this, upper_bound);
+ TryGuaranteeRangeRecursive(&context);
+ return context.RangeSatisfied();
+}
+
+
+void HValue::TryGuaranteeRangeRecursive(RangeEvaluationContext* context) {
+
+ if (FLAG_log_abcd) {
+ PrintF(" +++ TryGuaranteeRangeRecursive(");
+ SimplyPrint();
+ PrintF(") {[LOWER ");
+ if (context->lower_check_satisfied()) {
+ context->lower_check_guarantee()->SimplyPrint();
+ } else {
+ PrintF("NULL");
+ }
+ PrintF("] ");
+ context->lower_bound()->SimplyPrint();
+ PrintF(" <= ((x + %d) >> %d) ", context->offset(), context->scale());
+ context->upper_bound()->SimplyPrint();
+ PrintF(" [UPPER ");
+ if (context->upper_check_satisfied()) {
+ context->upper_check_guarantee()->SimplyPrint();
+ } else {
+ PrintF("NULL");
+ }
+ PrintF("]}\n");
+ }
+
+
+ // Try to satisfy the lower bound on this value
Jakob Kummerow 2013/03/11 11:55:02 better comment: // Check if we already know that t
+ if (!context->lower_check_satisfied()) {
+ if (IsRelationTrueInternal(NumericRelation::Ge(), context->lower_bound(),
+ context->offset(), context->scale())) {
+
+ if (FLAG_log_abcd)
+ PrintF(" ___ TryGuaranteeRangeRecursive(LOWER TRUE)\n");
+
+ context->set_lower_check_guarantee(this);
+ }
+ }
+
+ // Try to satisfy the upper bound on this value
Jakob Kummerow 2013/03/11 11:55:02 better comment: // Check if we already know that t
+ if (!context->upper_check_satisfied()) {
+ if (IsRelationTrueInternal(NumericRelation::Lt(), context->upper_bound(),
+ context->offset(), context->scale()) ||
+ (context->scale() == 0 &&
+ context->upper_bound()->IsRelationTrue(NumericRelation::Gt(),
+ this, -context->offset()))) {
+
+ if (FLAG_log_abcd)
+ PrintF(" ___ TryGuaranteeRangeRecursive(UPPER TRUE)\n");
+
+ context->set_upper_check_guarantee(this);
+ }
+ }
+
+ if (context->RangeSatisfied()) return;
+
+ // See if our RedefinedOperand() satisfies the constraints.
+ if (RedefinedOperand() != NULL) {
+ RedefinedOperand()->TryGuaranteeRangeRecursive(context);
+ }
+ if (context->RangeSatisfied()) return;
+
+ // See if the constraints can be satisfied by decomposition.
Jakob Kummerow 2013/03/11 11:55:02 Why does this need to happen in the recursive call
Massi 2013/03/13 15:58:14 Because every definition of this value could be de
Jakob Kummerow 2013/03/14 12:50:08 OK, I see.
+ HValue* base = NULL;
+ int offset = context->offset();
+ int scale = context->scale();
+ if (context->origin()->TryDecompose(&base, &offset, &scale)) {
+ context->swap_origin(base, offset, scale);
+
+ if (FLAG_log_abcd)
+ PrintF(" ___ TryGuaranteeRangeRecursive(DECOMPOSE START)\n");
+
+ context->origin()->TryGuaranteeRangeRecursive(context);
+
+ if (FLAG_log_abcd)
+ PrintF(" ___ TryGuaranteeRangeRecursive(DECOMPOSE END [%s])\n",
+ context->RangeSatisfied() ? "!" : "x");
+
+ context->swap_origin(base, offset, scale);
+ }
+ if (context->RangeSatisfied()) return;
+
+ // Try to modify this to satisfy the constraint.
+ TryGuaranteeRangeInner(context);
+
+ if (FLAG_log_abcd) {
+ PrintF(" >>> TryGuaranteeRangeRecursive(");
+ SimplyPrint();
+ PrintF("): %s\n", context->RangeSatisfied() ? "TRUE" : "FALSE");
+ }
+}
+
+
+HValue::RangeEvaluationContext::RangeEvaluationContext(
+ HValue* value, HValue* upper)
Jakob Kummerow 2013/03/11 11:55:02 for method/function declarations (as opposed to ca
+ : lower_bound_(upper->block()->graph()->GetConstant0()),
+ lower_check_guarantee_(NULL),
+ origin_(value),
+ upper_bound_(upper),
+ upper_check_guarantee_(NULL),
+ offset_(0), scale_(0) {
Jakob Kummerow 2013/03/11 11:55:02 let's give each initializer its own line.
+}
+
+
+HValue* HValue::RangeEvaluationContext::ConvertGuarantee(HValue* guarantee) {
Jakob Kummerow 2013/03/11 11:55:02 This method is simple enough to live in the .h fil
Massi 2013/03/13 15:58:14 But it needs to access HBoundsCheckBaseIndexInform
+ return guarantee->IsBoundsCheckBaseIndexInformation()
+ ? HBoundsCheckBaseIndexInformation::cast(guarantee)->bounds_check()
+ : guarantee;
+}
+
+
static int32_t ConvertAndSetOverflow(int64_t result, bool* overflow) {
if (result > kMaxInt) {
*overflow = true;
@@ -782,6 +898,17 @@ void HInstruction::Verify() {
cur = cur->previous();
}
// Must reach other operand in the same block!
+
+ if (cur != other_operand) {
+ PrintF("\n !!! !!! !!! !!! !!! ASSERT([BLOCK %d]",
+ other_operand->block()->block_id());
+ other_operand->SimplyPrint();
+ PrintF(" used in index %d does not dominate [BLOCK %d]",
+ i, block()->block_id());
+ SimplyPrint();
+ PrintF(")\n");
+ }
+
ASSERT(cur == other_operand);
}
} else {
@@ -885,25 +1012,188 @@ void HBinaryCall::PrintDataTo(StringStream* stream) {
}
+void HBoundsCheck::TryGuaranteeRangeInner(RangeEvaluationContext* context) {
+ if (FLAG_log_abcd) {
+ PrintF(" +++ HBoundsCheck::TryGuaranteeRangeInner(");
+ SimplyPrint();
+ PrintF(" [LOWER ");
+ if (context->lower_check_satisfied()) {
+ context->lower_check_guarantee()->SimplyPrint();
+ } else {
+ PrintF("NULL");
+ }
+ PrintF("] [UPPER ");
+ if (context->upper_check_satisfied()) {
+ context->upper_check_guarantee()->SimplyPrint();
+ } else {
+ PrintF("NULL");
+ }
+ PrintF("])\n");
+ }
+
+ if (context->origin()->ActualValue() == base()->ActualValue() &&
Jakob Kummerow 2013/03/11 11:55:02 nit: you can avoid one level of nested conditions
+ context->scale() >= scale()) {
+ if (index_has_not_been_changed()) {
+ if (offset() < context->offset()) {
+ change_direction_ = 1;
Jakob Kummerow 2013/03/11 11:55:02 It doesn't seem right that we're always setting ch
+ } else if (offset() > context->offset()) {
+ change_direction_ = -1;
+ }
+ }
+
+ if (context->upper_bound() == length() &&
+ context->lower_check_satisfied() &&
+ context->lower_check_guarantee() != this &&
+ index_can_increase() &&
+ !context->upper_check_satisfied()) {
+ if (offset() < context->offset()) {
Jakob Kummerow 2013/03/11 11:55:02 Since this condition doesn't have an else-branch,
+
+ if (FLAG_log_abcd)
+ PrintF(" ___ HBoundsCheck::TryGuaranteeRangeInner(%s%d CHANGE UPPER(base %s%d[%s%d][%d]), offset %d (was %d), scale %d)\n",
+ representation().Mnemonic(), id(),
+ base()->representation().Mnemonic(), base()->id(),
+ base()->ActualValue()->representation().Mnemonic(), base()->ActualValue()->id(),
+ change_direction_, context->offset(), offset(), scale());
+
+ offset_ = context->offset();
+ change_direction_ = 1;
Jakob Kummerow 2013/03/11 11:55:02 To make it more obvious that this is closely relat
+ context->set_upper_check_guarantee(this);
+ }
+ } else if (context->upper_check_satisfied() &&
+ context->upper_check_guarantee() != this &&
+ index_can_decrease() &&
+ !context->lower_check_satisfied()) {
+ if (offset() > context->offset()) {
+
+ if (FLAG_log_abcd)
+ PrintF(" ___ HBoundsCheck::TryGuaranteeRangeInner(%s%d CHANGE LOWER(base %s%d[%s%d][%d]), offset %d (was %d), scale %d)\n",
+ representation().Mnemonic(), id(),
+ base()->representation().Mnemonic(), base()->id(),
+ base()->ActualValue()->representation().Mnemonic(), base()->ActualValue()->id(),
+ change_direction_, context->offset(), offset(), scale());
+
+ offset_ = context->offset();
+ change_direction_ = -1;
+ context->set_lower_check_guarantee(this);
+ }
+ }
+ }
+}
+
+
+void HBoundsCheck::ApplyIndexChange() {
+ if (HasOriginalIndex() || skip_check()) return;
Jakob Kummerow 2013/03/11 11:55:02 HasOriginalIndex() potentially performs the "index
+
+ HValue* base_index = NULL;
Jakob Kummerow 2013/03/11 11:55:02 I think you mean index_base, index_offset, index_s
+ int base_offset = 0;
+ int base_scale = 0;
+ if (!index()->TryDecompose(&base_index, &base_offset, &base_scale)) return;
+
+ ReplaceAllUsesWith(index());
+
+ HValue* current_index = base_index;
+ int actual_offset = base_offset + offset();
+ int actual_scale = base_scale + scale();
+
+ if (actual_offset != 0) {
+ HConstant* add_offset = new(block()->graph()->zone()) HConstant(
+ actual_offset, index()->representation());
+ add_offset->InsertBefore(this);
+ HAdd* add = new(block()->graph()->zone()) HAdd(
+ 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);
+ HSar* sar = new(block()->graph()->zone()) HSar(
+ block()->graph()->GetInvalidContext(), current_index, sar_scale);
+ sar->InsertBefore(this);
+ sar->AssumeRepresentation(index()->representation());
+ current_index = sar;
+ }
+
+
+ if (FLAG_log_abcd)
+ PrintF("\n !!! !!! !!! HBoundsCheck::ApplyIndexChange(%s%d, index %s%d becomes ((%s%d + %d) >> %d)\n",
+ representation().Mnemonic(), id(),
+ index()->representation().Mnemonic(), index()->id(),
+ current_index->representation().Mnemonic(), current_index->id(),
+ offset(), scale());
+
+ SetOperandAt(0, current_index);
+
+ PrintF(" ");
+
+ base_ = NULL;
Jakob Kummerow 2013/03/11 11:55:02 Is it necessary to do this cleanup?
Massi 2013/03/13 15:58:14 In principle, no, but I don't like leaving meaning
Jakob Kummerow 2013/03/14 12:50:08 I disagree with this reasoning. Resetting those va
+ offset_ = 0;
+ scale_ = 0;
+ change_direction_ = 0;
+}
+
+
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_new_abcd) {
+
+ if (FLAG_log_abcd) {
+ PrintF("\n +++ >>> >>> >>> HBoundsCheck::AddInformativeDefinitions[BLOCK %d](",
+ block()->block_id());
+ SimplyPrint();
+ PrintF(") CHANGE FOR LENGTH %s%d\n",
+ length()->representation().Mnemonic(), length()->id());
+
+ if (index()->TryGuaranteeRange(length())) {
Jakob Kummerow 2013/03/11 11:55:02 This should *not* be inside the if(FLAG_log_abcd)
+ set_skip_check(true);
+ }
+ }
+
+ if (DetectCompoundIndex()) {
+ HBoundsCheckBaseIndexInformation* base_index_info =
+ new(block()->graph()->zone())
+ HBoundsCheckBaseIndexInformation(this);
+ base_index_info->InsertAfter(this);
+ }
+
+ if (FLAG_log_abcd) {
+ PrintF(" +++ <<< <<< <<< HBoundsCheck::AddInformativeDefinitions[BLOCK %d](",
+ block()->block_id());
+ SimplyPrint();
+ if (base() != index()) {
+ PrintF("{base %s%d (actually %s%d)}",
+ base()->representation().Mnemonic(), base()->id(),
+ base()->ActualValue()->representation().Mnemonic(), base()->ActualValue()->id());
+ }
+ PrintF(") LENGTH %s%d CHANGE %s\n",
+ length()->representation().Mnemonic(), length()->id(),
+ skip_check() ? "TRUE" : "FALSE");
+ }
+
+ } else {
+ if (index()->IsRelationTrue(NumericRelation::Ge(),
+ block()->graph()->GetConstant0()) &&
+ index()->IsRelationTrue(NumericRelation::Lt(), length())) {
+ set_skip_check(true);
+ }
}
}
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;
}
@@ -914,6 +1204,15 @@ void HBoundsCheck::PrintDataTo(StringStream* stream) {
index()->PrintNameTo(stream);
stream->Add(" ");
length()->PrintNameTo(stream);
+ if (base() != NULL && (offset() != 0 || scale() != 0)) {
+ stream->Add("base: ((");
Jakob Kummerow 2013/03/11 11:55:02 nit: you probably want to print a space first, i.e
+ if (base() != index()) {
+ index()->PrintNameTo(stream);
+ } else {
+ stream->Add("index");
+ }
+ stream->Add(" + %d) >> %d)", offset(), scale());
+ }
if (skip_check()) {
stream->Add(" [DISABLED]");
}
@@ -941,6 +1240,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 ");
@@ -1604,7 +1930,8 @@ void HPhi::AddInformativeDefinitions() {
}
-bool HPhi::IsRelationTrueInternal(NumericRelation relation, HValue* other) {
+bool HPhi::IsRelationTrueInternal(
+ NumericRelation relation, HValue* other, int offset, int scale) {
Jakob Kummerow 2013/03/11 11:55:02 for method/function declarations (as opposed to ca
if (CheckFlag(kNumericConstraintEvaluationInProgress)) return false;
SetFlag(kNumericConstraintEvaluationInProgress);
@@ -1613,7 +1940,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;
}

Powered by Google App Engine
This is Rietveld 408576698