Commit c95ba9bd authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

[turbofan] Eliminate redundant masking operations for word8/word16 stores.

There's no need to apply 0xff when storing 8-bit values or 0xffff when
storing 16-bit values.

TEST=unittests
R=titzer@chromium.org

Review URL: https://codereview.chromium.org/642033002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24492 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 52ec8a70
...@@ -473,6 +473,22 @@ Reduction MachineOperatorReducer::Reduce(Node* node) { ...@@ -473,6 +473,22 @@ Reduction MachineOperatorReducer::Reduce(Node* node) {
if (m.IsChangeFloat32ToFloat64()) return Replace(m.node()->InputAt(0)); if (m.IsChangeFloat32ToFloat64()) return Replace(m.node()->InputAt(0));
break; break;
} }
case IrOpcode::kStore: {
Node* const value = node->InputAt(2);
// TODO(turbofan): Extend to 64-bit?
if (value->opcode() == IrOpcode::kWord32And) {
MachineType const rep = static_cast<MachineType>(
StoreRepresentationOf(node->op()).machine_type() & kRepMask);
Uint32BinopMatcher m(value);
if (m.right().HasValue() &&
((rep == kRepWord8 && (m.right().Value() & 0xff) == 0xff) ||
(rep == kRepWord16 && (m.right().Value() & 0xffff) == 0xffff))) {
node->ReplaceInput(2, m.left().node());
return Changed(node);
}
}
break;
}
default: default:
break; break;
} }
......
...@@ -46,6 +46,12 @@ std::ostream& operator<<(std::ostream& os, StoreRepresentation rep) { ...@@ -46,6 +46,12 @@ std::ostream& operator<<(std::ostream& os, StoreRepresentation rep) {
} }
StoreRepresentation const& StoreRepresentationOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kStore, op->opcode());
return OpParameter<StoreRepresentation>(op);
}
#define PURE_OP_LIST(V) \ #define PURE_OP_LIST(V) \
V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 1) \ V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 1) \ V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 1) \
......
...@@ -49,6 +49,8 @@ size_t hash_value(StoreRepresentation); ...@@ -49,6 +49,8 @@ size_t hash_value(StoreRepresentation);
std::ostream& operator<<(std::ostream&, StoreRepresentation); std::ostream& operator<<(std::ostream&, StoreRepresentation);
StoreRepresentation const& StoreRepresentationOf(Operator const*);
// Interface for building machine-level operators. These operators are // Interface for building machine-level operators. These operators are
// machine-level but machine-independent and thus define a language suitable // machine-level but machine-independent and thus define a language suitable
......
...@@ -160,7 +160,8 @@ TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) { ...@@ -160,7 +160,8 @@ TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
IsFinish( IsFinish(
AllOf(CaptureEq(&heap_number), AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(IsValueEffect(val), graph()->start())), IsAllocateHeapNumber(IsValueEffect(val), graph()->start())),
IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number), IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsInt32Constant(HeapNumberValueOffset()), val, IsInt32Constant(HeapNumberValueOffset()), val,
CaptureEq(&heap_number), graph()->start()))); CaptureEq(&heap_number), graph()->start())));
} }
...@@ -202,13 +203,13 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) { ...@@ -202,13 +203,13 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
EXPECT_THAT( EXPECT_THAT(
phi, phi,
IsPhi(kMachAnyTagged, IsPhi(kMachAnyTagged,
IsFinish( IsFinish(AllOf(CaptureEq(&heap_number),
AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_true))), IsAllocateHeapNumber(_, CaptureEq(&if_true))),
IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number), IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsInt32Constant(HeapNumberValueOffset()), IsInt32Constant(HeapNumberValueOffset()),
IsChangeInt32ToFloat64(val), CaptureEq(&heap_number), IsChangeInt32ToFloat64(val),
CaptureEq(&if_true))), CaptureEq(&heap_number), CaptureEq(&if_true))),
IsProjection( IsProjection(
0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))), 0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))), IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
...@@ -308,13 +309,13 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) { ...@@ -308,13 +309,13 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
phi, phi,
IsPhi( IsPhi(
kMachAnyTagged, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())), kMachAnyTagged, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())),
IsFinish( IsFinish(AllOf(CaptureEq(&heap_number),
AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_false))), IsAllocateHeapNumber(_, CaptureEq(&if_false))),
IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number), IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsInt32Constant(HeapNumberValueOffset()), IsInt32Constant(HeapNumberValueOffset()),
IsChangeUint32ToFloat64(val), CaptureEq(&heap_number), IsChangeUint32ToFloat64(val),
CaptureEq(&if_false))), CaptureEq(&heap_number), CaptureEq(&if_false))),
IsMerge( IsMerge(
IsIfTrue(AllOf(CaptureEq(&branch), IsIfTrue(AllOf(CaptureEq(&branch),
IsBranch(IsUint32LessThanOrEqual( IsBranch(IsUint32LessThanOrEqual(
...@@ -442,13 +443,13 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) { ...@@ -442,13 +443,13 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
IsPhi( IsPhi(
kMachAnyTagged, IsWord64Shl(IsChangeUint32ToUint64(val), kMachAnyTagged, IsWord64Shl(IsChangeUint32ToUint64(val),
IsInt32Constant(SmiShiftAmount())), IsInt32Constant(SmiShiftAmount())),
IsFinish( IsFinish(AllOf(CaptureEq(&heap_number),
AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_false))), IsAllocateHeapNumber(_, CaptureEq(&if_false))),
IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number), IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsInt32Constant(HeapNumberValueOffset()), IsInt32Constant(HeapNumberValueOffset()),
IsChangeUint32ToFloat64(val), CaptureEq(&heap_number), IsChangeUint32ToFloat64(val),
CaptureEq(&if_false))), CaptureEq(&heap_number), CaptureEq(&if_false))),
IsMerge( IsMerge(
IsIfTrue(AllOf(CaptureEq(&branch), IsIfTrue(AllOf(CaptureEq(&branch),
IsBranch(IsUint32LessThanOrEqual( IsBranch(IsUint32LessThanOrEqual(
......
...@@ -654,16 +654,14 @@ class IsLoadMatcher FINAL : public NodeMatcher { ...@@ -654,16 +654,14 @@ class IsLoadMatcher FINAL : public NodeMatcher {
class IsStoreMatcher FINAL : public NodeMatcher { class IsStoreMatcher FINAL : public NodeMatcher {
public: public:
IsStoreMatcher(const Matcher<MachineType>& type_matcher, IsStoreMatcher(const Matcher<StoreRepresentation>& rep_matcher,
const Matcher<WriteBarrierKind> write_barrier_matcher,
const Matcher<Node*>& base_matcher, const Matcher<Node*>& base_matcher,
const Matcher<Node*>& index_matcher, const Matcher<Node*>& index_matcher,
const Matcher<Node*>& value_matcher, const Matcher<Node*>& value_matcher,
const Matcher<Node*>& effect_matcher, const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) const Matcher<Node*>& control_matcher)
: NodeMatcher(IrOpcode::kStore), : NodeMatcher(IrOpcode::kStore),
type_matcher_(type_matcher), rep_matcher_(rep_matcher),
write_barrier_matcher_(write_barrier_matcher),
base_matcher_(base_matcher), base_matcher_(base_matcher),
index_matcher_(index_matcher), index_matcher_(index_matcher),
value_matcher_(value_matcher), value_matcher_(value_matcher),
...@@ -672,10 +670,8 @@ class IsStoreMatcher FINAL : public NodeMatcher { ...@@ -672,10 +670,8 @@ class IsStoreMatcher FINAL : public NodeMatcher {
virtual void DescribeTo(std::ostream* os) const OVERRIDE { virtual void DescribeTo(std::ostream* os) const OVERRIDE {
NodeMatcher::DescribeTo(os); NodeMatcher::DescribeTo(os);
*os << " whose type ("; *os << " whose rep (";
type_matcher_.DescribeTo(os); rep_matcher_.DescribeTo(os);
*os << "), write barrier (";
write_barrier_matcher_.DescribeTo(os);
*os << "), base ("; *os << "), base (";
base_matcher_.DescribeTo(os); base_matcher_.DescribeTo(os);
*os << "), index ("; *os << "), index (";
...@@ -692,12 +688,8 @@ class IsStoreMatcher FINAL : public NodeMatcher { ...@@ -692,12 +688,8 @@ class IsStoreMatcher FINAL : public NodeMatcher {
virtual bool MatchAndExplain(Node* node, virtual bool MatchAndExplain(Node* node,
MatchResultListener* listener) const OVERRIDE { MatchResultListener* listener) const OVERRIDE {
return (NodeMatcher::MatchAndExplain(node, listener) && return (NodeMatcher::MatchAndExplain(node, listener) &&
PrintMatchAndExplain( PrintMatchAndExplain(OpParameter<StoreRepresentation>(node), "rep",
OpParameter<StoreRepresentation>(node).machine_type(), "type", rep_matcher_, listener) &&
type_matcher_, listener) &&
PrintMatchAndExplain(
OpParameter<StoreRepresentation>(node).write_barrier_kind(),
"write barrier", write_barrier_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base", PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0), "base",
base_matcher_, listener) && base_matcher_, listener) &&
PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1), PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
...@@ -711,8 +703,7 @@ class IsStoreMatcher FINAL : public NodeMatcher { ...@@ -711,8 +703,7 @@ class IsStoreMatcher FINAL : public NodeMatcher {
} }
private: private:
const Matcher<MachineType> type_matcher_; const Matcher<StoreRepresentation> rep_matcher_;
const Matcher<WriteBarrierKind> write_barrier_matcher_;
const Matcher<Node*> base_matcher_; const Matcher<Node*> base_matcher_;
const Matcher<Node*> index_matcher_; const Matcher<Node*> index_matcher_;
const Matcher<Node*> value_matcher_; const Matcher<Node*> value_matcher_;
...@@ -927,16 +918,15 @@ Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher, ...@@ -927,16 +918,15 @@ Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
} }
Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher, Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher,
const Matcher<WriteBarrierKind>& write_barrier_matcher,
const Matcher<Node*>& base_matcher, const Matcher<Node*>& base_matcher,
const Matcher<Node*>& index_matcher, const Matcher<Node*>& index_matcher,
const Matcher<Node*>& value_matcher, const Matcher<Node*>& value_matcher,
const Matcher<Node*>& effect_matcher, const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) { const Matcher<Node*>& control_matcher) {
return MakeMatcher(new IsStoreMatcher( return MakeMatcher(new IsStoreMatcher(rep_matcher, base_matcher,
type_matcher, write_barrier_matcher, base_matcher, index_matcher, index_matcher, value_matcher,
value_matcher, effect_matcher, control_matcher)); effect_matcher, control_matcher));
} }
......
...@@ -41,6 +41,9 @@ class GraphTest : public TestWithContext, public TestWithZone { ...@@ -41,6 +41,9 @@ class GraphTest : public TestWithContext, public TestWithZone {
Node* Float32Constant(volatile float value); Node* Float32Constant(volatile float value);
Node* Float64Constant(volatile double value); Node* Float64Constant(volatile double value);
Node* Int32Constant(int32_t value); Node* Int32Constant(int32_t value);
Node* Uint32Constant(uint32_t value) {
return Int32Constant(bit_cast<int32_t>(value));
}
Node* Int64Constant(int64_t value); Node* Int64Constant(int64_t value);
Node* NumberConstant(volatile double value); Node* NumberConstant(volatile double value);
Node* HeapConstant(const Handle<HeapObject>& value); Node* HeapConstant(const Handle<HeapObject>& value);
...@@ -119,8 +122,7 @@ Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher, ...@@ -119,8 +122,7 @@ Matcher<Node*> IsLoad(const Matcher<LoadRepresentation>& rep_matcher,
const Matcher<Node*>& index_matcher, const Matcher<Node*>& index_matcher,
const Matcher<Node*>& effect_matcher, const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher); const Matcher<Node*>& control_matcher);
Matcher<Node*> IsStore(const Matcher<MachineType>& type_matcher, Matcher<Node*> IsStore(const Matcher<StoreRepresentation>& rep_matcher,
const Matcher<WriteBarrierKind>& write_barrier_matcher,
const Matcher<Node*>& base_matcher, const Matcher<Node*>& base_matcher,
const Matcher<Node*>& index_matcher, const Matcher<Node*>& index_matcher,
const Matcher<Node*>& value_matcher, const Matcher<Node*>& value_matcher,
......
...@@ -654,6 +654,54 @@ TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) { ...@@ -654,6 +654,54 @@ TEST_F(MachineOperatorReducerTest, Int32SubWithOverflowWithConstant) {
} }
} }
// -----------------------------------------------------------------------------
// Store
TEST_F(MachineOperatorReducerTest, StoreRepWord8WithWord32And) {
const StoreRepresentation rep(kRepWord8, kNoWriteBarrier);
Node* const base = Parameter(0);
Node* const index = Parameter(1);
Node* const value = Parameter(2);
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FOREACH(uint32_t, x, kUint32Values) {
Node* const node =
graph()->NewNode(machine()->Store(rep), base, index,
graph()->NewNode(machine()->Word32And(), value,
Uint32Constant(x | 0xffu)),
effect, control);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsStore(rep, base, index, value, effect, control));
}
}
TEST_F(MachineOperatorReducerTest, StoreRepWord16WithWord32And) {
const StoreRepresentation rep(kRepWord16, kNoWriteBarrier);
Node* const base = Parameter(0);
Node* const index = Parameter(1);
Node* const value = Parameter(2);
Node* const effect = graph()->start();
Node* const control = graph()->start();
TRACED_FOREACH(uint32_t, x, kUint32Values) {
Node* const node =
graph()->NewNode(machine()->Store(rep), base, index,
graph()->NewNode(machine()->Word32And(), value,
Uint32Constant(x | 0xffffu)),
effect, control);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsStore(rep, base, index, value, effect, control));
}
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment