Revision: 24135
Author:   [email protected]
Date:     Tue Sep 23 08:16:54 2014 UTC
Log:      Extend JSBuiltinReducer to cover Math.max as well.

[email protected]
TEST=cctest/test-js-typed-lowering/BuiltinMathMax

Review URL: https://codereview.chromium.org/590993003
https://code.google.com/p/v8/source/detail?r=24135

Modified:
 /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc
 /branches/bleeding_edge/src/compiler/js-builtin-reducer.h
 /branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc

=======================================
--- /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc Fri Sep 19 16:35:42 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc Tue Sep 23 08:16:54 2014 UTC
@@ -47,24 +47,36 @@
Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value().handle());
     return function->shared()->builtin_function_id();
   }
+
+  // Determines whether the call takes zero inputs.
+  bool InputsMatchZero() { return GetJSCallArity() == 0; }

   // Determines whether the call takes one input of the given type.
-  bool InputsMatch(Type* t1) {
+  bool InputsMatchOne(Type* t1) {
     return GetJSCallArity() == 1 &&
            NodeProperties::GetBounds(GetJSCallInput(0)).upper->Is(t1);
   }

   // Determines whether the call takes two inputs of the given types.
-  bool InputsMatch(Type* t1, Type* t2) {
+  bool InputsMatchTwo(Type* t1, Type* t2) {
     return GetJSCallArity() == 2 &&
            NodeProperties::GetBounds(GetJSCallInput(0)).upper->Is(t1) &&
            NodeProperties::GetBounds(GetJSCallInput(1)).upper->Is(t2);
   }
+
+  // Determines whether the call takes inputs all of the given type.
+  bool InputsMatchAll(Type* t) {
+    for (int i = 0; i < GetJSCallArity(); i++) {
+      if (!NodeProperties::GetBounds(GetJSCallInput(i)).upper->Is(t)) {
+        return false;
+      }
+    }
+    return true;
+  }

   Node* left() { return GetJSCallInput(0); }
   Node* right() { return GetJSCallInput(1); }

- protected:
   int GetJSCallArity() {
     DCHECK_EQ(IrOpcode::kJSCallFunction, node_->opcode());
     // Skip first (i.e. callee) and second (i.e. receiver) operand.
@@ -81,12 +93,44 @@
  private:
   Node* node_;
 };
+
+
+// ECMA-262, section 15.8.2.11.
+Reduction JSBuiltinReducer::ReduceMathMax(Node* node) {
+  JSCallReduction r(node);
+  if (r.InputsMatchZero()) {
+    // Math.max() -> -Infinity
+    return Replace(jsgraph()->Constant(-V8_INFINITY));
+  }
+  if (r.InputsMatchOne(Type::Number())) {
+    // Math.max(a:number) -> a
+    return Replace(r.left());
+  }
+  if (r.InputsMatchAll(Type::Integral32())) {
+    // Math.max(a:int32, b:int32, ...)
+    Node* value = r.GetJSCallInput(0);
+    for (int i = 1; i < r.GetJSCallArity(); i++) {
+      Node* p = r.GetJSCallInput(i);
+      Node* control = graph()->start();
+ Node* tag = graph()->NewNode(simplified()->NumberLessThan(), value, p);
+
+      Node* branch = graph()->NewNode(common()->Branch(), tag, control);
+      Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
+      Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
+ Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+
+ value = graph()->NewNode(common()->Phi(kMachNone, 2), p, value, merge);
+    }
+    return Replace(value);
+  }
+  return NoChange();
+}


 // ES6 draft 08-24-14, section 20.2.2.19.
 Reduction JSBuiltinReducer::ReduceMathImul(Node* node) {
   JSCallReduction r(node);
-  if (r.InputsMatch(Type::Integral32(), Type::Integral32())) {
+  if (r.InputsMatchTwo(Type::Integral32(), Type::Integral32())) {
     // Math.imul(a:int32, b:int32) -> Int32Mul(a, b)
Node* value = graph()->NewNode(machine()->Int32Mul(), r.left(), r.right());
     return Replace(value);
@@ -101,6 +145,8 @@
   // Dispatch according to the BuiltinFunctionId if present.
   if (!r.HasBuiltinFunctionId()) return NoChange();
   switch (r.GetBuiltinFunctionId()) {
+    case kMathMax:
+      return ReplaceWithPureReduction(node, ReduceMathMax(node));
     case kMathImul:
       return ReplaceWithPureReduction(node, ReduceMathImul(node));
     default:
=======================================
--- /branches/bleeding_edge/src/compiler/js-builtin-reducer.h Fri Sep 19 15:02:58 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-builtin-reducer.h Tue Sep 23 08:16:54 2014 UTC
@@ -24,11 +24,13 @@
   virtual Reduction Reduce(Node* node) OVERRIDE;

  private:
-  Graph* graph() { return jsgraph_->graph(); }
-  CommonOperatorBuilder* common() { return jsgraph_->common(); }
-  MachineOperatorBuilder* machine() { return jsgraph_->machine(); }
+  JSGraph* jsgraph() const { return jsgraph_; }
+  Graph* graph() const { return jsgraph_->graph(); }
+  CommonOperatorBuilder* common() const { return jsgraph_->common(); }
+  MachineOperatorBuilder* machine() const { return jsgraph_->machine(); }
   SimplifiedOperatorBuilder* simplified() { return &simplified_; }

+  Reduction ReduceMathMax(Node* node);
   Reduction ReduceMathImul(Node* node);

   JSGraph* jsgraph_;
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc Fri Sep 19 15:02:58 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc Tue Sep 23 08:16:54 2014 UTC
@@ -1383,6 +1383,48 @@
     }
   }
 }
+
+
+TEST(BuiltinMathMax) {
+  JSTypedLoweringTester R;
+
+  Node* fun = R.HeapConstant(handle(R.isolate->context()->math_max_fun()));
+ Node* call = R.graph.NewNode(R.javascript.Call(2, NO_CALL_FUNCTION_FLAGS),
+                               fun, R.UndefinedConstant());
+  Node* r = R.reduce(call);
+  R.CheckNumberConstant(-V8_INFINITY, r);
+
+  for (size_t i = 0; i < arraysize(kNumberTypes); i++) {
+    Type* t0 = kNumberTypes[i];
+    Node* p0 = R.Parameter(t0, 0);
+ Node* call = R.graph.NewNode(R.javascript.Call(3, NO_CALL_FUNCTION_FLAGS),
+                                 fun, R.UndefinedConstant(), p0);
+    Node* r = R.reduce(call);
+    CHECK_EQ(IrOpcode::kParameter, r->opcode());
+    CHECK_EQ(p0, r);
+  }
+
+  for (size_t i = 0; i < arraysize(kNumberTypes); i++) {
+    for (size_t j = 0; j < arraysize(kNumberTypes); j++) {
+      Type* t0 = kNumberTypes[i];
+      Node* p0 = R.Parameter(t0, 0);
+      Type* t1 = kNumberTypes[j];
+      Node* p1 = R.Parameter(t1, 1);
+ Node* call = R.graph.NewNode(R.javascript.Call(4, NO_CALL_FUNCTION_FLAGS),
+                                   fun, R.UndefinedConstant(), p0, p1);
+      Node* r = R.reduce(call);
+
+      if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
+        CHECK_EQ(IrOpcode::kPhi, r->opcode());
+        CHECK(p0 == r->InputAt(0) || p1 == r->InputAt(0));
+        CHECK(p1 == r->InputAt(1) || p0 == r->InputAt(1));
+      } else {
+        CHECK_EQ(IrOpcode::kJSCallFunction, r->opcode());
+        CHECK_EQ(call, r);
+      }
+    }
+  }
+}


 TEST(BuiltinMathImul) {

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to