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

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)
@@ -315,6 +315,16 @@
}
+int HValue::UseCountIgnoringInputsRequiringNone() const {
+ int count = 0;
+ for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
+ Representation req = it.value()->RequiredInputRepresentation(it.index());
+ if (!req.IsNone()) count++;
+ }
+ return count;
+}
+
+
HUseListNode* HValue::RemoveUse(HValue* value, int index) {
HUseListNode* previous = NULL;
HUseListNode* current = use_list_;
@@ -1102,7 +1112,105 @@
}
+#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() &&
Vyacheslav Egorov (Google) 2012/07/30 12:01:44 I am a little bit uncomfortable that we apply this
Evan Wallace 2012/07/30 16:43:13 These aren't the only conditions that trigger this
Vyacheslav Egorov (Google) 2012/07/30 16:59:26 I don't dispute that it can be truncated to int32.
Evan Wallace 2012/07/30 19:35:43 I did not realize normal double to integer represe
+ change->from().IsDouble() &&
+ change->to().IsInteger32()) {
+ HDiv* div = HDiv::cast(change->value());
+
+ // We want to be sure that the use count is 1 for div so we can swap it
+ // out, but there may be other instructions (such as HSimulate) that do
+ // not need the resulting value and so shouldn't stop this optimization
+ if (div->UseCountIgnoringInputsRequiringNone() == 1) {
Vyacheslav Egorov (Google) 2012/07/30 12:01:44 I am not sure that your approach to simulates is c
Evan Wallace 2012/07/30 16:43:13 Thanks for pointing this out! I guess I don't unde
Vyacheslav Egorov (Google) 2012/07/30 16:59:26 Simulate is a pseudo-instruction that "simulates"
+ 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
+ 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(new_div);
+ 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 +1317,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