[turbofan] Improve ChangeLowering.

- Use representation information provided by the type system to skip SMI
  checks.
- Fix combining of ChangeTaggedToFloat64 with JSToNumber now that JS
  operators can produce control.
- Remove the unnecessary abstraction of smi/field offsets.
- Improve unit test coverage.
- Various cosmetic fixes.

R=svenpanne@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#27250}
This commit is contained in:
bmeurer 2015-03-18 00:27:31 -07:00 committed by Commit bot
parent 9710425529
commit 45434d575e
3 changed files with 359 additions and 302 deletions

View File

@ -5,7 +5,6 @@
#include "src/compiler/change-lowering.h"
#include "src/code-factory.h"
#include "src/compiler/diamond.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
@ -47,25 +46,17 @@ Reduction ChangeLowering::Reduce(Node* node) {
Node* ChangeLowering::HeapNumberValueIndexConstant() {
STATIC_ASSERT(HeapNumber::kValueOffset % kPointerSize == 0);
const int heap_number_value_offset =
((HeapNumber::kValueOffset / kPointerSize) * (machine()->Is64() ? 8 : 4));
return jsgraph()->IntPtrConstant(heap_number_value_offset - kHeapObjectTag);
return jsgraph()->IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag);
}
Node* ChangeLowering::SmiMaxValueConstant() {
const int smi_value_size = machine()->Is32() ? SmiTagging<4>::SmiValueSize()
: SmiTagging<8>::SmiValueSize();
return jsgraph()->Int32Constant(
-(static_cast<int>(0xffffffffu << (smi_value_size - 1)) + 1));
return jsgraph()->Int32Constant(Smi::kMaxValue);
}
Node* ChangeLowering::SmiShiftBitsConstant() {
const int smi_shift_size = machine()->Is32() ? SmiTagging<4>::SmiShiftSize()
: SmiTagging<8>::SmiShiftSize();
return jsgraph()->IntPtrConstant(smi_shift_size + kSmiTagSize);
return jsgraph()->IntPtrConstant(kSmiShiftSize + kSmiTagSize);
}
@ -93,6 +84,14 @@ Node* ChangeLowering::ChangeInt32ToFloat64(Node* value) {
}
Node* ChangeLowering::ChangeInt32ToSmi(Node* value) {
if (machine()->Is64()) {
value = graph()->NewNode(machine()->ChangeInt32ToInt64(), value);
}
return graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant());
}
Node* ChangeLowering::ChangeSmiToFloat64(Node* value) {
return ChangeInt32ToFloat64(ChangeSmiToInt32(value));
}
@ -135,64 +134,80 @@ Node* ChangeLowering::TestNotSmi(Node* value) {
}
Node* ChangeLowering::Uint32LessThanOrEqual(Node* lhs, Node* rhs) {
return graph()->NewNode(machine()->Uint32LessThanOrEqual(), lhs, rhs);
}
Reduction ChangeLowering::ChangeBitToBool(Node* val, Node* control) {
MachineType const type = static_cast<MachineType>(kTypeBool | kRepTagged);
return Replace(graph()->NewNode(common()->Select(type), val,
Reduction ChangeLowering::ChangeBitToBool(Node* value, Node* control) {
return Replace(graph()->NewNode(common()->Select(kMachAnyTagged), value,
jsgraph()->TrueConstant(),
jsgraph()->FalseConstant()));
}
Reduction ChangeLowering::ChangeBoolToBit(Node* val) {
return Replace(
graph()->NewNode(machine()->WordEqual(), val, jsgraph()->TrueConstant()));
Reduction ChangeLowering::ChangeBoolToBit(Node* value) {
return Replace(graph()->NewNode(machine()->WordEqual(), value,
jsgraph()->TrueConstant()));
}
Reduction ChangeLowering::ChangeFloat64ToTagged(Node* val, Node* control) {
return Replace(AllocateHeapNumberWithValue(val, control));
Reduction ChangeLowering::ChangeFloat64ToTagged(Node* value, Node* control) {
return Replace(AllocateHeapNumberWithValue(value, control));
}
Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) {
if (machine()->Is64()) {
return Replace(graph()->NewNode(
machine()->Word64Shl(),
graph()->NewNode(machine()->ChangeInt32ToInt64(), value),
SmiShiftBitsConstant()));
} else if (NodeProperties::GetBounds(value).upper->Is(Type::SignedSmall())) {
return Replace(
graph()->NewNode(machine()->WordShl(), value, SmiShiftBitsConstant()));
if (machine()->Is64() ||
NodeProperties::GetBounds(value).upper->Is(Type::SignedSmall())) {
return Replace(ChangeInt32ToSmi(value));
}
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value);
Node* ovf = graph()->NewNode(common()->Projection(1), add);
Diamond d(graph(), common(), ovf, BranchHint::kFalse);
d.Chain(control);
return Replace(
d.Phi(kMachAnyTagged,
AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), d.if_true),
graph()->NewNode(common()->Projection(0), add)));
Node* ovf = graph()->NewNode(common()->Projection(1), add);
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), ovf, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* vtrue =
AllocateHeapNumberWithValue(ChangeInt32ToFloat64(value), if_true);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* vfalse = graph()->NewNode(common()->Projection(0), add);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi =
graph()->NewNode(common()->Phi(kMachAnyTagged, 2), vtrue, vfalse, merge);
return Replace(phi);
}
Reduction ChangeLowering::ChangeTaggedToUI32(Node* value, Node* control,
Signedness signedness) {
if (NodeProperties::GetBounds(value).upper->Is(Type::TaggedSigned())) {
return Replace(ChangeSmiToInt32(value));
}
const MachineType type = (signedness == kSigned) ? kMachInt32 : kMachUint32;
const Operator* op = (signedness == kSigned)
? machine()->ChangeFloat64ToInt32()
: machine()->ChangeFloat64ToUint32();
Diamond d(graph(), common(), TestNotSmi(value), BranchHint::kFalse);
d.Chain(control);
return Replace(
d.Phi(type, graph()->NewNode(op, LoadHeapNumberValue(value, d.if_true)),
ChangeSmiToInt32(value)));
if (NodeProperties::GetBounds(value).upper->Is(Type::TaggedPointer())) {
return Replace(graph()->NewNode(op, LoadHeapNumberValue(value, control)));
}
Node* check = TestNotSmi(value);
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* vtrue = graph()->NewNode(op, LoadHeapNumberValue(value, if_true));
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* vfalse = ChangeSmiToInt32(value);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi = graph()->NewNode(common()->Phi(type, 2), vtrue, vfalse, merge);
return Replace(phi);
}
@ -226,50 +241,88 @@ Reduction ChangeLowering::ChangeTaggedToFloat64(Node* value, Node* control) {
Node* const effect = NodeProperties::GetEffectInput(value);
Node* const control = NodeProperties::GetControlInput(value);
Diamond d1(graph(), common(), TestNotSmi(object), BranchHint::kFalse);
d1.Chain(control);
const Operator* merge_op = common()->Merge(2);
const Operator* ephi_op = common()->EffectPhi(2);
const Operator* phi_op = common()->Phi(kMachFloat64, 2);
DCHECK_EQ(FLAG_turbo_deoptimization,
OperatorProperties::GetFrameStateInputCount(value->op()) == 1);
Node* number =
Node* check1 = TestNotSmi(object);
Node* branch1 =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check1, control);
Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
Node* vtrue1 =
FLAG_turbo_deoptimization
? graph()->NewNode(value->op(), object, context,
NodeProperties::GetFrameStateInput(value, 0),
effect, d1.if_true)
: graph()->NewNode(value->op(), object, context, effect,
d1.if_true);
Diamond d2(graph(), common(), TestNotSmi(number));
d2.Nest(d1, true);
Node* phi2 = d2.Phi(kMachFloat64, LoadHeapNumberValue(number, d2.if_true),
ChangeSmiToFloat64(number));
effect, if_true1)
: graph()->NewNode(value->op(), object, context, effect, if_true1);
Node* etrue1 = vtrue1;
{
Node* check2 = TestNotSmi(vtrue1);
Node* branch2 = graph()->NewNode(common()->Branch(), check2, if_true1);
Node* phi1 = d1.Phi(kMachFloat64, phi2, ChangeSmiToFloat64(object));
Node* ephi1 = d1.EffectPhi(number, effect);
Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
Node* vtrue2 = LoadHeapNumberValue(vtrue1, if_true2);
for (Edge edge : value->use_edges()) {
if (NodeProperties::IsEffectEdge(edge)) {
edge.UpdateTo(ephi1);
}
Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
Node* vfalse2 = ChangeSmiToFloat64(vtrue1);
if_true1 = graph()->NewNode(merge_op, if_true2, if_false2);
vtrue1 = graph()->NewNode(phi_op, vtrue2, vfalse2, if_true1);
}
Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
Node* vfalse1 = ChangeSmiToFloat64(object);
Node* efalse1 = effect;
Node* merge1 = graph()->NewNode(merge_op, if_true1, if_false1);
Node* ephi1 = graph()->NewNode(ephi_op, etrue1, efalse1, merge1);
Node* phi1 = graph()->NewNode(phi_op, vtrue1, vfalse1, merge1);
NodeProperties::ReplaceWithValue(value, phi1, ephi1, merge1);
return Replace(phi1);
}
Diamond d(graph(), common(), TestNotSmi(value), BranchHint::kFalse);
d.Chain(control);
Node* load = LoadHeapNumberValue(value, d.if_true);
Node* number = ChangeSmiToFloat64(value);
return Replace(d.Phi(kMachFloat64, load, number));
Node* check = TestNotSmi(value);
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* vtrue = LoadHeapNumberValue(value, if_true);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* vfalse = ChangeSmiToFloat64(value);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi =
graph()->NewNode(common()->Phi(kMachFloat64, 2), vtrue, vfalse, merge);
return Replace(phi);
}
Reduction ChangeLowering::ChangeUint32ToTagged(Node* value, Node* control) {
Diamond d(graph(), common(),
Uint32LessThanOrEqual(value, SmiMaxValueConstant()),
BranchHint::kTrue);
d.Chain(control);
return Replace(d.Phi(
kMachAnyTagged, ChangeUint32ToSmi(value),
AllocateHeapNumberWithValue(ChangeUint32ToFloat64(value), d.if_false)));
if (NodeProperties::GetBounds(value).upper->Is(Type::UnsignedSmall())) {
return Replace(ChangeUint32ToSmi(value));
}
Node* check = graph()->NewNode(machine()->Uint32LessThanOrEqual(), value,
SmiMaxValueConstant());
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
Node* vtrue = ChangeUint32ToSmi(value);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* vfalse =
AllocateHeapNumberWithValue(ChangeUint32ToFloat64(value), if_false);
Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* phi =
graph()->NewNode(common()->Phi(kMachAnyTagged, 2), vtrue, vfalse, merge);
return Replace(phi);
}

View File

@ -31,13 +31,13 @@ class ChangeLowering FINAL : public Reducer {
Node* AllocateHeapNumberWithValue(Node* value, Node* control);
Node* ChangeInt32ToFloat64(Node* value);
Node* ChangeInt32ToSmi(Node* value);
Node* ChangeSmiToFloat64(Node* value);
Node* ChangeSmiToInt32(Node* value);
Node* ChangeUint32ToFloat64(Node* value);
Node* ChangeUint32ToSmi(Node* value);
Node* LoadHeapNumberValue(Node* value, Node* control);
Node* TestNotSmi(Node* value);
Node* Uint32LessThanOrEqual(Node* lhs, Node* rhs);
Reduction ChangeBitToBool(Node* value, Node* control);
Reduction ChangeBoolToBit(Node* value);

View File

@ -23,45 +23,15 @@ namespace v8 {
namespace internal {
namespace compiler {
class ChangeLoweringTest : public GraphTest {
class ChangeLoweringTest : public TypedGraphTest {
public:
ChangeLoweringTest() : simplified_(zone()) {}
~ChangeLoweringTest() OVERRIDE {}
virtual MachineType WordRepresentation() const = 0;
protected:
int HeapNumberValueOffset() const {
STATIC_ASSERT(HeapNumber::kValueOffset % kApiPointerSize == 0);
return (HeapNumber::kValueOffset / kApiPointerSize) * PointerSize() -
kHeapObjectTag;
}
bool Is32() const { return WordRepresentation() == kRepWord32; }
int PointerSize() const {
switch (WordRepresentation()) {
case kRepWord32:
return 4;
case kRepWord64:
return 8;
default:
break;
}
UNREACHABLE();
return 0;
}
int SmiMaxValue() const { return -(SmiMinValue() + 1); }
int SmiMinValue() const {
return static_cast<int>(0xffffffffu << (SmiValueSize() - 1));
}
int SmiShiftAmount() const { return kSmiTagSize + SmiShiftSize(); }
int SmiShiftSize() const {
return Is32() ? SmiTagging<4>::SmiShiftSize()
: SmiTagging<8>::SmiShiftSize();
}
int SmiValueSize() const {
return Is32() ? SmiTagging<4>::SmiValueSize()
: SmiTagging<8>::SmiValueSize();
}
bool Is64() const { return WordRepresentation() == kRepWord64; }
Reduction Reduce(Node* node) {
MachineOperatorBuilder machine(zone(), WordRepresentation());
@ -80,15 +50,33 @@ class ChangeLoweringTest : public GraphTest {
IsNumberConstant(BitEq(0.0)), effect_matcher,
control_matcher);
}
Matcher<Node*> IsChangeInt32ToSmi(const Matcher<Node*>& value_matcher) {
return Is64() ? IsWord64Shl(IsChangeInt32ToInt64(value_matcher),
IsSmiShiftBitsConstant())
: IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
}
Matcher<Node*> IsChangeSmiToInt32(const Matcher<Node*>& value_matcher) {
return Is64() ? IsTruncateInt64ToInt32(
IsWord64Sar(value_matcher, IsSmiShiftBitsConstant()))
: IsWord32Sar(value_matcher, IsSmiShiftBitsConstant());
}
Matcher<Node*> IsChangeUint32ToSmi(const Matcher<Node*>& value_matcher) {
return Is64() ? IsWord64Shl(IsChangeUint32ToUint64(value_matcher),
IsSmiShiftBitsConstant())
: IsWord32Shl(value_matcher, IsSmiShiftBitsConstant());
}
Matcher<Node*> IsLoadHeapNumber(const Matcher<Node*>& value_matcher,
const Matcher<Node*>& control_matcher) {
return IsLoad(kMachFloat64, value_matcher,
IsIntPtrConstant(HeapNumberValueOffset()), graph()->start(),
control_matcher);
IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
graph()->start(), control_matcher);
}
Matcher<Node*> IsIntPtrConstant(int value) {
return Is32() ? IsInt32Constant(value) : IsInt64Constant(value);
}
Matcher<Node*> IsSmiShiftBitsConstant() {
return IsIntPtrConstant(kSmiShiftSize + kSmiTagSize);
}
Matcher<Node*> IsWordEqual(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return Is32() ? IsWord32Equal(lhs_matcher, rhs_matcher)
@ -115,51 +103,95 @@ class ChangeLoweringCommonTest
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBitToBool) {
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeBitToBool(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(),
IsSelect(static_cast<MachineType>(kTypeBool | kRepTagged), val,
IsTrueConstant(), IsFalseConstant()));
Node* value = Parameter(Type::Boolean());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeBitToBool(), value));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsSelect(kMachAnyTagged, value, IsTrueConstant(),
IsFalseConstant()));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeBoolToBit) {
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeBoolToBit(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(), IsWordEqual(val, IsTrueConstant()));
Node* value = Parameter(Type::Number());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeBoolToBit(), value));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsWordEqual(value, IsTrueConstant()));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeFloat64ToTagged) {
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeFloat64ToTagged(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* finish = reduction.replacement();
Node* value = Parameter(Type::Number());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeFloat64ToTagged(), value));
ASSERT_TRUE(r.Changed());
Capture<Node*> heap_number;
EXPECT_THAT(
finish,
r.replacement(),
IsFinish(
AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(IsValueEffect(val), graph()->start())),
IsAllocateHeapNumber(IsValueEffect(value), graph()->start())),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsIntPtrConstant(HeapNumberValueOffset()), val,
CaptureEq(&heap_number), graph()->start())));
IsIntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag),
value, CaptureEq(&heap_number), graph()->start())));
}
TARGET_TEST_P(ChangeLoweringCommonTest, StringAdd) {
Node* node =
graph()->NewNode(simplified()->StringAdd(), Parameter(0), Parameter(1));
Reduction reduction = Reduce(node);
EXPECT_FALSE(reduction.Changed());
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeInt32ToTaggedWithSignedSmall) {
Node* value = Parameter(Type::SignedSmall());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeInt32ToTagged(), value));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeUint32ToTaggedWithUnsignedSmall) {
Node* value = Parameter(Type::UnsignedSmall());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeUint32ToTagged(), value));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsChangeUint32ToSmi(value));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedSigned) {
Node* value = Parameter(Type::TaggedSigned());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToInt32WithTaggedPointer) {
Node* value = Parameter(Type::TaggedPointer());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeTaggedToInt32(), value));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsChangeFloat64ToInt32(
IsLoadHeapNumber(value, graph()->start())));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedSigned) {
Node* value = Parameter(Type::TaggedSigned());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsChangeSmiToInt32(value));
}
TARGET_TEST_P(ChangeLoweringCommonTest, ChangeTaggedToUint32WithTaggedPointer) {
Node* value = Parameter(Type::TaggedPointer());
Reduction r =
Reduce(graph()->NewNode(simplified()->ChangeTaggedToUint32(), value));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsChangeFloat64ToUint32(
IsLoadHeapNumber(value, graph()->start())));
}
@ -179,26 +211,24 @@ class ChangeLowering32Test : public ChangeLoweringTest {
TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
NodeProperties::SetBounds(val, Bounds(Type::None(), Type::Integral32()));
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Integral32());
Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> add, branch, heap_number, if_true;
EXPECT_THAT(
phi,
r.replacement(),
IsPhi(kMachAnyTagged,
IsFinish(AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_true))),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsIntPtrConstant(HeapNumberValueOffset()),
IsChangeInt32ToFloat64(val),
IsIntPtrConstant(HeapNumber::kValueOffset -
kHeapObjectTag),
IsChangeInt32ToFloat64(value),
CaptureEq(&heap_number), CaptureEq(&if_true))),
IsProjection(
0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))),
IsProjection(0, AllOf(CaptureEq(&add),
IsInt32AddWithOverflow(value, value))),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(CaptureEq(&branch),
IsBranch(IsProjection(1, CaptureEq(&add)),
@ -206,43 +236,27 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTagged) {
}
TARGET_TEST_F(ChangeLowering32Test, ChangeInt32ToTaggedSmall) {
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
NodeProperties::SetBounds(val, Bounds(Type::None(), Type::SignedSmall()));
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* change = reduction.replacement();
Capture<Node*> add, branch, heap_number, if_true;
EXPECT_THAT(change, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())));
}
TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToFloat64) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Number());
Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
IsPhi(
kMachFloat64, IsLoadHeapNumber(val, CaptureEq(&if_true)),
IsChangeInt32ToFloat64(
IsWord32Sar(val, IsInt32Constant(SmiShiftAmount()))),
IsMerge(
AllOf(CaptureEq(&if_true),
IsIfTrue(AllOf(
CaptureEq(&branch),
IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
graph()->start())))),
IsIfFalse(CaptureEq(&branch)))));
r.replacement(),
IsPhi(kMachFloat64, IsLoadHeapNumber(value, CaptureEq(&if_true)),
IsChangeInt32ToFloat64(IsWord32Sar(
value, IsInt32Constant(kSmiTagSize + kSmiShiftSize))),
IsMerge(AllOf(CaptureEq(&if_true),
IsIfTrue(AllOf(
CaptureEq(&branch),
IsBranch(IsWord32And(
value, IsInt32Constant(kSmiTagMask)),
graph()->start())))),
IsIfFalse(CaptureEq(&branch)))));
}
@ -250,23 +264,22 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToInt32) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Signed32());
Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
IsPhi(kMachInt32,
IsChangeFloat64ToInt32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(
CaptureEq(&branch),
IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
graph()->start()))))));
r.replacement(),
IsPhi(
kMachInt32,
IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(
CaptureEq(&branch),
IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
graph()->start()))))));
}
@ -274,23 +287,22 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeTaggedToUint32) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Unsigned32());
Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
IsPhi(kMachUint32,
IsChangeFloat64ToUint32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(
CaptureEq(&branch),
IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
graph()->start()))))));
r.replacement(),
IsPhi(
kMachUint32,
IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
IsWord32Sar(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(
CaptureEq(&branch),
IsBranch(IsWord32And(value, IsInt32Constant(kSmiTagMask)),
graph()->start()))))));
}
@ -298,30 +310,30 @@ TARGET_TEST_F(ChangeLowering32Test, ChangeUint32ToTagged) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Number());
Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> branch, heap_number, if_false;
EXPECT_THAT(
phi,
r.replacement(),
IsPhi(
kMachAnyTagged, IsWord32Shl(val, IsInt32Constant(SmiShiftAmount())),
kMachAnyTagged,
IsWord32Shl(value, IsInt32Constant(kSmiTagSize + kSmiShiftSize)),
IsFinish(AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_false))),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsInt32Constant(HeapNumberValueOffset()),
IsChangeUint32ToFloat64(val),
IsInt32Constant(HeapNumber::kValueOffset -
kHeapObjectTag),
IsChangeUint32ToFloat64(value),
CaptureEq(&heap_number), CaptureEq(&if_false))),
IsMerge(
IsIfTrue(AllOf(CaptureEq(&branch),
IsBranch(IsUint32LessThanOrEqual(
val, IsInt32Constant(SmiMaxValue())),
graph()->start()))),
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
IsMerge(IsIfTrue(AllOf(
CaptureEq(&branch),
IsBranch(IsUint32LessThanOrEqual(
value, IsInt32Constant(Smi::kMaxValue)),
graph()->start()))),
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
}
@ -337,14 +349,11 @@ class ChangeLowering64Test : public ChangeLoweringTest {
TARGET_TEST_F(ChangeLowering64Test, ChangeInt32ToTagged) {
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
EXPECT_THAT(reduction.replacement(),
IsWord64Shl(IsChangeInt32ToInt64(val),
IsInt64Constant(SmiShiftAmount())));
Node* value = Parameter(Type::Signed32());
Node* node = graph()->NewNode(simplified()->ChangeInt32ToTagged(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsChangeInt32ToSmi(value));
}
@ -352,26 +361,23 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToFloat64) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Number());
Node* node = graph()->NewNode(simplified()->ChangeTaggedToFloat64(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
IsPhi(
kMachFloat64, IsLoadHeapNumber(val, CaptureEq(&if_true)),
IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(
IsWord64Sar(val, IsInt64Constant(SmiShiftAmount())))),
IsMerge(
AllOf(CaptureEq(&if_true),
IsIfTrue(AllOf(
CaptureEq(&branch),
IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
graph()->start())))),
IsIfFalse(CaptureEq(&branch)))));
r.replacement(),
IsPhi(kMachFloat64, IsLoadHeapNumber(value, CaptureEq(&if_true)),
IsChangeInt32ToFloat64(IsTruncateInt64ToInt32(IsWord64Sar(
value, IsInt64Constant(kSmiTagSize + kSmiShiftSize)))),
IsMerge(AllOf(CaptureEq(&if_true),
IsIfTrue(AllOf(
CaptureEq(&branch),
IsBranch(IsWord64And(
value, IsInt64Constant(kSmiTagMask)),
graph()->start())))),
IsIfFalse(CaptureEq(&branch)))));
}
@ -379,24 +385,23 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToInt32) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Signed32());
Node* node = graph()->NewNode(simplified()->ChangeTaggedToInt32(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
IsPhi(kMachInt32,
IsChangeFloat64ToInt32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
IsTruncateInt64ToInt32(
IsWord64Sar(val, IsInt64Constant(SmiShiftAmount()))),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(
CaptureEq(&branch),
IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
graph()->start()))))));
r.replacement(),
IsPhi(
kMachInt32,
IsChangeFloat64ToInt32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
IsTruncateInt64ToInt32(
IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(
CaptureEq(&branch),
IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
graph()->start()))))));
}
@ -404,24 +409,23 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeTaggedToUint32) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Unsigned32());
Node* node = graph()->NewNode(simplified()->ChangeTaggedToUint32(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
IsPhi(kMachUint32,
IsChangeFloat64ToUint32(IsLoadHeapNumber(val, CaptureEq(&if_true))),
IsTruncateInt64ToInt32(
IsWord64Sar(val, IsInt64Constant(SmiShiftAmount()))),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(
CaptureEq(&branch),
IsBranch(IsWord64And(val, IsInt64Constant(kSmiTagMask)),
graph()->start()))))));
r.replacement(),
IsPhi(
kMachUint32,
IsChangeFloat64ToUint32(IsLoadHeapNumber(value, CaptureEq(&if_true))),
IsTruncateInt64ToInt32(
IsWord64Sar(value, IsInt64Constant(kSmiTagSize + kSmiShiftSize))),
IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
IsIfFalse(AllOf(
CaptureEq(&branch),
IsBranch(IsWord64And(value, IsInt64Constant(kSmiTagMask)),
graph()->start()))))));
}
@ -429,31 +433,31 @@ TARGET_TEST_F(ChangeLowering64Test, ChangeUint32ToTagged) {
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
Node* val = Parameter(0);
Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), val);
Reduction reduction = Reduce(node);
ASSERT_TRUE(reduction.Changed());
Node* phi = reduction.replacement();
Node* value = Parameter(Type::Number());
Node* node = graph()->NewNode(simplified()->ChangeUint32ToTagged(), value);
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
Capture<Node*> branch, heap_number, if_false;
EXPECT_THAT(
phi,
r.replacement(),
IsPhi(
kMachAnyTagged, IsWord64Shl(IsChangeUint32ToUint64(val),
IsInt64Constant(SmiShiftAmount())),
kMachAnyTagged,
IsWord64Shl(IsChangeUint32ToUint64(value),
IsInt64Constant(kSmiTagSize + kSmiShiftSize)),
IsFinish(AllOf(CaptureEq(&heap_number),
IsAllocateHeapNumber(_, CaptureEq(&if_false))),
IsStore(StoreRepresentation(kMachFloat64, kNoWriteBarrier),
CaptureEq(&heap_number),
IsInt64Constant(HeapNumberValueOffset()),
IsChangeUint32ToFloat64(val),
IsInt64Constant(HeapNumber::kValueOffset -
kHeapObjectTag),
IsChangeUint32ToFloat64(value),
CaptureEq(&heap_number), CaptureEq(&if_false))),
IsMerge(
IsIfTrue(AllOf(CaptureEq(&branch),
IsBranch(IsUint32LessThanOrEqual(
val, IsInt32Constant(SmiMaxValue())),
graph()->start()))),
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
IsMerge(IsIfTrue(AllOf(
CaptureEq(&branch),
IsBranch(IsUint32LessThanOrEqual(
value, IsInt32Constant(Smi::kMaxValue)),
graph()->start()))),
AllOf(CaptureEq(&if_false), IsIfFalse(CaptureEq(&branch))))));
}
} // namespace compiler