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