Commit b93cde37 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Allow non-speculative operators to consume feedback types.

Turn the retyping pass of SimplifiedLowering into a proper phase, and
make it possible to propagate feedback types through non-speculative
operators. This defers the output representation selection to the
retyping phase, and checks that we don't mess up.

As a first user, we consume input type feedback for NumberAbs as well.
Long-term we can add all other operators to the mix.

R=jarin@chromium.org

Review-Url: https://codereview.chromium.org/2139203002
Cr-Commit-Position: refs/heads/master@{#37672}
parent b571026f
......@@ -285,7 +285,7 @@ Type* OperationTyper::ToNumber(Type* type) {
return Type::Number();
}
Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) {
Type* OperationTyper::NumberAdd(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
......@@ -311,7 +311,7 @@ Type* OperationTyper::NumericAdd(Type* lhs, Type* rhs) {
return result;
}
Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) {
Type* OperationTyper::NumberSubtract(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
......@@ -329,7 +329,7 @@ Type* OperationTyper::NumericSubtract(Type* lhs, Type* rhs) {
return Type::Number();
}
Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) {
Type* OperationTyper::NumberMultiply(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
......@@ -346,7 +346,7 @@ Type* OperationTyper::NumericMultiply(Type* lhs, Type* rhs) {
return Type::Number();
}
Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) {
Type* OperationTyper::NumberDivide(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
......@@ -363,7 +363,7 @@ Type* OperationTyper::NumericDivide(Type* lhs, Type* rhs) {
return maybe_nan ? Type::Number() : Type::OrderedNumber();
}
Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) {
Type* OperationTyper::NumberModulus(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
......@@ -387,6 +387,34 @@ Type* OperationTyper::NumericModulus(Type* lhs, Type* rhs) {
return Type::OrderedNumber();
}
Type* OperationTyper::NumberAbs(Type* type) {
DCHECK(type->Is(Type::Number()));
if (!type->IsInhabited()) {
return Type::None();
}
bool const maybe_nan = type->Maybe(Type::NaN());
bool const maybe_minuszero = type->Maybe(Type::MinusZero());
type = Type::Intersect(type, Type::PlainNumber(), zone());
double const max = type->Max();
double const min = type->Min();
if (min < 0) {
if (type->Is(cache_.kInteger)) {
type = Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), zone());
} else {
type = Type::PlainNumber();
}
}
if (maybe_minuszero) {
type = Type::Union(type, cache_.kSingletonZero, zone());
}
if (maybe_nan) {
type = Type::Union(type, Type::NaN(), zone());
}
return type;
}
Type* OperationTyper::ToPrimitive(Type* type) {
if (type->Is(Type::Primitive()) && !type->Maybe(Type::Receiver())) {
return type;
......@@ -439,11 +467,11 @@ Type* OperationTyper::TypeJSAdd(Type* lhs, Type* rhs) {
}
lhs = ToNumber(lhs);
rhs = ToNumber(rhs);
return NumericAdd(lhs, rhs);
return NumberAdd(lhs, rhs);
}
Type* OperationTyper::TypeJSSubtract(Type* lhs, Type* rhs) {
return NumericSubtract(ToNumber(lhs), ToNumber(rhs));
return NumberSubtract(ToNumber(lhs), ToNumber(rhs));
}
} // namespace compiler
......
......@@ -32,11 +32,13 @@ class OperationTyper {
Type* ToNumber(Type* type);
Type* WeakenRange(Type* current_range, Type* previous_range);
Type* NumericAdd(Type* lhs, Type* rhs);
Type* NumericSubtract(Type* lhs, Type* rhs);
Type* NumericMultiply(Type* lhs, Type* rhs);
Type* NumericDivide(Type* lhs, Type* rhs);
Type* NumericModulus(Type* lhs, Type* rhs);
Type* NumberAdd(Type* lhs, Type* rhs);
Type* NumberSubtract(Type* lhs, Type* rhs);
Type* NumberMultiply(Type* lhs, Type* rhs);
Type* NumberDivide(Type* lhs, Type* rhs);
Type* NumberModulus(Type* lhs, Type* rhs);
Type* NumberAbs(Type* type);
enum ComparisonOutcomeFlags {
kComparisonTrue = 1,
......
......@@ -80,6 +80,21 @@ enum class TypeCheckKind : uint8_t {
kNumber
};
inline std::ostream& operator<<(std::ostream& os, TypeCheckKind type_check) {
switch (type_check) {
case TypeCheckKind::kNone:
return os << "None";
case TypeCheckKind::kSigned32:
return os << "Signed32";
case TypeCheckKind::kNumberOrUndefined:
return os << "NumberOrUndefined";
case TypeCheckKind::kNumber:
return os << "Number";
}
UNREACHABLE();
return os;
}
// The {UseInfo} class is used to describe a use of an input of a node.
//
// This information is used in two different ways, based on the phase:
......
......@@ -51,7 +51,10 @@ enum Phase {
// the next phase can begin.
PROPAGATE,
// 2.) LOWER: perform lowering for all {Simplified} nodes by replacing some
// 2.) RETYPE: Propagate types from type feedback forwards.
RETYPE,
// 3.) LOWER: perform lowering for all {Simplified} nodes by replacing some
// operators for some nodes, expanding some nodes to multiple nodes, or
// removing some (redundant) nodes.
// During this phase, use the {RepresentationChanger} to insert
......@@ -60,7 +63,6 @@ enum Phase {
LOWER
};
namespace {
......@@ -246,8 +248,12 @@ class RepresentationSelector {
// Forward propagation of types from type feedback.
void RunTypePropagationPhase() {
DCHECK(typing_stack_.empty());
// Run type propagation.
TRACE("--{Type propagation phase}--\n");
phase_ = RETYPE;
ResetNodeInfoState();
DCHECK(typing_stack_.empty());
typing_stack_.push({graph()->end(), 0});
GetInfo(graph()->end())->set_pushed();
while (!typing_stack_.empty()) {
......@@ -274,6 +280,8 @@ class RepresentationSelector {
NodeInfo* info = GetInfo(node);
info->set_visited();
bool updated = UpdateFeedbackType(node);
TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
VisitNode(node, info->truncation(), nullptr);
if (updated) {
for (Node* const user : node->uses()) {
if (GetInfo(user)->visited()) {
......@@ -291,6 +299,8 @@ class RepresentationSelector {
NodeInfo* info = GetInfo(node);
info->set_visited();
bool updated = UpdateFeedbackType(node);
TRACE(" visit #%d: %s\n", node->id(), node->op()->mnemonic());
VisitNode(node, info->truncation(), nullptr);
if (updated) {
for (Node* const user : node->uses()) {
if (GetInfo(user)->visited()) {
......@@ -376,7 +386,7 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericAdd(lhs, rhs);
Type* static_type = op_typer_.NumberAdd(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
......@@ -393,7 +403,7 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericSubtract(lhs, rhs);
Type* static_type = op_typer_.NumberSubtract(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
......@@ -410,7 +420,7 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericMultiply(lhs, rhs);
Type* static_type = op_typer_.NumberMultiply(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
......@@ -427,7 +437,7 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericDivide(lhs, rhs);
Type* static_type = op_typer_.NumberDivide(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
......@@ -444,7 +454,7 @@ class RepresentationSelector {
// computes a more precise type.
Type* lhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
Type* rhs = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(1)));
Type* static_type = op_typer_.NumericModulus(lhs, rhs);
Type* static_type = op_typer_.NumberModulus(lhs, rhs);
if (info->type_check() == TypeCheckKind::kNone) {
new_type = static_type;
} else {
......@@ -454,24 +464,21 @@ class RepresentationSelector {
break;
}
case IrOpcode::kNumberAbs: {
new_type = op_typer_.NumberAbs(FeedbackTypeOf(node->InputAt(0)));
break;
}
case IrOpcode::kPhi: {
new_type = TypePhi(node);
if (type != nullptr) {
new_type = Weaken(node, type, new_type);
}
// Recompute the phi representation based on the new type.
MachineRepresentation output =
GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type);
ResetOutput(node, output);
break;
}
case IrOpcode::kSelect: {
new_type = TypeSelect(node);
// Recompute representation based on the new type.
MachineRepresentation output =
GetOutputInfoForPhi(node, GetInfo(node)->truncation(), new_type);
ResetOutput(node, output);
break;
}
......@@ -569,8 +576,6 @@ class RepresentationSelector {
void Run(SimplifiedLowering* lowering) {
RunTruncationPropagationPhase();
// Run type propagation.
ResetNodeInfoState();
RunTypePropagationPhase();
// Run lowering and change insertion phase.
......@@ -647,14 +652,26 @@ class RepresentationSelector {
}
}
bool lower() { return phase_ == LOWER; }
bool propagate() { return phase_ == PROPAGATE; }
bool lower() const { return phase_ == LOWER; }
bool retype() const { return phase_ == RETYPE; }
bool propagate() const { return phase_ == PROPAGATE; }
void SetOutput(Node* node, MachineRepresentation representation,
TypeCheckKind type_check = TypeCheckKind::kNone) {
DCHECK(MachineRepresentationIsSubtype(GetInfo(node)->representation(),
representation));
ResetOutput(node, representation, type_check);
NodeInfo* const info = GetInfo(node);
switch (phase_) {
case PROPAGATE:
info->set_type_check(type_check);
break;
case RETYPE:
DCHECK_EQ(info->type_check(), type_check);
info->set_output(representation);
break;
case LOWER:
DCHECK_EQ(info->type_check(), type_check);
DCHECK_EQ(info->representation(), representation);
break;
}
}
void ResetOutput(Node* node, MachineRepresentation representation,
......@@ -715,10 +732,15 @@ class RepresentationSelector {
}
void ProcessInput(Node* node, int index, UseInfo use) {
if (phase_ == PROPAGATE) {
EnqueueInput(node, index, use);
} else {
ConvertInput(node, index, use);
switch (phase_) {
case PROPAGATE:
EnqueueInput(node, index, use);
break;
case RETYPE:
break;
case LOWER:
ConvertInput(node, index, use);
break;
}
}
......@@ -827,12 +849,9 @@ class RepresentationSelector {
}
// Infer representation for phi-like nodes.
MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use,
Type* type = nullptr) {
MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) {
// Compute the representation.
if (type == nullptr) {
type = TypeOf(node);
}
Type* type = TypeOf(node);
if (type->Is(Type::None())) {
return MachineRepresentation::kNone;
} else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
......@@ -949,11 +968,11 @@ class RepresentationSelector {
}
void VisitStateValues(Node* node) {
if (phase_ == PROPAGATE) {
if (propagate()) {
for (int i = 0; i < node->InputCount(); i++) {
EnqueueInput(node, i, UseInfo::Any());
}
} else {
} else if (lower()) {
Zone* zone = jsgraph_->zone();
ZoneVector<MachineType>* types =
new (zone->New(sizeof(ZoneVector<MachineType>)))
......@@ -1578,16 +1597,16 @@ class RepresentationSelector {
return;
}
case IrOpcode::kNumberAbs: {
if (InputIs(node, Type::Unsigned32())) {
if (TypeOf(node->InputAt(0))->Is(Type::Unsigned32())) {
VisitUnop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, node->InputAt(0));
} else if (InputIs(node, Type::Signed32())) {
} else if (TypeOf(node->InputAt(0))->Is(Type::Signed32())) {
VisitUnop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, lowering->Int32Abs(node));
} else if (InputIs(node,
type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) {
} else if (TypeOf(node->InputAt(0))
->Is(type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) {
VisitUnop(node, UseInfo::TruncatingFloat64(),
MachineRepresentation::kFloat64);
if (lower()) DeferReplacement(node, node->InputAt(0));
......
......@@ -254,7 +254,6 @@ class Typer::Visitor : public Reducer {
static Type* ToNumber(Type*, Typer*);
static Type* ToObject(Type*, Typer*);
static Type* ToString(Type*, Typer*);
static Type* NumberAbs(Type*, Typer*);
static Type* NumberCeil(Type*, Typer*);
static Type* NumberFloor(Type*, Typer*);
static Type* NumberRound(Type*, Typer*);
......@@ -491,34 +490,6 @@ Type* Typer::Visitor::ToString(Type* type, Typer* t) {
return Type::String();
}
// static
Type* Typer::Visitor::NumberAbs(Type* type, Typer* t) {
DCHECK(type->Is(Type::Number()));
Factory* const f = t->isolate()->factory();
bool const maybe_nan = type->Maybe(Type::NaN());
bool const maybe_minuszero = type->Maybe(Type::MinusZero());
type = Type::Intersect(type, Type::PlainNumber(), t->zone());
double const max = type->Max();
double const min = type->Min();
if (min < 0) {
if (type->Is(t->cache_.kInteger)) {
type =
Type::Range(0.0, std::max(std::fabs(min), std::fabs(max)), t->zone());
} else if (min == max) {
type = Type::Constant(f->NewNumber(std::fabs(min)), t->zone());
} else {
type = Type::PlainNumber();
}
}
if (maybe_minuszero) {
type = Type::Union(type, t->cache_.kSingletonZero, t->zone());
}
if (maybe_nan) {
type = Type::Union(type, Type::NaN(), t->zone());
}
return type;
}
// static
Type* Typer::Visitor::NumberCeil(Type* type, Typer* t) {
DCHECK(type->Is(Type::Number()));
......@@ -1055,36 +1026,26 @@ Type* Typer::Visitor::JSAddTyper(Type* lhs, Type* rhs, Typer* t) {
}
}
// The addition must be numeric.
return t->operation_typer()->NumericAdd(ToNumber(lhs, t), ToNumber(rhs, t));
return t->operation_typer()->NumberAdd(ToNumber(lhs, t), ToNumber(rhs, t));
}
Type* Typer::Visitor::JSSubtractTyper(Type* lhs, Type* rhs, Typer* t) {
return t->operation_typer()->NumericSubtract(ToNumber(lhs, t),
ToNumber(rhs, t));
return t->operation_typer()->NumberSubtract(ToNumber(lhs, t),
ToNumber(rhs, t));
}
Type* Typer::Visitor::JSMultiplyTyper(Type* lhs, Type* rhs, Typer* t) {
return t->operation_typer()->NumericMultiply(ToNumber(lhs, t),
ToNumber(rhs, t));
return t->operation_typer()->NumberMultiply(ToNumber(lhs, t),
ToNumber(rhs, t));
}
Type* Typer::Visitor::JSDivideTyper(Type* lhs, Type* rhs, Typer* t) {
return t->operation_typer()->NumericDivide(ToNumber(lhs, t),
ToNumber(rhs, t));
lhs = ToNumber(lhs, t);
rhs = ToNumber(rhs, t);
if (lhs->Is(Type::NaN()) || rhs->Is(Type::NaN())) return Type::NaN();
// Division is tricky, so all we do is try ruling out nan.
bool maybe_nan =
lhs->Maybe(Type::NaN()) || rhs->Maybe(t->cache_.kZeroish) ||
((lhs->Min() == -V8_INFINITY || lhs->Max() == +V8_INFINITY) &&
(rhs->Min() == -V8_INFINITY || rhs->Max() == +V8_INFINITY));
return maybe_nan ? Type::Number() : Type::OrderedNumber();
return t->operation_typer()->NumberDivide(ToNumber(lhs, t), ToNumber(rhs, t));
}
Type* Typer::Visitor::JSModulusTyper(Type* lhs, Type* rhs, Typer* t) {
return t->operation_typer()->NumericModulus(ToNumber(lhs, t),
ToNumber(rhs, t));
return t->operation_typer()->NumberModulus(ToNumber(lhs, t),
ToNumber(rhs, t));
}
......@@ -1645,7 +1606,7 @@ Type* Typer::Visitor::TypePlainPrimitiveToFloat64(Node* node) {
Type* Typer::Visitor::TypeNumberImul(Node* node) { return Type::Signed32(); }
Type* Typer::Visitor::TypeNumberAbs(Node* node) {
return TypeUnaryOp(node, NumberAbs);
return typer_->operation_typer()->NumberAbs(Operand(node, 0));
}
Type* Typer::Visitor::TypeNumberClz32(Node* node) {
......
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