| Index: src/compiler/arm64/instruction-selector-arm64.cc | 
| diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc | 
| index 427486b25a865941a8032590da1aa709892a788d..7979c141516d0827518e02e0fa64de852c86c94f 100644 | 
| --- a/src/compiler/arm64/instruction-selector-arm64.cc | 
| +++ b/src/compiler/arm64/instruction-selector-arm64.cc | 
| @@ -87,25 +87,16 @@ class Arm64OperandGenerator FINAL : public OperandGenerator { | 
| }; | 
|  | 
|  | 
| -static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 
| -                           Node* node) { | 
| -  Arm64OperandGenerator g(selector); | 
| -  selector->Emit(opcode, g.DefineAsRegister(node), | 
| -                 g.UseRegister(node->InputAt(0))); | 
| -} | 
| - | 
| +namespace { | 
|  | 
| -static void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, | 
| -                     Node* node) { | 
| +void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { | 
| Arm64OperandGenerator g(selector); | 
| selector->Emit(opcode, g.DefineAsRegister(node), | 
| -                 g.UseRegister(node->InputAt(0)), | 
| -                 g.UseRegister(node->InputAt(1))); | 
| +                 g.UseRegister(node->InputAt(0))); | 
| } | 
|  | 
|  | 
| -static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 
| -                            Node* node) { | 
| +void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) { | 
| Arm64OperandGenerator g(selector); | 
| selector->Emit(opcode, g.DefineAsRegister(node), | 
| g.UseRegister(node->InputAt(0)), | 
| @@ -113,8 +104,8 @@ static void VisitRRRFloat64(InstructionSelector* selector, ArchOpcode opcode, | 
| } | 
|  | 
|  | 
| -static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, | 
| -                     Node* node, ImmediateMode operand_mode) { | 
| +void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, Node* node, | 
| +              ImmediateMode operand_mode) { | 
| Arm64OperandGenerator g(selector); | 
| selector->Emit(opcode, g.DefineAsRegister(node), | 
| g.UseRegister(node->InputAt(0)), | 
| @@ -123,10 +114,9 @@ static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, | 
|  | 
|  | 
| template <typename Matcher> | 
| -static bool TryMatchShift(InstructionSelector* selector, Node* node, | 
| -                          InstructionCode* opcode, IrOpcode::Value shift_opcode, | 
| -                          ImmediateMode imm_mode, | 
| -                          AddressingMode addressing_mode) { | 
| +bool TryMatchShift(InstructionSelector* selector, Node* node, | 
| +                   InstructionCode* opcode, IrOpcode::Value shift_opcode, | 
| +                   ImmediateMode imm_mode, AddressingMode addressing_mode) { | 
| if (node->opcode() != shift_opcode) return false; | 
| Arm64OperandGenerator g(selector); | 
| Matcher m(node); | 
| @@ -138,8 +128,8 @@ static bool TryMatchShift(InstructionSelector* selector, Node* node, | 
| } | 
|  | 
|  | 
| -static bool TryMatchAnyShift(InstructionSelector* selector, Node* node, | 
| -                             InstructionCode* opcode, bool try_ror) { | 
| +bool TryMatchAnyShift(InstructionSelector* selector, Node* node, | 
| +                      InstructionCode* opcode, bool try_ror) { | 
| return TryMatchShift<Int32BinopMatcher>(selector, node, opcode, | 
| IrOpcode::kWord32Shl, kShift32Imm, | 
| kMode_Operand2_R_LSL_I) || | 
| @@ -167,8 +157,8 @@ static bool TryMatchAnyShift(InstructionSelector* selector, Node* node, | 
| } | 
|  | 
|  | 
| -static bool TryMatchAnyExtend(InstructionSelector* selector, Node* node, | 
| -                              InstructionCode* opcode) { | 
| +bool TryMatchAnyExtend(InstructionSelector* selector, Node* node, | 
| +                       InstructionCode* opcode) { | 
| NodeMatcher nm(node); | 
| if (nm.IsWord32And()) { | 
| Int32BinopMatcher m(node); | 
| @@ -188,9 +178,9 @@ static bool TryMatchAnyExtend(InstructionSelector* selector, Node* node, | 
|  | 
| // Shared routine for multiple binary operations. | 
| template <typename Matcher> | 
| -static void VisitBinop(InstructionSelector* selector, Node* node, | 
| -                       InstructionCode opcode, ImmediateMode operand_mode, | 
| -                       FlagsContinuation* cont) { | 
| +void VisitBinop(InstructionSelector* selector, Node* node, | 
| +                InstructionCode opcode, ImmediateMode operand_mode, | 
| +                FlagsContinuation* cont) { | 
| Arm64OperandGenerator g(selector); | 
| Matcher m(node); | 
| InstructionOperand inputs[4]; | 
| @@ -256,16 +246,16 @@ static void VisitBinop(InstructionSelector* selector, Node* node, | 
|  | 
| // Shared routine for multiple binary operations. | 
| template <typename Matcher> | 
| -static void VisitBinop(InstructionSelector* selector, Node* node, | 
| -                       ArchOpcode opcode, ImmediateMode operand_mode) { | 
| +void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, | 
| +                ImmediateMode operand_mode) { | 
| FlagsContinuation cont; | 
| VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); | 
| } | 
|  | 
|  | 
| template <typename Matcher> | 
| -static void VisitAddSub(InstructionSelector* selector, Node* node, | 
| -                        ArchOpcode opcode, ArchOpcode negate_opcode) { | 
| +void VisitAddSub(InstructionSelector* selector, Node* node, ArchOpcode opcode, | 
| +                 ArchOpcode negate_opcode) { | 
| Arm64OperandGenerator g(selector); | 
| Matcher m(node); | 
| if (m.right().HasValue() && (m.right().Value() < 0) && | 
| @@ -278,6 +268,8 @@ static void VisitAddSub(InstructionSelector* selector, Node* node, | 
| } | 
| } | 
|  | 
| +}  // namespace | 
| + | 
|  | 
| void InstructionSelector::VisitLoad(Node* node) { | 
| MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 
| @@ -956,43 +948,32 @@ void InstructionSelector::VisitUint64Mod(Node* node) { | 
|  | 
|  | 
| void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) { | 
| -  Arm64OperandGenerator g(this); | 
| -  Emit(kArm64Float32ToFloat64, g.DefineAsRegister(node), | 
| -       g.UseRegister(node->InputAt(0))); | 
| +  VisitRR(this, kArm64Float32ToFloat64, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) { | 
| -  Arm64OperandGenerator g(this); | 
| -  Emit(kArm64Int32ToFloat64, g.DefineAsRegister(node), | 
| -       g.UseRegister(node->InputAt(0))); | 
| +  VisitRR(this, kArm64Int32ToFloat64, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) { | 
| -  Arm64OperandGenerator g(this); | 
| -  Emit(kArm64Uint32ToFloat64, g.DefineAsRegister(node), | 
| -       g.UseRegister(node->InputAt(0))); | 
| +  VisitRR(this, kArm64Uint32ToFloat64, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) { | 
| -  Arm64OperandGenerator g(this); | 
| -  Emit(kArm64Float64ToInt32, g.DefineAsRegister(node), | 
| -       g.UseRegister(node->InputAt(0))); | 
| +  VisitRR(this, kArm64Float64ToInt32, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) { | 
| -  Arm64OperandGenerator g(this); | 
| -  Emit(kArm64Float64ToUint32, g.DefineAsRegister(node), | 
| -       g.UseRegister(node->InputAt(0))); | 
| +  VisitRR(this, kArm64Float64ToUint32, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitChangeInt32ToInt64(Node* node) { | 
| -  Arm64OperandGenerator g(this); | 
| -  Emit(kArm64Sxtw, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); | 
| +  VisitRR(this, kArm64Sxtw, node); | 
| } | 
|  | 
|  | 
| @@ -1061,8 +1042,18 @@ void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) { | 
| } | 
|  | 
|  | 
| +void InstructionSelector::VisitFloat32Add(Node* node) { | 
| +  VisitRRR(this, kArm64Float32Add, node); | 
| +} | 
| + | 
| + | 
| void InstructionSelector::VisitFloat64Add(Node* node) { | 
| -  VisitRRRFloat64(this, kArm64Float64Add, node); | 
| +  VisitRRR(this, kArm64Float64Add, node); | 
| +} | 
| + | 
| + | 
| +void InstructionSelector::VisitFloat32Sub(Node* node) { | 
| +  VisitRRR(this, kArm64Float32Sub, node); | 
| } | 
|  | 
|  | 
| @@ -1081,17 +1072,27 @@ void InstructionSelector::VisitFloat64Sub(Node* node) { | 
| } | 
| } | 
| } | 
| -  VisitRRRFloat64(this, kArm64Float64Sub, node); | 
| +  VisitRRR(this, kArm64Float64Sub, node); | 
| +} | 
| + | 
| + | 
| +void InstructionSelector::VisitFloat32Mul(Node* node) { | 
| +  VisitRRR(this, kArm64Float32Mul, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitFloat64Mul(Node* node) { | 
| -  VisitRRRFloat64(this, kArm64Float64Mul, node); | 
| +  VisitRRR(this, kArm64Float64Mul, node); | 
| +} | 
| + | 
| + | 
| +void InstructionSelector::VisitFloat32Div(Node* node) { | 
| +  VisitRRR(this, kArm64Float32Div, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitFloat64Div(Node* node) { | 
| -  VisitRRRFloat64(this, kArm64Float64Div, node); | 
| +  VisitRRR(this, kArm64Float64Div, node); | 
| } | 
|  | 
|  | 
| @@ -1103,41 +1104,48 @@ void InstructionSelector::VisitFloat64Mod(Node* node) { | 
| } | 
|  | 
|  | 
| +void InstructionSelector::VisitFloat32Max(Node* node) { | 
| +  VisitRRR(this, kArm64Float32Max, node); | 
| +} | 
| + | 
| + | 
| void InstructionSelector::VisitFloat64Max(Node* node) { | 
| -  Arm64OperandGenerator g(this); | 
| -  Node* left = node->InputAt(0); | 
| -  Node* right = node->InputAt(1); | 
| -  Emit(kArm64Float64Max, g.DefineAsRegister(node), g.UseRegister(left), | 
| -       g.UseRegister(right)); | 
| +  VisitRRR(this, kArm64Float64Max, node); | 
| +} | 
| + | 
| + | 
| +void InstructionSelector::VisitFloat32Min(Node* node) { | 
| +  VisitRRR(this, kArm64Float32Min, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitFloat64Min(Node* node) { | 
| -  Arm64OperandGenerator g(this); | 
| -  Node* left = node->InputAt(0); | 
| -  Node* right = node->InputAt(1); | 
| -  Emit(kArm64Float64Min, g.DefineAsRegister(node), g.UseRegister(left), | 
| -       g.UseRegister(right)); | 
| +  VisitRRR(this, kArm64Float64Min, node); | 
| +} | 
| + | 
| + | 
| +void InstructionSelector::VisitFloat32Sqrt(Node* node) { | 
| +  VisitRR(this, kArm64Float32Sqrt, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitFloat64Sqrt(Node* node) { | 
| -  VisitRRFloat64(this, kArm64Float64Sqrt, node); | 
| +  VisitRR(this, kArm64Float64Sqrt, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitFloat64RoundDown(Node* node) { | 
| -  VisitRRFloat64(this, kArm64Float64RoundDown, node); | 
| +  VisitRR(this, kArm64Float64RoundDown, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { | 
| -  VisitRRFloat64(this, kArm64Float64RoundTruncate, node); | 
| +  VisitRR(this, kArm64Float64RoundTruncate, node); | 
| } | 
|  | 
|  | 
| void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { | 
| -  VisitRRFloat64(this, kArm64Float64RoundTiesAway, node); | 
| +  VisitRR(this, kArm64Float64RoundTiesAway, node); | 
| } | 
|  | 
|  | 
| @@ -1222,10 +1230,12 @@ void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { | 
| } | 
|  | 
|  | 
| +namespace { | 
| + | 
| // Shared routine for multiple compare operations. | 
| -static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 
| -                         InstructionOperand left, InstructionOperand right, | 
| -                         FlagsContinuation* cont) { | 
| +void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 
| +                  InstructionOperand left, InstructionOperand right, | 
| +                  FlagsContinuation* cont) { | 
| Arm64OperandGenerator g(selector); | 
| opcode = cont->Encode(opcode); | 
| if (cont->IsBranch()) { | 
| @@ -1239,9 +1249,9 @@ static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 
|  | 
|  | 
| // Shared routine for multiple word compare operations. | 
| -static void VisitWordCompare(InstructionSelector* selector, Node* node, | 
| -                             InstructionCode opcode, FlagsContinuation* cont, | 
| -                             bool commutative, ImmediateMode immediate_mode) { | 
| +void VisitWordCompare(InstructionSelector* selector, Node* node, | 
| +                      InstructionCode opcode, FlagsContinuation* cont, | 
| +                      bool commutative, ImmediateMode immediate_mode) { | 
| Arm64OperandGenerator g(selector); | 
| Node* left = node->InputAt(0); | 
| Node* right = node->InputAt(1); | 
| @@ -1261,35 +1271,50 @@ static void VisitWordCompare(InstructionSelector* selector, Node* node, | 
| } | 
|  | 
|  | 
| -static void VisitWord32Compare(InstructionSelector* selector, Node* node, | 
| -                               FlagsContinuation* cont) { | 
| +void VisitWord32Compare(InstructionSelector* selector, Node* node, | 
| +                        FlagsContinuation* cont) { | 
| VisitWordCompare(selector, node, kArm64Cmp32, cont, false, kArithmeticImm); | 
| } | 
|  | 
|  | 
| -static void VisitWordTest(InstructionSelector* selector, Node* node, | 
| -                          InstructionCode opcode, FlagsContinuation* cont) { | 
| +void VisitWordTest(InstructionSelector* selector, Node* node, | 
| +                   InstructionCode opcode, FlagsContinuation* cont) { | 
| Arm64OperandGenerator g(selector); | 
| VisitCompare(selector, opcode, g.UseRegister(node), g.UseRegister(node), | 
| cont); | 
| } | 
|  | 
|  | 
| -static void VisitWord32Test(InstructionSelector* selector, Node* node, | 
| -                            FlagsContinuation* cont) { | 
| +void VisitWord32Test(InstructionSelector* selector, Node* node, | 
| +                     FlagsContinuation* cont) { | 
| VisitWordTest(selector, node, kArm64Tst32, cont); | 
| } | 
|  | 
|  | 
| -static void VisitWord64Test(InstructionSelector* selector, Node* node, | 
| -                            FlagsContinuation* cont) { | 
| +void VisitWord64Test(InstructionSelector* selector, Node* node, | 
| +                     FlagsContinuation* cont) { | 
| VisitWordTest(selector, node, kArm64Tst, cont); | 
| } | 
|  | 
|  | 
| -// Shared routine for multiple float compare operations. | 
| -static void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 
| -                                FlagsContinuation* cont) { | 
| +// Shared routine for multiple float64 compare operations. | 
| +void VisitFloat32Compare(InstructionSelector* selector, Node* node, | 
| +                         FlagsContinuation* cont) { | 
| +  Arm64OperandGenerator g(selector); | 
| +  Float32BinopMatcher m(node); | 
| +  if (m.right().Is(0.0f)) { | 
| +    VisitCompare(selector, kArm64Float32Cmp, g.UseRegister(m.left().node()), | 
| +                 g.UseImmediate(m.right().node()), cont); | 
| +  } else { | 
| +    VisitCompare(selector, kArm64Float32Cmp, g.UseRegister(m.left().node()), | 
| +                 g.UseRegister(m.right().node()), cont); | 
| +  } | 
| +} | 
| + | 
| + | 
| +// Shared routine for multiple float64 compare operations. | 
| +void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 
| +                         FlagsContinuation* cont) { | 
| Arm64OperandGenerator g(selector); | 
| Float64BinopMatcher m(node); | 
| if (m.right().Is(0.0)) { | 
| @@ -1301,6 +1326,8 @@ static void VisitFloat64Compare(InstructionSelector* selector, Node* node, | 
| } | 
| } | 
|  | 
| +}  // namespace | 
| + | 
|  | 
| void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 
| BasicBlock* fbranch) { | 
| @@ -1356,6 +1383,15 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 
| cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 
| return VisitWordCompare(this, value, kArm64Cmp, &cont, false, | 
| kArithmeticImm); | 
| +      case IrOpcode::kFloat32Equal: | 
| +        cont.OverwriteAndNegateIfEqual(kEqual); | 
| +        return VisitFloat32Compare(this, value, &cont); | 
| +      case IrOpcode::kFloat32LessThan: | 
| +        cont.OverwriteAndNegateIfEqual(kUnsignedLessThan); | 
| +        return VisitFloat32Compare(this, value, &cont); | 
| +      case IrOpcode::kFloat32LessThanOrEqual: | 
| +        cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual); | 
| +        return VisitFloat32Compare(this, value, &cont); | 
| case IrOpcode::kFloat64Equal: | 
| cont.OverwriteAndNegateIfEqual(kEqual); | 
| return VisitFloat64Compare(this, value, &cont); | 
| @@ -1584,6 +1620,24 @@ void InstructionSelector::VisitUint64LessThan(Node* node) { | 
| } | 
|  | 
|  | 
| +void InstructionSelector::VisitFloat32Equal(Node* node) { | 
| +  FlagsContinuation cont(kEqual, node); | 
| +  VisitFloat32Compare(this, node, &cont); | 
| +} | 
| + | 
| + | 
| +void InstructionSelector::VisitFloat32LessThan(Node* node) { | 
| +  FlagsContinuation cont(kUnsignedLessThan, node); | 
| +  VisitFloat32Compare(this, node, &cont); | 
| +} | 
| + | 
| + | 
| +void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) { | 
| +  FlagsContinuation cont(kUnsignedLessThanOrEqual, node); | 
| +  VisitFloat32Compare(this, node, &cont); | 
| +} | 
| + | 
| + | 
| void InstructionSelector::VisitFloat64Equal(Node* node) { | 
| FlagsContinuation cont(kEqual, node); | 
| VisitFloat64Compare(this, node, &cont); | 
| @@ -1654,11 +1708,13 @@ void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) { | 
| // static | 
| MachineOperatorBuilder::Flags | 
| InstructionSelector::SupportedMachineOperatorFlags() { | 
| -  return MachineOperatorBuilder::kFloat64RoundDown | | 
| -         MachineOperatorBuilder::kFloat64RoundTruncate | | 
| -         MachineOperatorBuilder::kFloat64RoundTiesAway | | 
| +  return MachineOperatorBuilder::kFloat32Max | | 
| +         MachineOperatorBuilder::kFloat32Min | | 
| MachineOperatorBuilder::kFloat64Max | | 
| MachineOperatorBuilder::kFloat64Min | | 
| +         MachineOperatorBuilder::kFloat64RoundDown | | 
| +         MachineOperatorBuilder::kFloat64RoundTruncate | | 
| +         MachineOperatorBuilder::kFloat64RoundTiesAway | | 
| MachineOperatorBuilder::kWord32ShiftIsSafe | | 
| MachineOperatorBuilder::kInt32DivIsSafe | | 
| MachineOperatorBuilder::kUint32DivIsSafe; | 
|  |