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
"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");
namespace internal {
namespace compiler {
+SimplifiedOperatorReducer::SimplifiedOperatorReducer(JSGraph* jsgraph)
+ : jsgraph_(jsgraph), simplified_(jsgraph->zone()) {}
+
+
SimplifiedOperatorReducer::~SimplifiedOperatorReducer() {}
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;
}
#define V8_COMPILER_SIMPLIFIED_OPERATOR_REDUCER_H_
#include "src/compiler/graph-reducer.h"
+#include "src/compiler/simplified-operator.h"
namespace v8 {
namespace internal {
class SimplifiedOperatorReducer FINAL : public Reducer {
public:
- explicit SimplifiedOperatorReducer(JSGraph* jsgraph) : jsgraph_(jsgraph) {}
+ explicit SimplifiedOperatorReducer(JSGraph* jsgraph);
virtual ~SimplifiedOperatorReducer();
virtual Reduction Reduce(Node* node) OVERRIDE;
Factory* factory() const;
JSGraph* jsgraph() const { return jsgraph_; }
MachineOperatorBuilder* machine() const;
+ SimplifiedOperatorBuilder* simplified() { return &simplified_; }
JSGraph* jsgraph_;
+ SimplifiedOperatorBuilder simplified_;
DISALLOW_COPY_AND_ASSIGN(SimplifiedOperatorReducer);
};
--- /dev/null
+// 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());
#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 {
}
}
+
+// -----------------------------------------------------------------------------
+// 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
} // namespace v8