[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:
jarin 2014-11-17 05:55:27 -08:00 committed by Commit bot
parent 685bc04a01
commit e130d01aee
4 changed files with 69 additions and 22 deletions

View File

@ -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);

View File

@ -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();
}

View File

@ -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());

View File

@ -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);