Revision: 24685
Author: bmeu...@chromium.org
Date: Fri Oct 17 09:35:45 2014 UTC
Log: [turbofan] Eliminate typed array bounds checks if both key and
length are constant.
TEST=mjsunit,unittests
R=dcar...@chromium.org
Review URL: https://codereview.chromium.org/638853004
https://code.google.com/p/v8/source/detail?r=24685
Added:
/branches/bleeding_edge/test/mjsunit/asm/int32array-constant-key.js
Modified:
/branches/bleeding_edge/src/compiler/node-matchers.h
/branches/bleeding_edge/src/compiler/pipeline.cc
/branches/bleeding_edge/src/compiler/simplified-operator-reducer.cc
/branches/bleeding_edge/src/compiler/simplified-operator-reducer.h
/branches/bleeding_edge/test/unittests/compiler/simplified-operator-reducer-unittest.cc
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/asm/int32array-constant-key.js Fri
Oct 17 09:35:45 2014 UTC
@@ -0,0 +1,32 @@
+// 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.
+
+function Module(stdlib, foreign, heap) {
+ "use asm";
+ var MEM32 = new stdlib.Int32Array(heap);
+ function load0() {
+ return MEM32[0];
+ }
+ function load4() {
+ return MEM32[4];
+ }
+ function store0(v) {
+ MEM32[0] = v;
+ }
+ function store4(v) {
+ MEM32[4] = v;
+ }
+ return { load0: load0, store0: store0, load4: load4, store4: store4 };
+}
+
+var m = Module(this, {}, new ArrayBuffer(4));
+
+assertEquals(0, m.load0());
+assertEquals(undefined, m.load4());
+m.store0(0x12345678);
+assertEquals(0x12345678, m.load0());
+assertEquals(undefined, m.load4());
+m.store4(43);
+assertEquals(0x12345678, m.load0());
+assertEquals(undefined, m.load4());
=======================================
--- /branches/bleeding_edge/src/compiler/node-matchers.h Tue Oct 7
13:30:28 2014 UTC
+++ /branches/bleeding_edge/src/compiler/node-matchers.h Fri Oct 17
09:35:45 2014 UTC
@@ -96,6 +96,41 @@
typedef FloatMatcher<double, IrOpcode::kNumberConstant> NumberMatcher;
+// A pattern matcher for any numberic constant.
+struct NumericValueMatcher : public NodeMatcher {
+ explicit NumericValueMatcher(Node* const node) : NodeMatcher(node) {
+ switch (opcode()) {
+ case IrOpcode::kInt32Constant:
+ has_value_ = true;
+ value_ = OpParameter<int32_t>(node);
+ break;
+ case IrOpcode::kFloat32Constant:
+ has_value_ = true;
+ value_ = OpParameter<float>(node);
+ break;
+ case IrOpcode::kFloat64Constant:
+ case IrOpcode::kNumberConstant:
+ has_value_ = true;
+ value_ = OpParameter<double>(node);
+ break;
+ default:
+ has_value_ = false;
+ break;
+ }
+ }
+
+ bool HasValue() const { return has_value_; }
+ double Value() const {
+ DCHECK(HasValue());
+ return value_;
+ }
+
+ private:
+ double value_;
+ bool has_value_;
+};
+
+
// A pattern matcher for heap object constants.
template <typename T>
struct HeapObjectMatcher FINAL
=======================================
--- /branches/bleeding_edge/src/compiler/pipeline.cc Thu Oct 16 11:29:31
2014 UTC
+++ /branches/bleeding_edge/src/compiler/pipeline.cc Fri Oct 17 09:35:45
2014 UTC
@@ -301,9 +301,13 @@
"typed lowering");
SourcePositionTable::Scope pos(&source_positions,
SourcePosition::Unknown());
+ ValueNumberingReducer vn_reducer(zone());
JSTypedLowering lowering(&jsgraph);
+ SimplifiedOperatorReducer simple_reducer(&jsgraph);
GraphReducer graph_reducer(&graph);
+ graph_reducer.AddReducer(&vn_reducer);
graph_reducer.AddReducer(&lowering);
+ graph_reducer.AddReducer(&simple_reducer);
graph_reducer.ReduceGraph();
VerifyAndPrintGraph(&graph, "Lowered typed");
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-operator-reducer.cc Tue
Sep 16 16:20:10 2014 UTC
+++ /branches/bleeding_edge/src/compiler/simplified-operator-reducer.cc Fri
Oct 17 09:35:45 2014 UTC
@@ -12,6 +12,10 @@
namespace internal {
namespace compiler {
+SimplifiedOperatorReducer::SimplifiedOperatorReducer(JSGraph* jsgraph)
+ : jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
+
+
SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
@@ -95,6 +99,38 @@
if (m.HasValue()) return ReplaceNumber(FastUI2D(m.Value()));
break;
}
+ case IrOpcode::kLoadElement: {
+ ElementAccess access = ElementAccessOf(node->op());
+ if (access.bounds_check == kTypedArrayBoundsCheck) {
+ NumericValueMatcher mkey(node->InputAt(1));
+ NumericValueMatcher mlength(node->InputAt(2));
+ if (mkey.HasValue() && mlength.HasValue()) {
+ // Skip the typed array bounds check if key and length are
constant.
+ if (mkey.Value() < mlength.Value()) {
+ access.bounds_check = kNoBoundsCheck;
+ node->set_op(simplified()->LoadElement(access));
+ return Changed(node);
+ }
+ }
+ }
+ break;
+ }
+ case IrOpcode::kStoreElement: {
+ ElementAccess access = ElementAccessOf(node->op());
+ if (access.bounds_check == kTypedArrayBoundsCheck) {
+ NumericValueMatcher mkey(node->InputAt(1));
+ NumericValueMatcher mlength(node->InputAt(2));
+ if (mkey.HasValue() && mlength.HasValue()) {
+ // Skip the typed array bounds check if key and length are
constant.
+ if (mkey.Value() < mlength.Value()) {
+ access.bounds_check = kNoBoundsCheck;
+ node->set_op(simplified()->StoreElement(access));
+ return Changed(node);
+ }
+ }
+ }
+ break;
+ }
default:
break;
}
=======================================
--- /branches/bleeding_edge/src/compiler/simplified-operator-reducer.h Tue
Sep 16 16:20:10 2014 UTC
+++ /branches/bleeding_edge/src/compiler/simplified-operator-reducer.h Fri
Oct 17 09:35:45 2014 UTC
@@ -6,6 +6,7 @@
#define V8_COMPILER_SIMPLIFIED_OPERATOR_REDUCER_H_
#include "src/compiler/graph-reducer.h"
+#include "src/compiler/simplified-operator.h"
namespace v8 {
namespace internal {
@@ -21,7 +22,7 @@
class SimplifiedOperatorReducer FINAL : public Reducer {
public:
- explicit SimplifiedOperatorReducer(JSGraph* jsgraph) : jsgraph_(jsgraph)
{}
+ explicit SimplifiedOperatorReducer(JSGraph* jsgraph);
virtual ~SimplifiedOperatorReducer();
virtual Reduction Reduce(Node* node) OVERRIDE;
@@ -40,8 +41,10 @@
Factory* factory() const;
JSGraph* jsgraph() const { return jsgraph_; }
MachineOperatorBuilder* machine() const;
+ SimplifiedOperatorBuilder* simplified() { return &simplified_; }
JSGraph* jsgraph_;
+ SimplifiedOperatorBuilder simplified_;
DISALLOW_COPY_AND_ASSIGN(SimplifiedOperatorReducer);
};
=======================================
---
/branches/bleeding_edge/test/unittests/compiler/simplified-operator-reducer-unittest.cc
Wed Oct 15 11:38:04 2014 UTC
+++
/branches/bleeding_edge/test/unittests/compiler/simplified-operator-reducer-unittest.cc
Fri Oct 17 09:35:45 2014 UTC
@@ -6,6 +6,7 @@
#include "src/compiler/simplified-operator.h"
#include "src/compiler/simplified-operator-reducer.h"
#include "src/conversions.h"
+#include "src/types.h"
#include "test/unittests/compiler/graph-unittest.h"
namespace v8 {
@@ -475,6 +476,64 @@
EXPECT_THAT(reduction.replacement(), IsNumberConstant(FastUI2D(n)));
}
}
+
+
+//
-----------------------------------------------------------------------------
+// LoadElement
+
+
+TEST_F(SimplifiedOperatorReducerTest, LoadElementWithConstantKeyAndLength)
{
+ ElementAccess const access = {kTypedArrayBoundsCheck, kUntaggedBase, 0,
+ Type::Any(), kMachAnyTagged};
+ ElementAccess access_nocheck = access;
+ access_nocheck.bounds_check = kNoBoundsCheck;
+ Node* const base = Parameter(0);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ TRACED_FOREACH(double, key, kFloat64Values) {
+ TRACED_FOREACH(int32_t, length, kInt32Values) {
+ if (key < length) {
+ Reduction r = Reduce(graph()->NewNode(
+ simplified()->LoadElement(access), base, NumberConstant(key),
+ Int32Constant(length), effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(r.replacement(),
+ IsLoadElement(access_nocheck, base,
IsNumberConstant(key),
+ IsInt32Constant(length), effect,
control));
+ }
+ }
+ }
+}
+
+
+//
-----------------------------------------------------------------------------
+// StoreElement
+
+
+TEST_F(SimplifiedOperatorReducerTest,
StoreElementWithConstantKeyAndLength) {
+ ElementAccess const access = {kTypedArrayBoundsCheck, kUntaggedBase, 0,
+ Type::Any(), kMachAnyTagged};
+ ElementAccess access_nocheck = access;
+ access_nocheck.bounds_check = kNoBoundsCheck;
+ Node* const base = Parameter(0);
+ Node* const value = Parameter(1);
+ Node* const effect = graph()->start();
+ Node* const control = graph()->start();
+ TRACED_FOREACH(int32_t, key, kInt32Values) {
+ TRACED_FOREACH(double, length, kFloat64Values) {
+ if (key < length) {
+ Reduction r = Reduce(graph()->NewNode(
+ simplified()->StoreElement(access), base, Int32Constant(key),
+ NumberConstant(length), value, effect, control));
+ ASSERT_TRUE(r.Changed());
+ EXPECT_THAT(
+ r.replacement(),
+ IsStoreElement(access_nocheck, base, IsInt32Constant(key),
+ IsNumberConstant(length), value, effect,
control));
+ }
+ }
+ }
+}
} // namespace compiler
} // namespace internal
--
--
v8-dev mailing list
v8-dev@googlegroups.com
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 v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.