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 12315005: Constant fold math and string operations. (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 2d4b82bf16ba1efe84bbc0915111921069ad9384..788dd67e5e5ab9b71bfe2b3c92349d3faf474e1a 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -27,6 +27,7 @@
#include "v8.h"
+#include "double.h"
#include "factory.h"
#include "hydrogen.h"
@@ -2755,7 +2756,7 @@ HInstruction* HInstr::New##HInstr(Zone* zone, \
HValue* context, \
HValue* left, \
HValue* right) { \
- if (left->IsConstant() && right->IsConstant()) { \
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) { \
HConstant* c_left = HConstant::cast(left); \
HConstant* c_right = HConstant::cast(right); \
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
@@ -2777,11 +2778,177 @@ DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR(HSub, -)
#undef DEFINE_NEW_H_SIMPLE_ARITHMETIC_INSTR
+HInstruction* HStringAdd::NewHStringAdd(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right) {
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
+ HConstant* c_right = HConstant::cast(right);
+ HConstant* c_left = HConstant::cast(left);
+ if (c_left->HasStringValue() && c_right->HasStringValue()) {
+ return new(zone) HConstant(FACTORY->NewConsString(c_left->StringValue(),
+ c_right->StringValue()),
+ Representation::Tagged());
+ }
+ }
+ return new(zone) HStringAdd(context, left, right);
+}
+
+
+HInstruction* HStringCharFromCode::NewHStringCharFromCode(Zone* zone,
+ HValue* context,
+ HValue* char_code) {
+ if (FLAG_fold_constants && char_code->IsConstant()) {
+ HConstant* c_code = HConstant::cast(char_code);
+ if (c_code->HasNumberValue()) {
+ if (isfinite(c_code->DoubleValue())) {
+ uint32_t code = c_code->NumberValueAsInteger32() & 0xffff;
+ return new(zone) HConstant(LookupSingleCharacterStringFromCode(code),
+ Representation::Tagged());
+ }
+ return new(zone) HConstant(FACTORY->empty_string(),
+ Representation::Tagged());
+ }
+ }
+ return new(zone) HStringCharFromCode(context, char_code);
+}
+
+
+HInstruction* HStringLength::NewHStringLength(Zone* zone, HValue* string) {
+ if (FLAG_fold_constants && string->IsConstant()) {
+ HConstant* c_string = HConstant::cast(string);
+ if (c_string->HasStringValue()) {
+ return H_CONSTANT_INT32(c_string->StringValue()->length());
+ }
+ }
+ return new(zone) HStringLength(string);
+}
+
+
+HInstruction* HUnaryMathOperation::NewHUnaryMathOperation(
+ Zone* zone, HValue* context, HValue* value, BuiltinFunctionId op) {
+ do {
+ if (!FLAG_fold_constants) break;
+ if (!value->IsConstant()) break;
+ HConstant* constant = HConstant::cast(value);
+ if (!constant->HasNumberValue()) break;
+ double d = constant->DoubleValue();
+ if (isnan(d)) { // NaN poisons everything.
+ return H_CONSTANT_DOUBLE(OS::nan_value());
+ }
+ if (isinf(d)) { // +Inifinity and -Infinity.
Jakob Kummerow 2013/02/20 15:31:04 nit: "Inifinity" sounds nice, but has an "i" too m
Yang 2013/02/20 17:51:15 Done.
+ switch (op) {
+ case kMathSin:
+ case kMathCos:
+ case kMathTan:
+ return H_CONSTANT_DOUBLE(OS::nan_value());
+ case kMathExp:
+ return H_CONSTANT_DOUBLE((d > 0.0) ? d : 0.0);
+ case kMathLog:
+ case kMathSqrt:
+ return H_CONSTANT_DOUBLE((d > 0.0) ? d : OS::nan_value());
+ case kMathPowHalf:
+ case kMathAbs:
+ return H_CONSTANT_DOUBLE((d > 0.0) ? d : -d);
+ case kMathRound:
+ case kMathFloor:
+ return H_CONSTANT_DOUBLE(d);
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ switch (op) {
+ case kMathSin:
+ return H_CONSTANT_DOUBLE(fast_sin(d));
+ case kMathCos:
+ return H_CONSTANT_DOUBLE(fast_cos(d));
+ case kMathTan:
+ return H_CONSTANT_DOUBLE(fast_tan(d));
+ case kMathExp:
+ return H_CONSTANT_DOUBLE(fast_exp(d));
+ case kMathLog:
+ return H_CONSTANT_DOUBLE(fast_log(d));
+ case kMathSqrt:
+ return H_CONSTANT_DOUBLE(fast_sqrt(d));
+ case kMathPowHalf:
+ return H_CONSTANT_DOUBLE(power_double_double(d, 0.5));
+ case kMathAbs:
+ return H_CONSTANT_DOUBLE((d >= 0.0) ? d + 0.0 : -d);
+ case kMathRound:
+ if (d >= -0.5 && d < 0.0) return H_CONSTANT_DOUBLE(-0.0);
+ // Doubles are represented as Significant * 2 ^ Exponent. If the
+ // Exponent is not negative, the double value is already an integer.
+ if (Double(d).Exponent() >= 0) return H_CONSTANT_DOUBLE(d);
Jakob Kummerow 2013/02/20 15:31:04 I'm not convinced having this "fast path" is worth
Yang 2013/02/20 17:51:15 This is not a fast path, but for correctness. The
+ return H_CONSTANT_DOUBLE(floor(d + 0.5));
+ case kMathFloor:
+ return H_CONSTANT_DOUBLE(floor(d));
+ default:
+ UNREACHABLE();
+ break;
+ }
+ } while (false);
+ return new(zone) HUnaryMathOperation(context, value, op);
+}
+
+
+HInstruction* HPower::NewHPower(Zone* zone,
+ HValue* left,
+ HValue* right) {
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
+ HConstant* c_left = HConstant::cast(left);
+ HConstant* c_right = HConstant::cast(right);
+ if (c_left->HasNumberValue() && c_right->HasNumberValue()) {
+ double result = power_helper(c_left->DoubleValue(),
+ c_right->DoubleValue());
+ return H_CONSTANT_DOUBLE(isnan(result) ? OS::nan_value() : result);
+ }
+ }
+ return new(zone) HPower(left, right);
+}
+
+
+HInstruction* HMathMinMax::NewHMathMinMax(Zone* zone,
+ HValue* context,
+ HValue* left,
+ HValue* right,
+ Operation op) {
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
+ HConstant* c_left = HConstant::cast(left);
+ HConstant* c_right = HConstant::cast(right);
+ if (c_left->HasNumberValue() && c_right->HasNumberValue()) {
+ double d_left = c_left->DoubleValue();
+ double d_right = c_right->DoubleValue();
+ if (op == kMathMin) {
Jakob Kummerow 2013/02/20 15:31:04 nit: double space
+ if (d_left > d_right) return H_CONSTANT_DOUBLE(d_right);
+ if (d_left < d_right) return H_CONSTANT_DOUBLE(d_left);
+ if (d_left == d_right) {
+ // Handle +0 and -0.
+ return H_CONSTANT_DOUBLE((Double(d_left).Sign() == -1) ? d_left
+ : d_right);
+ }
+ } else {
+ if (d_left < d_right) return H_CONSTANT_DOUBLE(d_right);
+ if (d_left > d_right) return H_CONSTANT_DOUBLE(d_left);
+ if (d_left == d_right) {
+ // Handle +0 and -0.
+ return H_CONSTANT_DOUBLE((Double(d_left).Sign() == -1) ? d_right
+ : d_left);
+ }
+ }
+ // All comparisons failed, must be NaN.
+ return H_CONSTANT_DOUBLE(OS::nan_value());
+ }
+ }
+ return new(zone) HMathMinMax(context, left, right, op);
+}
+
+
HInstruction* HMod::NewHMod(Zone* zone,
HValue* context,
HValue* left,
HValue* right) {
- if (left->IsConstant() && right->IsConstant()) {
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
HConstant* c_left = HConstant::cast(left);
HConstant* c_right = HConstant::cast(right);
if (c_left->HasInteger32Value() && c_right->HasInteger32Value()) {
@@ -2805,7 +2972,7 @@ HInstruction* HDiv::NewHDiv(Zone* zone,
HValue* left,
HValue* right) {
// If left and right are constant values, try to return a constant value.
- if (left->IsConstant() && right->IsConstant()) {
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
HConstant* c_left = HConstant::cast(left);
HConstant* c_right = HConstant::cast(right);
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
@@ -2815,6 +2982,10 @@ HInstruction* HDiv::NewHDiv(Zone* zone,
return H_CONSTANT_INT32(static_cast<int32_t>(double_res));
}
return H_CONSTANT_DOUBLE(double_res);
+ } else {
+ int sign = Double(c_left->DoubleValue()).Sign() *
+ Double(c_right->DoubleValue()).Sign(); // Right could be -0.
+ return H_CONSTANT_DOUBLE(sign * V8_INFINITY);
}
}
}
@@ -2827,7 +2998,7 @@ HInstruction* HBitwise::NewHBitwise(Zone* zone,
HValue* context,
HValue* left,
HValue* right) {
- if (left->IsConstant() && right->IsConstant()) {
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
HConstant* c_left = HConstant::cast(left);
HConstant* c_right = HConstant::cast(right);
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {
@@ -2860,7 +3031,7 @@ HInstruction* HInstr::New##HInstr(Zone* zone, \
HValue* context, \
HValue* left, \
HValue* right) { \
- if (left->IsConstant() && right->IsConstant()) { \
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) { \
HConstant* c_left = HConstant::cast(left); \
HConstant* c_right = HConstant::cast(right); \
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) { \
@@ -2883,7 +3054,7 @@ HInstruction* HShr::NewHShr(Zone* zone,
HValue* context,
HValue* left,
HValue* right) {
- if (left->IsConstant() && right->IsConstant()) {
+ if (FLAG_fold_constants && left->IsConstant() && right->IsConstant()) {
HConstant* c_left = HConstant::cast(left);
HConstant* c_right = HConstant::cast(right);
if ((c_left->HasNumberValue() && c_right->HasNumberValue())) {

Powered by Google App Engine
This is Rietveld 408576698