Upgrade V8 to 5.1.281.57 DO NOT MERGE
FPIIM-449
Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
index ed7fe9d..88931f5 100644
--- a/src/compiler/simplified-lowering.cc
+++ b/src/compiler/simplified-lowering.cc
@@ -104,15 +104,6 @@
static UseInfo None() {
return UseInfo(MachineRepresentation::kNone, Truncation::None());
}
-
- // Truncation to a representation that is smaller than the preferred
- // one.
- static UseInfo Float64TruncatingToWord32() {
- return UseInfo(MachineRepresentation::kFloat64, Truncation::Word32());
- }
- static UseInfo Word64TruncatingToWord32() {
- return UseInfo(MachineRepresentation::kWord64, Truncation::Word32());
- }
static UseInfo AnyTruncatingToBool() {
return UseInfo(MachineRepresentation::kNone, Truncation::Bool());
}
@@ -242,71 +233,6 @@
class RepresentationSelector {
public:
// Information for each node tracked during the fixpoint.
- class NodeOutputInfo {
- public:
- NodeOutputInfo(MachineRepresentation representation, Type* type)
- : type_(type), representation_(representation) {}
- NodeOutputInfo()
- : type_(Type::None()), representation_(MachineRepresentation::kNone) {}
-
- MachineRepresentation representation() const { return representation_; }
- Type* type() const { return type_; }
-
- static NodeOutputInfo None() {
- return NodeOutputInfo(MachineRepresentation::kNone, Type::None());
- }
-
- static NodeOutputInfo Float32() {
- return NodeOutputInfo(MachineRepresentation::kFloat32, Type::Number());
- }
-
- static NodeOutputInfo Float64() {
- return NodeOutputInfo(MachineRepresentation::kFloat64, Type::Number());
- }
-
- static NodeOutputInfo NumberTruncatedToWord32() {
- return NodeOutputInfo(MachineRepresentation::kWord32, Type::Number());
- }
-
- static NodeOutputInfo Int32() {
- return NodeOutputInfo(MachineRepresentation::kWord32, Type::Signed32());
- }
-
- static NodeOutputInfo Uint32() {
- return NodeOutputInfo(MachineRepresentation::kWord32, Type::Unsigned32());
- }
-
- static NodeOutputInfo Bool() {
- return NodeOutputInfo(MachineRepresentation::kBit, Type::Boolean());
- }
-
- static NodeOutputInfo Int64() {
- // TODO(jarin) Fix once we have a real int64 type.
- return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
- }
-
- static NodeOutputInfo Uint64() {
- // TODO(jarin) Fix once we have a real uint64 type.
- return NodeOutputInfo(MachineRepresentation::kWord64, Type::Internal());
- }
-
- static NodeOutputInfo AnyTagged() {
- return NodeOutputInfo(MachineRepresentation::kTagged, Type::Any());
- }
-
- static NodeOutputInfo NumberTagged() {
- return NodeOutputInfo(MachineRepresentation::kTagged, Type::Number());
- }
-
- static NodeOutputInfo Pointer() {
- return NodeOutputInfo(MachineType::PointerRepresentation(), Type::Any());
- }
-
- private:
- Type* type_;
- MachineRepresentation representation_;
- };
-
class NodeInfo {
public:
// Adds new use to the node. Returns true if something has changed
@@ -322,17 +248,15 @@
void set_visited() { visited_ = true; }
bool visited() const { return visited_; }
Truncation truncation() const { return truncation_; }
- void set_output_type(NodeOutputInfo output) { output_ = output; }
+ void set_output(MachineRepresentation output) { representation_ = output; }
- Type* output_type() const { return output_.type(); }
- MachineRepresentation representation() const {
- return output_.representation();
- }
+ MachineRepresentation representation() const { return representation_; }
private:
- bool queued_ = false; // Bookkeeping for the traversal.
- bool visited_ = false; // Bookkeeping for the traversal.
- NodeOutputInfo output_; // Output type and representation.
+ bool queued_ = false; // Bookkeeping for the traversal.
+ bool visited_ = false; // Bookkeeping for the traversal.
+ MachineRepresentation representation_ =
+ MachineRepresentation::kNone; // Output representation.
Truncation truncation_ = Truncation::None(); // Information about uses.
};
@@ -467,76 +391,31 @@
}
}
- void SetOutputFromMachineType(Node* node, MachineType machine_type) {
- Type* type = Type::None();
- switch (machine_type.semantic()) {
- case MachineSemantic::kNone:
- type = Type::None();
- break;
- case MachineSemantic::kBool:
- type = Type::Boolean();
- break;
- case MachineSemantic::kInt32:
- type = Type::Signed32();
- break;
- case MachineSemantic::kUint32:
- type = Type::Unsigned32();
- break;
- case MachineSemantic::kInt64:
- // TODO(jarin) Fix once we have proper int64.
- type = Type::Internal();
- break;
- case MachineSemantic::kUint64:
- // TODO(jarin) Fix once we have proper uint64.
- type = Type::Internal();
- break;
- case MachineSemantic::kNumber:
- type = Type::Number();
- break;
- case MachineSemantic::kAny:
- type = Type::Any();
- break;
- }
- return SetOutput(node, NodeOutputInfo(machine_type.representation(), type));
+ void SetOutput(Node* node, MachineRepresentation representation) {
+ NodeInfo* info = GetInfo(node);
+ DCHECK(
+ MachineRepresentationIsSubtype(info->representation(), representation));
+ info->set_output(representation);
}
- void SetOutput(Node* node, NodeOutputInfo output_info) {
- // Every node should have at most one output representation. Note that
- // phis can have 0, if they have not been used in a representation-inducing
- // instruction.
- Type* output_type = output_info.type();
- if (NodeProperties::IsTyped(node)) {
- output_type = Type::Intersect(NodeProperties::GetType(node),
- output_info.type(), jsgraph_->zone());
- }
- NodeInfo* info = GetInfo(node);
- DCHECK(info->output_type()->Is(output_type));
- DCHECK(MachineRepresentationIsSubtype(info->representation(),
- output_info.representation()));
- if (!output_type->Is(info->output_type()) ||
- output_info.representation() != info->representation()) {
- EnqueueUses(node);
- }
- info->set_output_type(
- NodeOutputInfo(output_info.representation(), output_type));
- }
+ Type* GetUpperBound(Node* node) { return NodeProperties::GetType(node); }
bool BothInputsAreSigned32(Node* node) {
DCHECK_EQ(2, node->InputCount());
- return GetInfo(node->InputAt(0))->output_type()->Is(Type::Signed32()) &&
- GetInfo(node->InputAt(1))->output_type()->Is(Type::Signed32());
+ return GetUpperBound(node->InputAt(0))->Is(Type::Signed32()) &&
+ GetUpperBound(node->InputAt(1))->Is(Type::Signed32());
}
bool BothInputsAreUnsigned32(Node* node) {
DCHECK_EQ(2, node->InputCount());
- return GetInfo(node->InputAt(0))->output_type()->Is(Type::Unsigned32()) &&
- GetInfo(node->InputAt(1))->output_type()->Is(Type::Unsigned32());
+ return GetUpperBound(node->InputAt(0))->Is(Type::Unsigned32()) &&
+ GetUpperBound(node->InputAt(1))->Is(Type::Unsigned32());
}
bool BothInputsAre(Node* node, Type* type) {
DCHECK_EQ(2, node->InputCount());
- return GetInfo(node->InputAt(0))->output_type()->Is(type) &&
- GetInfo(node->InputAt(1))->output_type()->Is(type);
+ return GetUpperBound(node->InputAt(0))->Is(type) &&
+ GetUpperBound(node->InputAt(1))->Is(type);
}
void ConvertInput(Node* node, int index, UseInfo use) {
@@ -556,7 +435,7 @@
PrintUseInfo(use);
TRACE("\n");
Node* n = changer_->GetRepresentationFor(
- input, input_info->representation(), input_info->output_type(),
+ input, input_info->representation(), GetUpperBound(input),
use.preferred(), use.truncation());
node->ReplaceInput(index, n);
}
@@ -602,7 +481,7 @@
// Helper for binops of the R x L -> O variety.
void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
- NodeOutputInfo output) {
+ MachineRepresentation output) {
DCHECK_EQ(2, node->op()->ValueInputCount());
ProcessInput(node, 0, left_use);
ProcessInput(node, 1, right_use);
@@ -613,80 +492,77 @@
}
// Helper for binops of the I x I -> O variety.
- void VisitBinop(Node* node, UseInfo input_use, NodeOutputInfo output) {
+ void VisitBinop(Node* node, UseInfo input_use, MachineRepresentation output) {
VisitBinop(node, input_use, input_use, output);
}
// Helper for unops of the I -> O variety.
- void VisitUnop(Node* node, UseInfo input_use, NodeOutputInfo output) {
+ void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) {
DCHECK_EQ(1, node->InputCount());
ProcessInput(node, 0, input_use);
SetOutput(node, output);
}
// Helper for leaf nodes.
- void VisitLeaf(Node* node, NodeOutputInfo output) {
+ void VisitLeaf(Node* node, MachineRepresentation output) {
DCHECK_EQ(0, node->InputCount());
SetOutput(node, output);
}
// Helpers for specific types of binops.
void VisitFloat64Binop(Node* node) {
- VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
+ VisitBinop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
}
void VisitInt32Binop(Node* node) {
- VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
+ VisitBinop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kWord32);
}
void VisitWord32TruncatingBinop(Node* node) {
VisitBinop(node, UseInfo::TruncatingWord32(),
- NodeOutputInfo::NumberTruncatedToWord32());
+ MachineRepresentation::kWord32);
}
void VisitUint32Binop(Node* node) {
- VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
+ VisitBinop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kWord32);
}
void VisitInt64Binop(Node* node) {
- VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Int64());
+ VisitBinop(node, UseInfo::TruncatingWord64(),
+ MachineRepresentation::kWord64);
}
void VisitUint64Binop(Node* node) {
- VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Uint64());
+ VisitBinop(node, UseInfo::TruncatingWord64(),
+ MachineRepresentation::kWord64);
}
void VisitFloat64Cmp(Node* node) {
- VisitBinop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
+ VisitBinop(node, UseInfo::Float64(), MachineRepresentation::kBit);
}
void VisitInt32Cmp(Node* node) {
- VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
+ VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
}
void VisitUint32Cmp(Node* node) {
- VisitBinop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Bool());
+ VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit);
}
void VisitInt64Cmp(Node* node) {
- VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
+ VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
}
void VisitUint64Cmp(Node* node) {
- VisitBinop(node, UseInfo::TruncatingWord64(), NodeOutputInfo::Bool());
+ VisitBinop(node, UseInfo::TruncatingWord64(), MachineRepresentation::kBit);
}
// Infer representation for phi-like nodes.
- NodeOutputInfo GetOutputInfoForPhi(Node* node, Truncation use) {
- // Compute the type.
- Type* type = GetInfo(node->InputAt(0))->output_type();
- for (int i = 1; i < node->op()->ValueInputCount(); ++i) {
- type = Type::Union(type, GetInfo(node->InputAt(i))->output_type(),
- jsgraph_->zone());
- }
-
+ MachineRepresentation GetOutputInfoForPhi(Node* node, Truncation use) {
// Compute the representation.
- MachineRepresentation rep = MachineRepresentation::kTagged;
+ Type* type = GetUpperBound(node);
if (type->Is(Type::None())) {
- rep = MachineRepresentation::kNone;
+ return MachineRepresentation::kNone;
} else if (type->Is(Type::Signed32()) || type->Is(Type::Unsigned32())) {
- rep = MachineRepresentation::kWord32;
+ return MachineRepresentation::kWord32;
} else if (use.TruncatesToWord32()) {
- rep = MachineRepresentation::kWord32;
+ return MachineRepresentation::kWord32;
} else if (type->Is(Type::Boolean())) {
- rep = MachineRepresentation::kBit;
+ return MachineRepresentation::kBit;
} else if (type->Is(Type::Number())) {
- rep = MachineRepresentation::kFloat64;
+ return MachineRepresentation::kFloat64;
} else if (type->Is(Type::Internal())) {
// We mark (u)int64 as Type::Internal.
// TODO(jarin) This is a workaround for our lack of (u)int64
@@ -702,10 +578,10 @@
MachineRepresentation::kWord64);
}
#endif
- rep = is_word64 ? MachineRepresentation::kWord64
- : MachineRepresentation::kTagged;
+ return is_word64 ? MachineRepresentation::kWord64
+ : MachineRepresentation::kTagged;
}
- return NodeOutputInfo(rep, type);
+ return MachineRepresentation::kTagged;
}
// Helper for handling selects.
@@ -713,20 +589,20 @@
SimplifiedLowering* lowering) {
ProcessInput(node, 0, UseInfo::Bool());
- NodeOutputInfo output = GetOutputInfoForPhi(node, truncation);
+ MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
SetOutput(node, output);
if (lower()) {
// Update the select operator.
SelectParameters p = SelectParametersOf(node->op());
- if (output.representation() != p.representation()) {
- NodeProperties::ChangeOp(node, lowering->common()->Select(
- output.representation(), p.hint()));
+ if (output != p.representation()) {
+ NodeProperties::ChangeOp(node,
+ lowering->common()->Select(output, p.hint()));
}
}
// Convert inputs to the output representation of this phi, pass the
// truncation truncation along.
- UseInfo input_use(output.representation(), truncation);
+ UseInfo input_use(output, truncation);
ProcessInput(node, 1, input_use);
ProcessInput(node, 2, input_use);
}
@@ -734,21 +610,20 @@
// Helper for handling phis.
void VisitPhi(Node* node, Truncation truncation,
SimplifiedLowering* lowering) {
- NodeOutputInfo output = GetOutputInfoForPhi(node, truncation);
+ MachineRepresentation output = GetOutputInfoForPhi(node, truncation);
SetOutput(node, output);
int values = node->op()->ValueInputCount();
if (lower()) {
// Update the phi operator.
- if (output.representation() != PhiRepresentationOf(node->op())) {
- NodeProperties::ChangeOp(
- node, lowering->common()->Phi(output.representation(), values));
+ if (output != PhiRepresentationOf(node->op())) {
+ NodeProperties::ChangeOp(node, lowering->common()->Phi(output, values));
}
}
// Convert inputs to the output representation of this phi, pass the
// truncation truncation along.
- UseInfo input_use(output.representation(), truncation);
+ UseInfo input_use(output, truncation);
for (int i = 0; i < node->InputCount(); i++) {
ProcessInput(node, i, i < values ? input_use : UseInfo::None());
}
@@ -772,9 +647,10 @@
}
if (sig->return_count() > 0) {
- SetOutputFromMachineType(node, desc->GetMachineSignature()->GetReturn());
+ SetOutput(node,
+ desc->GetMachineSignature()->GetReturn().representation());
} else {
- SetOutput(node, NodeOutputInfo::AnyTagged());
+ SetOutput(node, MachineRepresentation::kTagged);
}
}
@@ -801,10 +677,10 @@
new (zone->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(node->InputCount(), zone);
for (int i = 0; i < node->InputCount(); i++) {
- NodeInfo* input_info = GetInfo(node->InputAt(i));
- MachineType machine_type(
- input_info->representation(),
- DeoptValueSemanticOf(input_info->output_type()));
+ Node* input = node->InputAt(i);
+ NodeInfo* input_info = GetInfo(input);
+ MachineType machine_type(input_info->representation(),
+ DeoptValueSemanticOf(GetUpperBound(input)));
DCHECK(machine_type.representation() !=
MachineRepresentation::kWord32 ||
machine_type.semantic() == MachineSemantic::kInt32 ||
@@ -814,7 +690,7 @@
NodeProperties::ChangeOp(node,
jsgraph_->common()->TypedStateValues(types));
}
- SetOutput(node, NodeOutputInfo::AnyTagged());
+ SetOutput(node, MachineRepresentation::kTagged);
}
const Operator* Int32Op(Node* node) {
@@ -839,29 +715,34 @@
//------------------------------------------------------------------
case IrOpcode::kStart:
case IrOpcode::kDead:
- return VisitLeaf(node, NodeOutputInfo::None());
+ return VisitLeaf(node, MachineRepresentation::kNone);
case IrOpcode::kParameter: {
// TODO(titzer): use representation from linkage.
- Type* type = NodeProperties::GetType(node);
ProcessInput(node, 0, UseInfo::None());
- SetOutput(node, NodeOutputInfo(MachineRepresentation::kTagged, type));
+ SetOutput(node, MachineRepresentation::kTagged);
return;
}
case IrOpcode::kInt32Constant:
- return VisitLeaf(node, NodeOutputInfo::Int32());
+ return VisitLeaf(node, MachineRepresentation::kWord32);
case IrOpcode::kInt64Constant:
- return VisitLeaf(node, NodeOutputInfo::Int64());
+ return VisitLeaf(node, MachineRepresentation::kWord64);
case IrOpcode::kFloat32Constant:
- return VisitLeaf(node, NodeOutputInfo::Float32());
+ return VisitLeaf(node, MachineRepresentation::kFloat32);
case IrOpcode::kFloat64Constant:
- return VisitLeaf(node, NodeOutputInfo::Float64());
+ return VisitLeaf(node, MachineRepresentation::kFloat64);
case IrOpcode::kExternalConstant:
- return VisitLeaf(node, NodeOutputInfo::Pointer());
+ return VisitLeaf(node, MachineType::PointerRepresentation());
case IrOpcode::kNumberConstant:
- return VisitLeaf(node, NodeOutputInfo::NumberTagged());
+ return VisitLeaf(node, MachineRepresentation::kTagged);
case IrOpcode::kHeapConstant:
- return VisitLeaf(node, NodeOutputInfo::AnyTagged());
+ return VisitLeaf(node, MachineRepresentation::kTagged);
+ case IrOpcode::kDeoptimizeIf:
+ case IrOpcode::kDeoptimizeUnless:
+ ProcessInput(node, 0, UseInfo::Bool());
+ ProcessInput(node, 1, UseInfo::AnyTagged());
+ ProcessRemainingInputs(node, 2);
+ break;
case IrOpcode::kBranch:
ProcessInput(node, 0, UseInfo::Bool());
EnqueueInput(node, NodeProperties::FirstControlIndex(node));
@@ -889,7 +770,7 @@
JS_OP_LIST(DEFINE_JS_CASE)
#undef DEFINE_JS_CASE
VisitInputs(node);
- return SetOutput(node, NodeOutputInfo::AnyTagged());
+ return SetOutput(node, MachineRepresentation::kTagged);
//------------------------------------------------------------------
// Simplified operators.
@@ -909,7 +790,7 @@
} else {
// No input representation requirement; adapt during lowering.
ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
- SetOutput(node, NodeOutputInfo::Bool());
+ SetOutput(node, MachineRepresentation::kBit);
}
break;
}
@@ -927,7 +808,7 @@
} else {
// No input representation requirement; adapt during lowering.
ProcessInput(node, 0, UseInfo::AnyTruncatingToBool());
- SetOutput(node, NodeOutputInfo::Int32());
+ SetOutput(node, MachineRepresentation::kWord32);
}
break;
}
@@ -1055,46 +936,80 @@
break;
}
case IrOpcode::kNumberShiftLeft: {
- Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
+ Type* rhs_type = GetUpperBound(node->InputAt(1));
VisitBinop(node, UseInfo::TruncatingWord32(),
- UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
+ UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
if (lower()) {
lowering->DoShift(node, lowering->machine()->Word32Shl(), rhs_type);
}
break;
}
case IrOpcode::kNumberShiftRight: {
- Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
+ Type* rhs_type = GetUpperBound(node->InputAt(1));
VisitBinop(node, UseInfo::TruncatingWord32(),
- UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
+ UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
if (lower()) {
lowering->DoShift(node, lowering->machine()->Word32Sar(), rhs_type);
}
break;
}
case IrOpcode::kNumberShiftRightLogical: {
- Type* rhs_type = GetInfo(node->InputAt(1))->output_type();
+ Type* rhs_type = GetUpperBound(node->InputAt(1));
VisitBinop(node, UseInfo::TruncatingWord32(),
- UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
+ UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
if (lower()) {
lowering->DoShift(node, lowering->machine()->Word32Shr(), rhs_type);
}
break;
}
+ case IrOpcode::kNumberImul: {
+ VisitBinop(node, UseInfo::TruncatingWord32(),
+ UseInfo::TruncatingWord32(), MachineRepresentation::kWord32);
+ if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
+ break;
+ }
+ case IrOpcode::kNumberClz32: {
+ VisitUnop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kWord32);
+ if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node));
+ break;
+ }
+ case IrOpcode::kNumberCeil: {
+ VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ if (lower()) DeferReplacement(node, lowering->Float64Ceil(node));
+ break;
+ }
+ case IrOpcode::kNumberFloor: {
+ VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ if (lower()) DeferReplacement(node, lowering->Float64Floor(node));
+ break;
+ }
+ case IrOpcode::kNumberRound: {
+ VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ if (lower()) DeferReplacement(node, lowering->Float64Round(node));
+ break;
+ }
+ case IrOpcode::kNumberTrunc: {
+ VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kFloat64);
+ if (lower()) DeferReplacement(node, lowering->Float64Trunc(node));
+ break;
+ }
case IrOpcode::kNumberToInt32: {
// Just change representation if necessary.
- VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Int32());
+ VisitUnop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, node->InputAt(0));
break;
}
case IrOpcode::kNumberToUint32: {
// Just change representation if necessary.
- VisitUnop(node, UseInfo::TruncatingWord32(), NodeOutputInfo::Uint32());
+ VisitUnop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kWord32);
if (lower()) DeferReplacement(node, node->InputAt(0));
break;
}
case IrOpcode::kNumberIsHoleNaN: {
- VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Bool());
+ VisitUnop(node, UseInfo::Float64(), MachineRepresentation::kBit);
if (lower()) {
// NumberIsHoleNaN(x) => Word32Equal(Float64ExtractLowWord32(x),
// #HoleNaNLower32)
@@ -1109,7 +1024,7 @@
break;
}
case IrOpcode::kPlainPrimitiveToNumber: {
- VisitUnop(node, UseInfo::AnyTagged(), NodeOutputInfo::NumberTagged());
+ VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
if (lower()) {
// PlainPrimitiveToNumber(x) => Call(ToNumberStub, x, no-context)
Operator::Properties properties = node->op()->properties();
@@ -1126,38 +1041,93 @@
break;
}
case IrOpcode::kReferenceEqual: {
- VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
+ VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
if (lower()) {
NodeProperties::ChangeOp(node, lowering->machine()->WordEqual());
}
break;
}
case IrOpcode::kStringEqual: {
- VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
- if (lower()) lowering->DoStringEqual(node);
+ VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
+ if (lower()) {
+ // StringEqual(x, y) => Call(StringEqualStub, x, y, no-context)
+ Operator::Properties properties = node->op()->properties();
+ Callable callable = CodeFactory::StringEqual(jsgraph_->isolate());
+ CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+ jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
+ flags, properties);
+ node->InsertInput(jsgraph_->zone(), 0,
+ jsgraph_->HeapConstant(callable.code()));
+ node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+ NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
+ }
break;
}
case IrOpcode::kStringLessThan: {
- VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
- if (lower()) lowering->DoStringLessThan(node);
+ VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
+ if (lower()) {
+ // StringLessThan(x, y) => Call(StringLessThanStub, x, y, no-context)
+ Operator::Properties properties = node->op()->properties();
+ Callable callable = CodeFactory::StringLessThan(jsgraph_->isolate());
+ CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+ jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
+ flags, properties);
+ node->InsertInput(jsgraph_->zone(), 0,
+ jsgraph_->HeapConstant(callable.code()));
+ node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+ NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
+ }
break;
}
case IrOpcode::kStringLessThanOrEqual: {
- VisitBinop(node, UseInfo::AnyTagged(), NodeOutputInfo::Bool());
- if (lower()) lowering->DoStringLessThanOrEqual(node);
+ VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
+ if (lower()) {
+ // StringLessThanOrEqual(x, y)
+ // => Call(StringLessThanOrEqualStub, x, y, no-context)
+ Operator::Properties properties = node->op()->properties();
+ Callable callable =
+ CodeFactory::StringLessThanOrEqual(jsgraph_->isolate());
+ CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+ jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
+ flags, properties);
+ node->InsertInput(jsgraph_->zone(), 0,
+ jsgraph_->HeapConstant(callable.code()));
+ node->InsertInput(jsgraph_->zone(), 3, jsgraph_->NoContextConstant());
+ NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
+ }
+ break;
+ }
+ case IrOpcode::kStringToNumber: {
+ VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
+ if (lower()) {
+ // StringToNumber(x) => Call(StringToNumberStub, x, no-context)
+ Operator::Properties properties = node->op()->properties();
+ Callable callable = CodeFactory::StringToNumber(jsgraph_->isolate());
+ CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
+ CallDescriptor* desc = Linkage::GetStubCallDescriptor(
+ jsgraph_->isolate(), jsgraph_->zone(), callable.descriptor(), 0,
+ flags, properties);
+ node->InsertInput(jsgraph_->zone(), 0,
+ jsgraph_->HeapConstant(callable.code()));
+ node->AppendInput(jsgraph_->zone(), jsgraph_->NoContextConstant());
+ NodeProperties::ChangeOp(node, jsgraph_->common()->Call(desc));
+ }
break;
}
case IrOpcode::kAllocate: {
ProcessInput(node, 0, UseInfo::AnyTagged());
ProcessRemainingInputs(node, 1);
- SetOutput(node, NodeOutputInfo::AnyTagged());
+ SetOutput(node, MachineRepresentation::kTagged);
break;
}
case IrOpcode::kLoadField: {
FieldAccess access = FieldAccessOf(node->op());
ProcessInput(node, 0, UseInfoForBasePointer(access));
ProcessRemainingInputs(node, 1);
- SetOutputFromMachineType(node, access.machine_type);
+ SetOutput(node, access.machine_type.representation());
break;
}
case IrOpcode::kStoreField: {
@@ -1166,7 +1136,7 @@
ProcessInput(node, 1, TruncatingUseInfoFromRepresentation(
access.machine_type.representation()));
ProcessRemainingInputs(node, 2);
- SetOutput(node, NodeOutputInfo::None());
+ SetOutput(node, MachineRepresentation::kNone);
break;
}
case IrOpcode::kLoadBuffer: {
@@ -1176,29 +1146,26 @@
ProcessInput(node, 2, UseInfo::TruncatingWord32()); // length
ProcessRemainingInputs(node, 3);
- NodeOutputInfo output_info;
+ MachineRepresentation output;
if (truncation.TruncatesUndefinedToZeroOrNaN()) {
if (truncation.TruncatesNaNToZero()) {
// If undefined is truncated to a non-NaN number, we can use
// the load's representation.
- output_info = NodeOutputInfo(access.machine_type().representation(),
- NodeProperties::GetType(node));
+ output = access.machine_type().representation();
} else {
// If undefined is truncated to a number, but the use can
// observe NaN, we need to output at least the float32
// representation.
if (access.machine_type().representation() ==
MachineRepresentation::kFloat32) {
- output_info =
- NodeOutputInfo(access.machine_type().representation(),
- NodeProperties::GetType(node));
+ output = access.machine_type().representation();
} else {
if (access.machine_type().representation() !=
MachineRepresentation::kFloat64) {
// TODO(bmeurer): See comment on abort_compilation_.
if (lower()) lowering->abort_compilation_ = true;
}
- output_info = NodeOutputInfo::Float64();
+ output = MachineRepresentation::kFloat64;
}
}
} else {
@@ -1207,11 +1174,10 @@
// If undefined is not truncated away, we need to have the tagged
// representation.
- output_info = NodeOutputInfo::AnyTagged();
+ output = MachineRepresentation::kTagged;
}
- SetOutput(node, output_info);
- if (lower())
- lowering->DoLoadBuffer(node, output_info.representation(), changer_);
+ SetOutput(node, output);
+ if (lower()) lowering->DoLoadBuffer(node, output, changer_);
break;
}
case IrOpcode::kStoreBuffer: {
@@ -1223,7 +1189,7 @@
TruncatingUseInfoFromRepresentation(
access.machine_type().representation())); // value
ProcessRemainingInputs(node, 4);
- SetOutput(node, NodeOutputInfo::None());
+ SetOutput(node, MachineRepresentation::kNone);
if (lower()) lowering->DoStoreBuffer(node);
break;
}
@@ -1232,7 +1198,7 @@
ProcessInput(node, 0, UseInfoForBasePointer(access)); // base
ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index
ProcessRemainingInputs(node, 2);
- SetOutputFromMachineType(node, access.machine_type);
+ SetOutput(node, access.machine_type.representation());
break;
}
case IrOpcode::kStoreElement: {
@@ -1243,22 +1209,15 @@
TruncatingUseInfoFromRepresentation(
access.machine_type.representation())); // value
ProcessRemainingInputs(node, 3);
- SetOutput(node, NodeOutputInfo::None());
+ SetOutput(node, MachineRepresentation::kNone);
break;
}
- case IrOpcode::kObjectIsNumber: {
+ case IrOpcode::kObjectIsNumber:
+ case IrOpcode::kObjectIsReceiver:
+ case IrOpcode::kObjectIsSmi:
+ case IrOpcode::kObjectIsUndetectable: {
ProcessInput(node, 0, UseInfo::AnyTagged());
- SetOutput(node, NodeOutputInfo::Bool());
- break;
- }
- case IrOpcode::kObjectIsReceiver: {
- ProcessInput(node, 0, UseInfo::AnyTagged());
- SetOutput(node, NodeOutputInfo::Bool());
- break;
- }
- case IrOpcode::kObjectIsSmi: {
- ProcessInput(node, 0, UseInfo::AnyTagged());
- SetOutput(node, NodeOutputInfo::Bool());
+ SetOutput(node, MachineRepresentation::kBit);
break;
}
@@ -1272,7 +1231,7 @@
ProcessInput(node, 0, UseInfo::AnyTagged()); // tagged pointer
ProcessInput(node, 1, UseInfo::PointerInt()); // index
ProcessRemainingInputs(node, 2);
- SetOutputFromMachineType(node, rep);
+ SetOutput(node, rep.representation());
break;
}
case IrOpcode::kStore: {
@@ -1284,13 +1243,13 @@
ProcessInput(node, 2,
TruncatingUseInfoFromRepresentation(rep.representation()));
ProcessRemainingInputs(node, 3);
- SetOutput(node, NodeOutputInfo::None());
+ SetOutput(node, MachineRepresentation::kNone);
break;
}
case IrOpcode::kWord32Shr:
// We output unsigned int32 for shift right because JavaScript.
return VisitBinop(node, UseInfo::TruncatingWord32(),
- NodeOutputInfo::Uint32());
+ MachineRepresentation::kWord32);
case IrOpcode::kWord32And:
case IrOpcode::kWord32Or:
case IrOpcode::kWord32Xor:
@@ -1300,14 +1259,14 @@
// though the machine bits are the same for either signed or unsigned,
// because JavaScript considers the result from these operations signed.
return VisitBinop(node, UseInfo::TruncatingWord32(),
- NodeOutputInfo::Int32());
+ MachineRepresentation::kWord32);
case IrOpcode::kWord32Equal:
return VisitBinop(node, UseInfo::TruncatingWord32(),
- NodeOutputInfo::Bool());
+ MachineRepresentation::kBit);
case IrOpcode::kWord32Clz:
return VisitUnop(node, UseInfo::TruncatingWord32(),
- NodeOutputInfo::Uint32());
+ MachineRepresentation::kWord32);
case IrOpcode::kInt32Add:
case IrOpcode::kInt32Sub:
@@ -1352,45 +1311,33 @@
case IrOpcode::kWord64Shr:
case IrOpcode::kWord64Sar:
return VisitBinop(node, UseInfo::TruncatingWord64(),
- NodeOutputInfo::Int64());
+ MachineRepresentation::kWord64);
case IrOpcode::kWord64Equal:
return VisitBinop(node, UseInfo::TruncatingWord64(),
- NodeOutputInfo::Bool());
+ MachineRepresentation::kBit);
case IrOpcode::kChangeInt32ToInt64:
- return VisitUnop(
- node, UseInfo::TruncatingWord32(),
- NodeOutputInfo(MachineRepresentation::kWord64, Type::Signed32()));
+ return VisitUnop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kWord64);
case IrOpcode::kChangeUint32ToUint64:
- return VisitUnop(
- node, UseInfo::TruncatingWord32(),
- NodeOutputInfo(MachineRepresentation::kWord64, Type::Unsigned32()));
+ return VisitUnop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kWord64);
case IrOpcode::kTruncateFloat64ToFloat32:
- return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float32());
+ return VisitUnop(node, UseInfo::Float64(),
+ MachineRepresentation::kFloat32);
case IrOpcode::kTruncateFloat64ToInt32:
- return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
- case IrOpcode::kTruncateInt64ToInt32:
- // TODO(titzer): Is kTypeInt32 correct here?
- return VisitUnop(node, UseInfo::Word64TruncatingToWord32(),
- NodeOutputInfo::Int32());
+ return VisitUnop(node, UseInfo::Float64(),
+ MachineRepresentation::kWord32);
case IrOpcode::kChangeFloat32ToFloat64:
- return VisitUnop(node, UseInfo::Float32(), NodeOutputInfo::Float64());
+ return VisitUnop(node, UseInfo::Float32(),
+ MachineRepresentation::kFloat64);
case IrOpcode::kChangeInt32ToFloat64:
- return VisitUnop(
- node, UseInfo::TruncatingWord32(),
- NodeOutputInfo(MachineRepresentation::kFloat64, Type::Signed32()));
+ return VisitUnop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kFloat64);
case IrOpcode::kChangeUint32ToFloat64:
return VisitUnop(node, UseInfo::TruncatingWord32(),
- NodeOutputInfo(MachineRepresentation::kFloat64,
- Type::Unsigned32()));
- case IrOpcode::kChangeFloat64ToInt32:
- return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
- NodeOutputInfo::Int32());
- case IrOpcode::kChangeFloat64ToUint32:
- return VisitUnop(node, UseInfo::Float64TruncatingToWord32(),
- NodeOutputInfo::Uint32());
-
+ MachineRepresentation::kFloat64);
case IrOpcode::kFloat64Add:
case IrOpcode::kFloat64Sub:
case IrOpcode::kFloat64Mul:
@@ -1404,29 +1351,40 @@
case IrOpcode::kFloat64RoundTruncate:
case IrOpcode::kFloat64RoundTiesAway:
case IrOpcode::kFloat64RoundUp:
- return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Float64());
+ return VisitUnop(node, UseInfo::Float64(),
+ MachineRepresentation::kFloat64);
case IrOpcode::kFloat64Equal:
case IrOpcode::kFloat64LessThan:
case IrOpcode::kFloat64LessThanOrEqual:
return VisitFloat64Cmp(node);
case IrOpcode::kFloat64ExtractLowWord32:
case IrOpcode::kFloat64ExtractHighWord32:
- return VisitUnop(node, UseInfo::Float64(), NodeOutputInfo::Int32());
+ return VisitUnop(node, UseInfo::Float64(),
+ MachineRepresentation::kWord32);
case IrOpcode::kFloat64InsertLowWord32:
case IrOpcode::kFloat64InsertHighWord32:
return VisitBinop(node, UseInfo::Float64(), UseInfo::TruncatingWord32(),
- NodeOutputInfo::Float64());
+ MachineRepresentation::kFloat64);
case IrOpcode::kLoadStackPointer:
case IrOpcode::kLoadFramePointer:
case IrOpcode::kLoadParentFramePointer:
- return VisitLeaf(node, NodeOutputInfo::Pointer());
+ return VisitLeaf(node, MachineType::PointerRepresentation());
case IrOpcode::kStateValues:
VisitStateValues(node);
break;
+
+ // The following opcodes are not produced before representation
+ // inference runs, so we do not have any real test coverage.
+ // Simply fail here.
+ case IrOpcode::kChangeFloat64ToInt32:
+ case IrOpcode::kChangeFloat64ToUint32:
+ case IrOpcode::kTruncateInt64ToInt32:
+ FATAL("Representation inference: unsupported opcodes.");
+
default:
VisitInputs(node);
// Assume the output is tagged.
- SetOutput(node, NodeOutputInfo::AnyTagged());
+ SetOutput(node, MachineRepresentation::kTagged);
break;
}
}
@@ -1437,7 +1395,7 @@
replacement->op()->mnemonic());
if (replacement->id() < count_ &&
- GetInfo(node)->output_type()->Is(GetInfo(replacement)->output_type())) {
+ GetUpperBound(node)->Is(GetUpperBound(replacement))) {
// Replace with a previously existing node eagerly only if the type is the
// same.
node->ReplaceUses(replacement);
@@ -1455,9 +1413,7 @@
void PrintOutputInfo(NodeInfo* info) {
if (FLAG_trace_representation) {
OFStream os(stdout);
- os << info->representation() << " (";
- info->output_type()->PrintTo(os, Type::SEMANTIC_DIM);
- os << ")";
+ os << info->representation();
}
}
@@ -1595,21 +1551,392 @@
NodeProperties::ChangeOp(node, machine()->CheckedStore(rep));
}
+Node* SimplifiedLowering::Float64Ceil(Node* const node) {
+ Node* const one = jsgraph()->Float64Constant(1.0);
+ Node* const zero = jsgraph()->Float64Constant(0.0);
+ Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
+ Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
+ Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
+ Node* const input = node->InputAt(0);
-Node* SimplifiedLowering::StringComparison(Node* node) {
- Operator::Properties properties = node->op()->properties();
- Callable callable = CodeFactory::StringCompare(isolate());
- CallDescriptor::Flags flags = CallDescriptor::kNoFlags;
- CallDescriptor* desc = Linkage::GetStubCallDescriptor(
- isolate(), zone(), callable.descriptor(), 0, flags, properties);
- return graph()->NewNode(
- common()->Call(desc), jsgraph()->HeapConstant(callable.code()),
- NodeProperties::GetValueInput(node, 0),
- NodeProperties::GetValueInput(node, 1), jsgraph()->NoContextConstant(),
- NodeProperties::GetEffectInput(node),
- NodeProperties::GetControlInput(node));
+ // Use fast hardware instruction if available.
+ if (machine()->Float64RoundUp().IsSupported()) {
+ return graph()->NewNode(machine()->Float64RoundUp().op(), input);
+ }
+
+ // General case for ceil.
+ //
+ // if 0.0 < input then
+ // if 2^52 <= input then
+ // input
+ // else
+ // let temp1 = (2^52 + input) - 2^52 in
+ // if temp1 < input then
+ // temp1 + 1
+ // else
+ // temp1
+ // else
+ // if input == 0 then
+ // input
+ // else
+ // if input <= -2^52 then
+ // input
+ // else
+ // let temp1 = -0 - input in
+ // let temp2 = (2^52 + temp1) - 2^52 in
+ // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
+ // -0 - temp3
+ //
+ // Note: We do not use the Diamond helper class here, because it really hurts
+ // readability with nested diamonds.
+
+ Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
+ Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
+ graph()->start());
+
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+ Node* vtrue0;
+ {
+ Node* check1 =
+ graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
+ Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* vtrue1 = input;
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* vfalse1;
+ {
+ Node* temp1 = graph()->NewNode(
+ machine()->Float64Sub(),
+ graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
+ vfalse1 = graph()->NewNode(
+ common()->Select(MachineRepresentation::kFloat64),
+ graph()->NewNode(machine()->Float64LessThan(), temp1, input),
+ graph()->NewNode(machine()->Float64Add(), temp1, one), temp1);
+ }
+
+ if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue1, vfalse1, if_true0);
+ }
+
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+ Node* vfalse0;
+ {
+ Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
+ Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+ check1, if_false0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* vtrue1 = input;
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* vfalse1;
+ {
+ Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
+ input, minus_two_52);
+ Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+ check2, if_false1);
+
+ Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+ Node* vtrue2 = input;
+
+ Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+ Node* vfalse2;
+ {
+ Node* temp1 =
+ graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
+ Node* temp2 = graph()->NewNode(
+ machine()->Float64Sub(),
+ graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
+ Node* temp3 = graph()->NewNode(
+ common()->Select(MachineRepresentation::kFloat64),
+ graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
+ graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
+ vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
+ }
+
+ if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
+ vfalse1 =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue2, vfalse2, if_false1);
+ }
+
+ if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ vfalse0 =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue1, vfalse1, if_false0);
+ }
+
+ Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+ return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue0, vfalse0, merge0);
}
+Node* SimplifiedLowering::Float64Floor(Node* const node) {
+ Node* const one = jsgraph()->Float64Constant(1.0);
+ Node* const zero = jsgraph()->Float64Constant(0.0);
+ Node* const minus_one = jsgraph()->Float64Constant(-1.0);
+ Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
+ Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
+ Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
+ Node* const input = node->InputAt(0);
+
+ // Use fast hardware instruction if available.
+ if (machine()->Float64RoundDown().IsSupported()) {
+ return graph()->NewNode(machine()->Float64RoundDown().op(), input);
+ }
+
+ // General case for floor.
+ //
+ // if 0.0 < input then
+ // if 2^52 <= input then
+ // input
+ // else
+ // let temp1 = (2^52 + input) - 2^52 in
+ // if input < temp1 then
+ // temp1 - 1
+ // else
+ // temp1
+ // else
+ // if input == 0 then
+ // input
+ // else
+ // if input <= -2^52 then
+ // input
+ // else
+ // let temp1 = -0 - input in
+ // let temp2 = (2^52 + temp1) - 2^52 in
+ // if temp2 < temp1 then
+ // -1 - temp2
+ // else
+ // -0 - temp2
+ //
+ // Note: We do not use the Diamond helper class here, because it really hurts
+ // readability with nested diamonds.
+
+ Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
+ Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
+ graph()->start());
+
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+ Node* vtrue0;
+ {
+ Node* check1 =
+ graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
+ Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* vtrue1 = input;
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* vfalse1;
+ {
+ Node* temp1 = graph()->NewNode(
+ machine()->Float64Sub(),
+ graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
+ vfalse1 = graph()->NewNode(
+ common()->Select(MachineRepresentation::kFloat64),
+ graph()->NewNode(machine()->Float64LessThan(), input, temp1),
+ graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
+ }
+
+ if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue1, vfalse1, if_true0);
+ }
+
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+ Node* vfalse0;
+ {
+ Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
+ Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+ check1, if_false0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* vtrue1 = input;
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* vfalse1;
+ {
+ Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
+ input, minus_two_52);
+ Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+ check2, if_false1);
+
+ Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+ Node* vtrue2 = input;
+
+ Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+ Node* vfalse2;
+ {
+ Node* temp1 =
+ graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
+ Node* temp2 = graph()->NewNode(
+ machine()->Float64Sub(),
+ graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
+ vfalse2 = graph()->NewNode(
+ common()->Select(MachineRepresentation::kFloat64),
+ graph()->NewNode(machine()->Float64LessThan(), temp2, temp1),
+ graph()->NewNode(machine()->Float64Sub(), minus_one, temp2),
+ graph()->NewNode(machine()->Float64Sub(), minus_zero, temp2));
+ }
+
+ if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
+ vfalse1 =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue2, vfalse2, if_false1);
+ }
+
+ if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ vfalse0 =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue1, vfalse1, if_false0);
+ }
+
+ Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+ return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue0, vfalse0, merge0);
+}
+
+Node* SimplifiedLowering::Float64Round(Node* const node) {
+ Node* const one = jsgraph()->Float64Constant(1.0);
+ Node* const one_half = jsgraph()->Float64Constant(0.5);
+ Node* const input = node->InputAt(0);
+
+ // Round up towards Infinity, and adjust if the difference exceeds 0.5.
+ Node* result = Float64Ceil(node);
+ return graph()->NewNode(
+ common()->Select(MachineRepresentation::kFloat64),
+ graph()->NewNode(
+ machine()->Float64LessThanOrEqual(),
+ graph()->NewNode(machine()->Float64Sub(), result, one_half), input),
+ result, graph()->NewNode(machine()->Float64Sub(), result, one));
+}
+
+Node* SimplifiedLowering::Float64Trunc(Node* const node) {
+ Node* const one = jsgraph()->Float64Constant(1.0);
+ Node* const zero = jsgraph()->Float64Constant(0.0);
+ Node* const minus_zero = jsgraph()->Float64Constant(-0.0);
+ Node* const two_52 = jsgraph()->Float64Constant(4503599627370496.0E0);
+ Node* const minus_two_52 = jsgraph()->Float64Constant(-4503599627370496.0E0);
+ Node* const input = node->InputAt(0);
+
+ // Use fast hardware instruction if available.
+ if (machine()->Float64RoundTruncate().IsSupported()) {
+ return graph()->NewNode(machine()->Float64RoundTruncate().op(), input);
+ }
+
+ // General case for trunc.
+ //
+ // if 0.0 < input then
+ // if 2^52 <= input then
+ // input
+ // else
+ // let temp1 = (2^52 + input) - 2^52 in
+ // if input < temp1 then
+ // temp1 - 1
+ // else
+ // temp1
+ // else
+ // if input == 0 then
+ // input
+ // else
+ // if input <= -2^52 then
+ // input
+ // else
+ // let temp1 = -0 - input in
+ // let temp2 = (2^52 + temp1) - 2^52 in
+ // let temp3 = (if temp1 < temp2 then temp2 - 1 else temp2) in
+ // -0 - temp3
+ //
+ // Note: We do not use the Diamond helper class here, because it really hurts
+ // readability with nested diamonds.
+
+ Node* check0 = graph()->NewNode(machine()->Float64LessThan(), zero, input);
+ Node* branch0 = graph()->NewNode(common()->Branch(BranchHint::kTrue), check0,
+ graph()->start());
+
+ Node* if_true0 = graph()->NewNode(common()->IfTrue(), branch0);
+ Node* vtrue0;
+ {
+ Node* check1 =
+ graph()->NewNode(machine()->Float64LessThanOrEqual(), two_52, input);
+ Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_true0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* vtrue1 = input;
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* vfalse1;
+ {
+ Node* temp1 = graph()->NewNode(
+ machine()->Float64Sub(),
+ graph()->NewNode(machine()->Float64Add(), two_52, input), two_52);
+ vfalse1 = graph()->NewNode(
+ common()->Select(MachineRepresentation::kFloat64),
+ graph()->NewNode(machine()->Float64LessThan(), input, temp1),
+ graph()->NewNode(machine()->Float64Sub(), temp1, one), temp1);
+ }
+
+ if_true0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ vtrue0 = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue1, vfalse1, if_true0);
+ }
+
+ Node* if_false0 = graph()->NewNode(common()->IfFalse(), branch0);
+ Node* vfalse0;
+ {
+ Node* check1 = graph()->NewNode(machine()->Float64Equal(), input, zero);
+ Node* branch1 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+ check1, if_false0);
+
+ Node* if_true1 = graph()->NewNode(common()->IfTrue(), branch1);
+ Node* vtrue1 = input;
+
+ Node* if_false1 = graph()->NewNode(common()->IfFalse(), branch1);
+ Node* vfalse1;
+ {
+ Node* check2 = graph()->NewNode(machine()->Float64LessThanOrEqual(),
+ input, minus_two_52);
+ Node* branch2 = graph()->NewNode(common()->Branch(BranchHint::kFalse),
+ check2, if_false1);
+
+ Node* if_true2 = graph()->NewNode(common()->IfTrue(), branch2);
+ Node* vtrue2 = input;
+
+ Node* if_false2 = graph()->NewNode(common()->IfFalse(), branch2);
+ Node* vfalse2;
+ {
+ Node* temp1 =
+ graph()->NewNode(machine()->Float64Sub(), minus_zero, input);
+ Node* temp2 = graph()->NewNode(
+ machine()->Float64Sub(),
+ graph()->NewNode(machine()->Float64Add(), two_52, temp1), two_52);
+ Node* temp3 = graph()->NewNode(
+ common()->Select(MachineRepresentation::kFloat64),
+ graph()->NewNode(machine()->Float64LessThan(), temp1, temp2),
+ graph()->NewNode(machine()->Float64Sub(), temp2, one), temp2);
+ vfalse2 = graph()->NewNode(machine()->Float64Sub(), minus_zero, temp3);
+ }
+
+ if_false1 = graph()->NewNode(common()->Merge(2), if_true2, if_false2);
+ vfalse1 =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue2, vfalse2, if_false1);
+ }
+
+ if_false0 = graph()->NewNode(common()->Merge(2), if_true1, if_false1);
+ vfalse0 =
+ graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue1, vfalse1, if_false0);
+ }
+
+ Node* merge0 = graph()->NewNode(common()->Merge(2), if_true0, if_false0);
+ return graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
+ vtrue0, vfalse0, merge0);
+}
Node* SimplifiedLowering::Int32Div(Node* const node) {
Int32BinopMatcher m(node);
@@ -1873,53 +2200,6 @@
NodeProperties::ChangeOp(node, op);
}
-
-namespace {
-
-void ReplaceEffectUses(Node* node, Node* replacement) {
- // Requires distinguishing between value and effect edges.
- DCHECK(replacement->op()->EffectOutputCount() > 0);
- for (Edge edge : node->use_edges()) {
- if (NodeProperties::IsEffectEdge(edge)) {
- edge.UpdateTo(replacement);
- } else {
- DCHECK(NodeProperties::IsValueEdge(edge));
- }
- }
-}
-
-} // namespace
-
-
-void SimplifiedLowering::DoStringEqual(Node* node) {
- Node* comparison = StringComparison(node);
- ReplaceEffectUses(node, comparison);
- node->ReplaceInput(0, comparison);
- node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
- node->TrimInputCount(2);
- NodeProperties::ChangeOp(node, machine()->WordEqual());
-}
-
-
-void SimplifiedLowering::DoStringLessThan(Node* node) {
- Node* comparison = StringComparison(node);
- ReplaceEffectUses(node, comparison);
- node->ReplaceInput(0, comparison);
- node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
- node->TrimInputCount(2);
- NodeProperties::ChangeOp(node, machine()->IntLessThan());
-}
-
-
-void SimplifiedLowering::DoStringLessThanOrEqual(Node* node) {
- Node* comparison = StringComparison(node);
- ReplaceEffectUses(node, comparison);
- node->ReplaceInput(0, comparison);
- node->ReplaceInput(1, jsgraph()->SmiConstant(EQUAL));
- node->TrimInputCount(2);
- NodeProperties::ChangeOp(node, machine()->IntLessThanOrEqual());
-}
-
} // namespace compiler
} // namespace internal
} // namespace v8