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

Unified Diff: src/hydrogen-instructions.cc

Issue 10825071: Use integer division in a certain case. (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 8 years, 5 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-codegen-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen-instructions.cc
===================================================================
--- src/hydrogen-instructions.cc (revision 12214)
+++ src/hydrogen-instructions.cc (working copy)
@@ -1102,7 +1102,102 @@
}
+#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
+
+// Return an integer value or NULL, which may involve skipping over a
+// representation change
+static HValue* SimplifiedValueForIntDiv(HValue* value) {
+ if (value->representation().IsInteger32()) {
+ return value;
+ } else if (value->IsConstant() &&
+ HConstant::cast(value)->HasInteger32Value()) {
+ return value;
+ } else if (value->IsChange() &&
+ HChange::cast(value)->from().IsInteger32()) {
+ return HChange::cast(value)->value();
+ }
+ return NULL;
+}
+
+
+// Insert an integer constant into the graph when given a non-integer constant
+static HValue* EnsureIntegerConstantForIntDiv(HValue* value,
+ HInstruction* insertBefore) {
+ if (value->IsConstant() && !value->representation().IsInteger32()) {
+ ASSERT(HConstant::cast(value)->HasInteger32Value());
+ HConstant* constant = HConstant::cast(value)->CopyToRepresentation(
+ Representation::Integer32(), insertBefore->block()->zone());
+ constant->InsertBefore(insertBefore);
+ return constant;
+ }
+ return value;
+}
+
+
+// Try to replace the division of a non-negative integer by a positive integer
+// that is then truncated to an integer with an integer division instruction.
+// This gives a 2x speedup over using double division. Return NULL on failure.
+static HDiv* MaybeConvertToIntDiv(HChange* change, Zone* zone) {
+ if (change->value()->IsDiv() &&
+ HDiv::cast(change->value())->UseCount() == 1 &&
+ change->from().IsDouble() &&
+ change->to().IsInteger32() &&
+ change->CheckFlag(HValue::kTruncatingToInt32)) {
+ HDiv* div = HDiv::cast(change->value());
+ HValue* left = div->left();
+ HValue* right = div->right();
+ HValue* new_left = SimplifiedValueForIntDiv(left);
+ HValue* new_right = SimplifiedValueForIntDiv(right);
+
+ // Only apply this optimization if we know it won't hit any special cases
+ // that would otherwise cause a deopt in the representation change
+ if (new_left != NULL && new_right != NULL &&
+ new_left->range()->lower() >= 0 &&
+ new_right->range()->lower() > 0) {
+ // Change non-integer constants to integer constants
+ new_left = EnsureIntegerConstantForIntDiv(new_left, div);
+ new_right = EnsureIntegerConstantForIntDiv(new_right, div);
+ ASSERT(new_left->representation().IsInteger32());
+ ASSERT(new_right->representation().IsInteger32());
+
+ // Replace this representation change with an integer division
+ HDiv* new_div = new(div->block()->zone()) HDiv(div->context(),
+ new_left, new_right);
+ new_div->AssumeRepresentation(Representation::Integer32());
+ new_div->InsertBefore(div);
+ change->DeleteAndReplaceWith(new_div);
+
+ // Delete unused instructions
+ div->DeleteAndReplaceWith(NULL);
+ if (left->HasNoUses()) left->DeleteAndReplaceWith(NULL);
+ if (right->HasNoUses()) right->DeleteAndReplaceWith(NULL);
+
+ // Tell codegen not to emit code to check for a non-zero remainder.
+ // Codegen can't use CheckUsesForFlag(kTruncatingToInt32) because
+ // that flag is on the HChange instruction which is now deleted.
+ new_div->SetFlag(HValue::kWillTruncateToInt32);
+
+ // Make sure all new values have ranges
+ if (!new_left->HasRange()) new_left->ComputeInitialRange(zone);
+ if (!new_right->HasRange()) new_right->ComputeInitialRange(zone);
+ new_div->ComputeInitialRange(zone);
+ return new_div;
+ }
+ }
+ return NULL;
+}
+
+#endif
+
+
Range* HChange::InferRange(Zone* zone) {
+#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
+ HDiv* div = MaybeConvertToIntDiv(this, zone);
+ if (div != NULL) {
+ return div->range();
+ }
+#endif
+
Range* input_range = value()->range();
if (from().IsInteger32() &&
to().IsTagged() &&
@@ -1209,11 +1304,23 @@
if (right()->range()->Includes(-1) && left()->range()->Includes(kMinInt)) {
SetFlag(HValue::kCanOverflow);
+ } else {
+ ClearFlag(HValue::kCanOverflow);
}
if (!right()->range()->CanBeZero()) {
ClearFlag(HValue::kCanBeDivByZero);
}
+
+ // An exact range can be inferred for division with integer operands
+ if (left()->representation().IsInteger32() &&
+ right()->representation().IsInteger32() &&
+ left()->range()->lower() >= 0 &&
+ right()->range()->lower() > 0) {
+ Range limits(left()->range()->lower() / right()->range()->upper(),
+ left()->range()->upper() / right()->range()->lower());
+ result->Intersect(&limits);
+ }
return result;
} else {
return HValue::InferRange(zone);
« no previous file with comments | « src/hydrogen-instructions.h ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698