[turbofan] More useful typing for And, Or and Shr.
BUG= Review URL: https://codereview.chromium.org/714413004 Cr-Commit-Position: refs/heads/master@{#25381}
This commit is contained in:
parent
685bc04a01
commit
e130d01aee
@ -163,6 +163,9 @@ Reduction ChangeLowering::ChangeInt32ToTagged(Node* value, Node* control) {
|
||||
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()));
|
||||
}
|
||||
|
||||
Node* add = graph()->NewNode(machine()->Int32AddWithOverflow(), value, value);
|
||||
|
@ -717,16 +717,26 @@ Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
|
||||
double rmax = rhs->Max();
|
||||
// Or-ing any two values results in a value no smaller than their minimum.
|
||||
// Even no smaller than their maximum if both values are non-negative.
|
||||
Handle<Object> min = f->NewNumber(
|
||||
lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin));
|
||||
double min =
|
||||
lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
|
||||
double max = Type::Signed32()->Max();
|
||||
|
||||
// Or-ing with 0 is essentially a conversion to int32.
|
||||
if (rmin == 0 && rmax == 0) {
|
||||
min = lmin;
|
||||
max = lmax;
|
||||
}
|
||||
if (lmin == 0 && lmax == 0) {
|
||||
min = rmin;
|
||||
max = rmax;
|
||||
}
|
||||
|
||||
if (lmax < 0 || rmax < 0) {
|
||||
// Or-ing two values of which at least one is negative results in a negative
|
||||
// value.
|
||||
Handle<Object> max = f->NewNumber(-1);
|
||||
return Type::Range(min, max, t->zone());
|
||||
max = std::min(max, -1.0);
|
||||
}
|
||||
Handle<Object> max = f->NewNumber(Type::Signed32()->Max());
|
||||
return Type::Range(min, max, t->zone());
|
||||
return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
|
||||
// TODO(neis): Be precise for singleton inputs, here and elsewhere.
|
||||
}
|
||||
|
||||
@ -739,18 +749,22 @@ Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
|
||||
double rmin = rhs->Min();
|
||||
double lmax = lhs->Max();
|
||||
double rmax = rhs->Max();
|
||||
double min = Type::Signed32()->Min();
|
||||
// And-ing any two values results in a value no larger than their maximum.
|
||||
// Even no larger than their minimum if both values are non-negative.
|
||||
Handle<Object> max = f->NewNumber(
|
||||
lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax));
|
||||
if (lmin >= 0 || rmin >= 0) {
|
||||
// And-ing two values of which at least one is non-negative results in a
|
||||
// non-negative value.
|
||||
Handle<Object> min = f->NewNumber(0);
|
||||
return Type::Range(min, max, t->zone());
|
||||
double max =
|
||||
lmin >= 0 && rmin >= 0 ? std::min(lmax, rmax) : std::max(lmax, rmax);
|
||||
// And-ing with a non-negative value x causes the result to be between
|
||||
// zero and x.
|
||||
if (lmin >= 0) {
|
||||
min = 0;
|
||||
max = std::min(max, lmax);
|
||||
}
|
||||
Handle<Object> min = f->NewNumber(Type::Signed32()->Min());
|
||||
return Type::Range(min, max, t->zone());
|
||||
if (rmin >= 0) {
|
||||
min = 0;
|
||||
max = std::min(max, rmax);
|
||||
}
|
||||
return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
|
||||
}
|
||||
|
||||
|
||||
@ -780,18 +794,31 @@ Type* Typer::Visitor::JSShiftLeftTyper(Type* lhs, Type* rhs, Typer* t) {
|
||||
|
||||
Type* Typer::Visitor::JSShiftRightTyper(Type* lhs, Type* rhs, Typer* t) {
|
||||
lhs = NumberToInt32(ToNumber(lhs, t), t);
|
||||
Factory* f = t->isolate()->factory();
|
||||
rhs = NumberToUint32(ToNumber(rhs, t), t);
|
||||
double min = kMinInt;
|
||||
double max = kMaxInt;
|
||||
if (lhs->Min() >= 0) {
|
||||
// Right-shifting a non-negative value cannot make it negative, nor larger.
|
||||
Handle<Object> min = f->NewNumber(0);
|
||||
Handle<Object> max = f->NewNumber(lhs->Max());
|
||||
return Type::Range(min, max, t->zone());
|
||||
min = std::max(min, 0.0);
|
||||
max = std::min(max, lhs->Max());
|
||||
}
|
||||
if (lhs->Max() < 0) {
|
||||
// Right-shifting a negative value cannot make it non-negative, nor smaller.
|
||||
Handle<Object> min = f->NewNumber(lhs->Min());
|
||||
Handle<Object> max = f->NewNumber(-1);
|
||||
return Type::Range(min, max, t->zone());
|
||||
min = std::max(min, lhs->Min());
|
||||
max = std::min(max, -1.0);
|
||||
}
|
||||
if (rhs->Min() > 0 && rhs->Max() <= 31) {
|
||||
// Right-shifting by a positive value yields a small integer value.
|
||||
double shift_min = kMinInt >> static_cast<int>(rhs->Min());
|
||||
double shift_max = kMaxInt >> static_cast<int>(rhs->Min());
|
||||
min = std::max(min, shift_min);
|
||||
max = std::min(max, shift_max);
|
||||
}
|
||||
// TODO(jarin) Ideally, the following micro-optimization should be performed
|
||||
// by the type constructor.
|
||||
if (max != Type::Signed32()->Max() || min != Type::Signed32()->Min()) {
|
||||
Factory* f = t->isolate()->factory();
|
||||
return Type::Range(f->NewNumber(min), f->NewNumber(max), t->zone());
|
||||
}
|
||||
return Type::Signed32();
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "src/compiler/pipeline.h"
|
||||
#include "src/compiler/select-lowering.h"
|
||||
#include "src/compiler/simplified-lowering.h"
|
||||
#include "src/compiler/typer.h"
|
||||
#include "src/compiler/verifier.h"
|
||||
#include "src/execution.h"
|
||||
#include "src/globals.h"
|
||||
@ -127,6 +128,8 @@ class ChangesLoweringTester : public GraphBuilderTester<ReturnType> {
|
||||
// Run the graph reducer with changes lowering on a single node.
|
||||
CompilationInfo info(this->isolate(), this->zone());
|
||||
Linkage linkage(this->zone(), &info);
|
||||
Typer typer(this->graph(), info.context());
|
||||
typer.Run();
|
||||
ChangeLowering change_lowering(&jsgraph, &linkage);
|
||||
SelectLowering select_lowering(this->graph(), this->common());
|
||||
GraphReducer reducer(this->graph(), this->zone());
|
||||
|
@ -188,6 +188,7 @@ 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::Signed32()));
|
||||
Reduction reduction = Reduce(node);
|
||||
ASSERT_TRUE(reduction.Changed());
|
||||
|
||||
@ -212,6 +213,19 @@ 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);
|
||||
|
Loading…
Reference in New Issue
Block a user