Revision: 24095
Author:   [email protected]
Date:     Fri Sep 19 15:02:58 2014 UTC
Log:      Add JSBuiltinReducer for inlining well-known builtins.

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

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

Added:
 /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc
 /branches/bleeding_edge/src/compiler/js-builtin-reducer.h
Modified:
 /branches/bleeding_edge/BUILD.gn
 /branches/bleeding_edge/src/compiler/js-typed-lowering.cc
 /branches/bleeding_edge/src/compiler/js-typed-lowering.h
 /branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc
 /branches/bleeding_edge/tools/gyp/v8.gyp

=======================================
--- /dev/null
+++ /branches/bleeding_edge/src/compiler/js-builtin-reducer.cc Fri Sep 19 15:02:58 2014 UTC
@@ -0,0 +1,111 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/graph-inl.h"
+#include "src/compiler/js-builtin-reducer.h"
+#include "src/compiler/node-matchers.h"
+#include "src/compiler/node-properties-inl.h"
+#include "src/types.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+
+// Helper method that assumes replacement nodes are pure values that don't
+// produce an effect. Replaces {node} with {reduction} and relaxes effects.
+static Reduction ReplaceWithPureReduction(Node* node, Reduction reduction) {
+  if (reduction.Changed()) {
+    NodeProperties::ReplaceWithValue(node, reduction.replacement());
+    return reduction;
+  }
+  return Reducer::NoChange();
+}
+
+
+// Helper class to access JSCallFunction nodes that are potential candidates
+// for reduction when they have a BuiltinFunctionId associated with them.
+class JSCallReduction {
+ public:
+  explicit JSCallReduction(Node* node) : node_(node) {}
+
+ // Determines whether the node is a JSCallFunction operation that targets a
+  // constant callee being a well-known builtin with a BuiltinFunctionId.
+  bool HasBuiltinFunctionId() {
+    if (node_->opcode() != IrOpcode::kJSCallFunction) return false;
+ HeapObjectMatcher<JSFunction> m(NodeProperties::GetValueInput(node_, 0)); + return m.HasValue() && m.Value().handle()->shared()->HasBuiltinFunctionId();
+  }
+
+  // Retrieves the BuiltinFunctionId as described above.
+  BuiltinFunctionId GetBuiltinFunctionId() {
+    DCHECK_EQ(IrOpcode::kJSCallFunction, node_->opcode());
+ HeapObjectMatcher<JSFunction> m(NodeProperties::GetValueInput(node_, 0));
+    return m.Value().handle()->shared()->builtin_function_id();
+  }
+
+  // Determines whether the call takes one input of the given type.
+  bool InputsMatch(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) {
+    return GetJSCallArity() == 2 &&
+           NodeProperties::GetBounds(GetJSCallInput(0)).upper->Is(t1) &&
+           NodeProperties::GetBounds(GetJSCallInput(1)).upper->Is(t2);
+  }
+
+  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.
+    return OperatorProperties::GetValueInputCount(node_->op()) - 2;
+  }
+
+  Node* GetJSCallInput(int index) {
+    DCHECK_EQ(IrOpcode::kJSCallFunction, node_->opcode());
+    DCHECK_LT(index, GetJSCallArity());
+    // Skip first (i.e. callee) and second (i.e. receiver) operand.
+    return NodeProperties::GetValueInput(node_, index + 2);
+  }
+
+ private:
+  Node* node_;
+};
+
+
+// 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())) {
+    // Math.imul(a:int32, b:int32) -> Int32Mul(a, b)
+ Node* value = graph()->NewNode(machine()->Int32Mul(), r.left(), r.right());
+    return Replace(value);
+  }
+  return NoChange();
+}
+
+
+Reduction JSBuiltinReducer::Reduce(Node* node) {
+  JSCallReduction r(node);
+
+  // Dispatch according to the BuiltinFunctionId if present.
+  if (!r.HasBuiltinFunctionId()) return NoChange();
+  switch (r.GetBuiltinFunctionId()) {
+    case kMathImul:
+      return ReplaceWithPureReduction(node, ReduceMathImul(node));
+    default:
+      break;
+  }
+  return NoChange();
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
=======================================
--- /dev/null
+++ /branches/bleeding_edge/src/compiler/js-builtin-reducer.h Fri Sep 19 15:02:58 2014 UTC
@@ -0,0 +1,42 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_JS_BUILTIN_REDUCER_H_
+#define V8_COMPILER_JS_BUILTIN_REDUCER_H_
+
+#include "src/compiler/graph-reducer.h"
+#include "src/compiler/js-graph.h"
+#include "src/compiler/machine-operator.h"
+#include "src/compiler/node.h"
+#include "src/compiler/simplified-operator.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class JSBuiltinReducer FINAL : public Reducer {
+ public:
+  explicit JSBuiltinReducer(JSGraph* jsgraph)
+      : jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
+  virtual ~JSBuiltinReducer() {}
+
+  virtual Reduction Reduce(Node* node) OVERRIDE;
+
+ private:
+  Graph* graph() { return jsgraph_->graph(); }
+  CommonOperatorBuilder* common() { return jsgraph_->common(); }
+  MachineOperatorBuilder* machine() { return jsgraph_->machine(); }
+  SimplifiedOperatorBuilder* simplified() { return &simplified_; }
+
+  Reduction ReduceMathImul(Node* node);
+
+  JSGraph* jsgraph_;
+  SimplifiedOperatorBuilder simplified_;
+};
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
+
+#endif  // V8_COMPILER_JS_BUILTIN_REDUCER_H_
=======================================
--- /branches/bleeding_edge/BUILD.gn    Thu Sep 18 12:31:31 2014 UTC
+++ /branches/bleeding_edge/BUILD.gn    Fri Sep 19 15:02:58 2014 UTC
@@ -504,6 +504,8 @@
     "src/compiler/instruction-selector.h",
     "src/compiler/instruction.cc",
     "src/compiler/instruction.h",
+    "src/compiler/js-builtin-reducer.cc",
+    "src/compiler/js-builtin-reducer.h",
     "src/compiler/js-context-specialization.cc",
     "src/compiler/js-context-specialization.h",
     "src/compiler/js-generic-lowering.cc",
=======================================
--- /branches/bleeding_edge/src/compiler/js-typed-lowering.cc Wed Sep 17 14:47:25 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-typed-lowering.cc Fri Sep 19 15:02:58 2014 UTC
@@ -4,6 +4,7 @@

 #include "src/compiler/access-builder.h"
 #include "src/compiler/graph-inl.h"
+#include "src/compiler/js-builtin-reducer.h"
 #include "src/compiler/js-typed-lowering.h"
 #include "src/compiler/node-aux-data-inl.h"
 #include "src/compiler/node-properties-inl.h"
@@ -678,6 +679,8 @@
       return ReduceJSLoadProperty(node);
     case IrOpcode::kJSStoreProperty:
       return ReduceJSStoreProperty(node);
+    case IrOpcode::kJSCallFunction:
+      return JSBuiltinReducer(jsgraph()).Reduce(node);
     default:
       break;
   }
=======================================
--- /branches/bleeding_edge/src/compiler/js-typed-lowering.h Tue Sep 16 16:20:10 2014 UTC +++ /branches/bleeding_edge/src/compiler/js-typed-lowering.h Fri Sep 19 15:02:58 2014 UTC
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

-#ifndef V8_COMPILER_OPERATOR_REDUCERS_H_
-#define V8_COMPILER_OPERATOR_REDUCERS_H_
+#ifndef V8_COMPILER_JS_TYPED_LOWERING_H_
+#define V8_COMPILER_JS_TYPED_LOWERING_H_

 #include "src/compiler/graph-reducer.h"
 #include "src/compiler/js-graph.h"
@@ -61,4 +61,4 @@
 }  // namespace internal
 }  // namespace v8

-#endif  // V8_COMPILER_OPERATOR_REDUCERS_H_
+#endif  // V8_COMPILER_JS_TYPED_LOWERING_H_
=======================================
--- /branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc Thu Sep 18 08:56:52 2014 UTC +++ /branches/bleeding_edge/test/cctest/compiler/test-js-typed-lowering.cc Fri Sep 19 15:02:58 2014 UTC
@@ -53,6 +53,11 @@
Unique<Object>::CreateImmovable(isolate->factory()->undefined_value());
     return graph.NewNode(common.HeapConstant(unique));
   }
+
+  Node* HeapConstant(Handle<Object> constant) {
+    Unique<Object> unique = Unique<Object>::CreateUninitialized(constant);
+    return graph.NewNode(common.HeapConstant(unique));
+  }

   Node* EmptyFrameState(Node* context) {
     Node* parameters = graph.NewNode(common.StateValues(0));
@@ -1378,3 +1383,30 @@
     }
   }
 }
+
+
+TEST(BuiltinMathImul) {
+  JSTypedLoweringTester 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* fun = R.HeapConstant(handle(R.isolate->context()->math_imul_fun())); + 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())) {
+        R.CheckPureBinop(R.machine.Int32Mul(), r);
+        CHECK_EQ(p0, r->InputAt(0));
+        CHECK_EQ(p1, r->InputAt(1));
+      } else {
+        CHECK_EQ(IrOpcode::kJSCallFunction, r->opcode());
+        CHECK_EQ(call, r);
+      }
+    }
+  }
+}
=======================================
--- /branches/bleeding_edge/tools/gyp/v8.gyp    Thu Sep 18 12:31:31 2014 UTC
+++ /branches/bleeding_edge/tools/gyp/v8.gyp    Fri Sep 19 15:02:58 2014 UTC
@@ -415,6 +415,8 @@
         '../../src/compiler/instruction-selector.h',
         '../../src/compiler/instruction.cc',
         '../../src/compiler/instruction.h',
+        '../../src/compiler/js-builtin-reducer.cc',
+        '../../src/compiler/js-builtin-reducer.h',
         '../../src/compiler/js-context-specialization.cc',
         '../../src/compiler/js-context-specialization.h',
         '../../src/compiler/js-generic-lowering.cc',

--
--
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