Home | History | Annotate | Download | only in arm
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/base/adapters.h"
      6 #include "src/base/bits.h"
      7 #include "src/compiler/instruction-selector-impl.h"
      8 #include "src/compiler/node-matchers.h"
      9 #include "src/compiler/node-properties.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace compiler {
     14 
     15 // Adds Arm-specific methods for generating InstructionOperands.
     16 class ArmOperandGenerator : public OperandGenerator {
     17  public:
     18   explicit ArmOperandGenerator(InstructionSelector* selector)
     19       : OperandGenerator(selector) {}
     20 
     21   bool CanBeImmediate(int32_t value) const {
     22     return Assembler::ImmediateFitsAddrMode1Instruction(value);
     23   }
     24 
     25   bool CanBeImmediate(uint32_t value) const {
     26     return CanBeImmediate(bit_cast<int32_t>(value));
     27   }
     28 
     29   bool CanBeImmediate(Node* node, InstructionCode opcode) {
     30     Int32Matcher m(node);
     31     if (!m.HasValue()) return false;
     32     int32_t value = m.Value();
     33     switch (ArchOpcodeField::decode(opcode)) {
     34       case kArmAnd:
     35       case kArmMov:
     36       case kArmMvn:
     37       case kArmBic:
     38         return CanBeImmediate(value) || CanBeImmediate(~value);
     39 
     40       case kArmAdd:
     41       case kArmSub:
     42       case kArmCmp:
     43       case kArmCmn:
     44         return CanBeImmediate(value) || CanBeImmediate(-value);
     45 
     46       case kArmTst:
     47       case kArmTeq:
     48       case kArmOrr:
     49       case kArmEor:
     50       case kArmRsb:
     51         return CanBeImmediate(value);
     52 
     53       case kArmVldrF32:
     54       case kArmVstrF32:
     55       case kArmVldrF64:
     56       case kArmVstrF64:
     57         return value >= -1020 && value <= 1020 && (value % 4) == 0;
     58 
     59       case kArmLdrb:
     60       case kArmLdrsb:
     61       case kArmStrb:
     62       case kArmLdr:
     63       case kArmStr:
     64         return value >= -4095 && value <= 4095;
     65 
     66       case kArmLdrh:
     67       case kArmLdrsh:
     68       case kArmStrh:
     69         return value >= -255 && value <= 255;
     70 
     71       default:
     72         break;
     73     }
     74     return false;
     75   }
     76 };
     77 
     78 
     79 namespace {
     80 
     81 void VisitRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
     82   ArmOperandGenerator g(selector);
     83   selector->Emit(opcode, g.DefineAsRegister(node),
     84                  g.UseRegister(node->InputAt(0)));
     85 }
     86 
     87 void VisitRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
     88   ArmOperandGenerator g(selector);
     89   selector->Emit(opcode, g.DefineAsRegister(node),
     90                  g.UseRegister(node->InputAt(0)),
     91                  g.UseRegister(node->InputAt(1)));
     92 }
     93 
     94 void VisitRRRR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
     95   ArmOperandGenerator g(selector);
     96   // Use DefineSameAsFirst for ternary ops that clobber their first input,
     97   // e.g. the NEON vbsl instruction.
     98   selector->Emit(
     99       opcode, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
    100       g.UseRegister(node->InputAt(1)), g.UseRegister(node->InputAt(2)));
    101 }
    102 
    103 void VisitRRI(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
    104   ArmOperandGenerator g(selector);
    105   int32_t imm = OpParameter<int32_t>(node);
    106   selector->Emit(opcode, g.DefineAsRegister(node),
    107                  g.UseRegister(node->InputAt(0)), g.UseImmediate(imm));
    108 }
    109 
    110 void VisitRRIR(InstructionSelector* selector, ArchOpcode opcode, Node* node) {
    111   ArmOperandGenerator g(selector);
    112   int32_t imm = OpParameter<int32_t>(node);
    113   selector->Emit(opcode, g.DefineAsRegister(node),
    114                  g.UseRegister(node->InputAt(0)), g.UseImmediate(imm),
    115                  g.UseRegister(node->InputAt(1)));
    116 }
    117 
    118 template <IrOpcode::Value kOpcode, int kImmMin, int kImmMax,
    119           AddressingMode kImmMode, AddressingMode kRegMode>
    120 bool TryMatchShift(InstructionSelector* selector,
    121                    InstructionCode* opcode_return, Node* node,
    122                    InstructionOperand* value_return,
    123                    InstructionOperand* shift_return) {
    124   ArmOperandGenerator g(selector);
    125   if (node->opcode() == kOpcode) {
    126     Int32BinopMatcher m(node);
    127     *value_return = g.UseRegister(m.left().node());
    128     if (m.right().IsInRange(kImmMin, kImmMax)) {
    129       *opcode_return |= AddressingModeField::encode(kImmMode);
    130       *shift_return = g.UseImmediate(m.right().node());
    131     } else {
    132       *opcode_return |= AddressingModeField::encode(kRegMode);
    133       *shift_return = g.UseRegister(m.right().node());
    134     }
    135     return true;
    136   }
    137   return false;
    138 }
    139 
    140 template <IrOpcode::Value kOpcode, int kImmMin, int kImmMax,
    141           AddressingMode kImmMode>
    142 bool TryMatchShiftImmediate(InstructionSelector* selector,
    143                             InstructionCode* opcode_return, Node* node,
    144                             InstructionOperand* value_return,
    145                             InstructionOperand* shift_return) {
    146   ArmOperandGenerator g(selector);
    147   if (node->opcode() == kOpcode) {
    148     Int32BinopMatcher m(node);
    149     if (m.right().IsInRange(kImmMin, kImmMax)) {
    150       *opcode_return |= AddressingModeField::encode(kImmMode);
    151       *value_return = g.UseRegister(m.left().node());
    152       *shift_return = g.UseImmediate(m.right().node());
    153       return true;
    154     }
    155   }
    156   return false;
    157 }
    158 
    159 bool TryMatchROR(InstructionSelector* selector, InstructionCode* opcode_return,
    160                  Node* node, InstructionOperand* value_return,
    161                  InstructionOperand* shift_return) {
    162   return TryMatchShift<IrOpcode::kWord32Ror, 1, 31, kMode_Operand2_R_ROR_I,
    163                        kMode_Operand2_R_ROR_R>(selector, opcode_return, node,
    164                                                value_return, shift_return);
    165 }
    166 
    167 
    168 bool TryMatchASR(InstructionSelector* selector, InstructionCode* opcode_return,
    169                  Node* node, InstructionOperand* value_return,
    170                  InstructionOperand* shift_return) {
    171   return TryMatchShift<IrOpcode::kWord32Sar, 1, 32, kMode_Operand2_R_ASR_I,
    172                        kMode_Operand2_R_ASR_R>(selector, opcode_return, node,
    173                                                value_return, shift_return);
    174 }
    175 
    176 
    177 bool TryMatchLSL(InstructionSelector* selector, InstructionCode* opcode_return,
    178                  Node* node, InstructionOperand* value_return,
    179                  InstructionOperand* shift_return) {
    180   return TryMatchShift<IrOpcode::kWord32Shl, 0, 31, kMode_Operand2_R_LSL_I,
    181                        kMode_Operand2_R_LSL_R>(selector, opcode_return, node,
    182                                                value_return, shift_return);
    183 }
    184 
    185 bool TryMatchLSLImmediate(InstructionSelector* selector,
    186                           InstructionCode* opcode_return, Node* node,
    187                           InstructionOperand* value_return,
    188                           InstructionOperand* shift_return) {
    189   return TryMatchShiftImmediate<IrOpcode::kWord32Shl, 0, 31,
    190                                 kMode_Operand2_R_LSL_I>(
    191       selector, opcode_return, node, value_return, shift_return);
    192 }
    193 
    194 bool TryMatchLSR(InstructionSelector* selector, InstructionCode* opcode_return,
    195                  Node* node, InstructionOperand* value_return,
    196                  InstructionOperand* shift_return) {
    197   return TryMatchShift<IrOpcode::kWord32Shr, 1, 32, kMode_Operand2_R_LSR_I,
    198                        kMode_Operand2_R_LSR_R>(selector, opcode_return, node,
    199                                                value_return, shift_return);
    200 }
    201 
    202 
    203 bool TryMatchShift(InstructionSelector* selector,
    204                    InstructionCode* opcode_return, Node* node,
    205                    InstructionOperand* value_return,
    206                    InstructionOperand* shift_return) {
    207   return (
    208       TryMatchASR(selector, opcode_return, node, value_return, shift_return) ||
    209       TryMatchLSL(selector, opcode_return, node, value_return, shift_return) ||
    210       TryMatchLSR(selector, opcode_return, node, value_return, shift_return) ||
    211       TryMatchROR(selector, opcode_return, node, value_return, shift_return));
    212 }
    213 
    214 
    215 bool TryMatchImmediateOrShift(InstructionSelector* selector,
    216                               InstructionCode* opcode_return, Node* node,
    217                               size_t* input_count_return,
    218                               InstructionOperand* inputs) {
    219   ArmOperandGenerator g(selector);
    220   if (g.CanBeImmediate(node, *opcode_return)) {
    221     *opcode_return |= AddressingModeField::encode(kMode_Operand2_I);
    222     inputs[0] = g.UseImmediate(node);
    223     *input_count_return = 1;
    224     return true;
    225   }
    226   if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) {
    227     *input_count_return = 2;
    228     return true;
    229   }
    230   return false;
    231 }
    232 
    233 
    234 void VisitBinop(InstructionSelector* selector, Node* node,
    235                 InstructionCode opcode, InstructionCode reverse_opcode,
    236                 FlagsContinuation* cont) {
    237   ArmOperandGenerator g(selector);
    238   Int32BinopMatcher m(node);
    239   InstructionOperand inputs[5];
    240   size_t input_count = 0;
    241   InstructionOperand outputs[2];
    242   size_t output_count = 0;
    243 
    244   if (m.left().node() == m.right().node()) {
    245     // If both inputs refer to the same operand, enforce allocating a register
    246     // for both of them to ensure that we don't end up generating code like
    247     // this:
    248     //
    249     //   mov r0, r1, asr #16
    250     //   adds r0, r0, r1, asr #16
    251     //   bvs label
    252     InstructionOperand const input = g.UseRegister(m.left().node());
    253     opcode |= AddressingModeField::encode(kMode_Operand2_R);
    254     inputs[input_count++] = input;
    255     inputs[input_count++] = input;
    256   } else if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
    257                                       &input_count, &inputs[1])) {
    258     inputs[0] = g.UseRegister(m.left().node());
    259     input_count++;
    260   } else if (TryMatchImmediateOrShift(selector, &reverse_opcode,
    261                                       m.left().node(), &input_count,
    262                                       &inputs[1])) {
    263     inputs[0] = g.UseRegister(m.right().node());
    264     opcode = reverse_opcode;
    265     input_count++;
    266   } else {
    267     opcode |= AddressingModeField::encode(kMode_Operand2_R);
    268     inputs[input_count++] = g.UseRegister(m.left().node());
    269     inputs[input_count++] = g.UseRegister(m.right().node());
    270   }
    271 
    272   if (cont->IsBranch()) {
    273     inputs[input_count++] = g.Label(cont->true_block());
    274     inputs[input_count++] = g.Label(cont->false_block());
    275   }
    276 
    277   outputs[output_count++] = g.DefineAsRegister(node);
    278   if (cont->IsSet()) {
    279     outputs[output_count++] = g.DefineAsRegister(cont->result());
    280   }
    281 
    282   DCHECK_NE(0u, input_count);
    283   DCHECK_NE(0u, output_count);
    284   DCHECK_GE(arraysize(inputs), input_count);
    285   DCHECK_GE(arraysize(outputs), output_count);
    286   DCHECK_NE(kMode_None, AddressingModeField::decode(opcode));
    287 
    288   opcode = cont->Encode(opcode);
    289   if (cont->IsDeoptimize()) {
    290     selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
    291                              cont->kind(), cont->reason(), cont->frame_state());
    292   } else if (cont->IsTrap()) {
    293     inputs[input_count++] = g.UseImmediate(cont->trap_id());
    294     selector->Emit(opcode, output_count, outputs, input_count, inputs);
    295   } else {
    296     selector->Emit(opcode, output_count, outputs, input_count, inputs);
    297   }
    298 }
    299 
    300 
    301 void VisitBinop(InstructionSelector* selector, Node* node,
    302                 InstructionCode opcode, InstructionCode reverse_opcode) {
    303   FlagsContinuation cont;
    304   VisitBinop(selector, node, opcode, reverse_opcode, &cont);
    305 }
    306 
    307 
    308 void EmitDiv(InstructionSelector* selector, ArchOpcode div_opcode,
    309              ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode,
    310              InstructionOperand result_operand, InstructionOperand left_operand,
    311              InstructionOperand right_operand) {
    312   ArmOperandGenerator g(selector);
    313   if (selector->IsSupported(SUDIV)) {
    314     selector->Emit(div_opcode, result_operand, left_operand, right_operand);
    315     return;
    316   }
    317   InstructionOperand left_double_operand = g.TempDoubleRegister();
    318   InstructionOperand right_double_operand = g.TempDoubleRegister();
    319   InstructionOperand result_double_operand = g.TempDoubleRegister();
    320   selector->Emit(f64i32_opcode, left_double_operand, left_operand);
    321   selector->Emit(f64i32_opcode, right_double_operand, right_operand);
    322   selector->Emit(kArmVdivF64, result_double_operand, left_double_operand,
    323                  right_double_operand);
    324   selector->Emit(i32f64_opcode, result_operand, result_double_operand);
    325 }
    326 
    327 
    328 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode div_opcode,
    329               ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode) {
    330   ArmOperandGenerator g(selector);
    331   Int32BinopMatcher m(node);
    332   EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode,
    333           g.DefineAsRegister(node), g.UseRegister(m.left().node()),
    334           g.UseRegister(m.right().node()));
    335 }
    336 
    337 
    338 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode div_opcode,
    339               ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode) {
    340   ArmOperandGenerator g(selector);
    341   Int32BinopMatcher m(node);
    342   InstructionOperand div_operand = g.TempRegister();
    343   InstructionOperand result_operand = g.DefineAsRegister(node);
    344   InstructionOperand left_operand = g.UseRegister(m.left().node());
    345   InstructionOperand right_operand = g.UseRegister(m.right().node());
    346   EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode, div_operand,
    347           left_operand, right_operand);
    348   if (selector->IsSupported(ARMv7)) {
    349     selector->Emit(kArmMls, result_operand, div_operand, right_operand,
    350                    left_operand);
    351   } else {
    352     InstructionOperand mul_operand = g.TempRegister();
    353     selector->Emit(kArmMul, mul_operand, div_operand, right_operand);
    354     selector->Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R),
    355                    result_operand, left_operand, mul_operand);
    356   }
    357 }
    358 
    359 void EmitLoad(InstructionSelector* selector, InstructionCode opcode,
    360               InstructionOperand* output, Node* base, Node* index) {
    361   ArmOperandGenerator g(selector);
    362   InstructionOperand inputs[3];
    363   size_t input_count = 2;
    364 
    365   inputs[0] = g.UseRegister(base);
    366   if (g.CanBeImmediate(index, opcode)) {
    367     inputs[1] = g.UseImmediate(index);
    368     opcode |= AddressingModeField::encode(kMode_Offset_RI);
    369   } else if ((opcode == kArmLdr) &&
    370              TryMatchLSLImmediate(selector, &opcode, index, &inputs[1],
    371                                   &inputs[2])) {
    372     input_count = 3;
    373   } else {
    374     inputs[1] = g.UseRegister(index);
    375     opcode |= AddressingModeField::encode(kMode_Offset_RR);
    376   }
    377   selector->Emit(opcode, 1, output, input_count, inputs);
    378 }
    379 
    380 void EmitStore(InstructionSelector* selector, InstructionCode opcode,
    381                size_t input_count, InstructionOperand* inputs,
    382                Node* index) {
    383   ArmOperandGenerator g(selector);
    384 
    385   if (g.CanBeImmediate(index, opcode)) {
    386     inputs[input_count++] = g.UseImmediate(index);
    387     opcode |= AddressingModeField::encode(kMode_Offset_RI);
    388   } else if ((opcode == kArmStr) &&
    389              TryMatchLSLImmediate(selector, &opcode, index, &inputs[2],
    390                                   &inputs[3])) {
    391     input_count = 4;
    392   } else {
    393     inputs[input_count++] = g.UseRegister(index);
    394     opcode |= AddressingModeField::encode(kMode_Offset_RR);
    395   }
    396   selector->Emit(opcode, 0, nullptr, input_count, inputs);
    397 }
    398 
    399 }  // namespace
    400 
    401 
    402 void InstructionSelector::VisitLoad(Node* node) {
    403   LoadRepresentation load_rep = LoadRepresentationOf(node->op());
    404   ArmOperandGenerator g(this);
    405   Node* base = node->InputAt(0);
    406   Node* index = node->InputAt(1);
    407 
    408   InstructionCode opcode = kArchNop;
    409   switch (load_rep.representation()) {
    410     case MachineRepresentation::kFloat32:
    411       opcode = kArmVldrF32;
    412       break;
    413     case MachineRepresentation::kFloat64:
    414       opcode = kArmVldrF64;
    415       break;
    416     case MachineRepresentation::kBit:  // Fall through.
    417     case MachineRepresentation::kWord8:
    418       opcode = load_rep.IsUnsigned() ? kArmLdrb : kArmLdrsb;
    419       break;
    420     case MachineRepresentation::kWord16:
    421       opcode = load_rep.IsUnsigned() ? kArmLdrh : kArmLdrsh;
    422       break;
    423     case MachineRepresentation::kTaggedSigned:   // Fall through.
    424     case MachineRepresentation::kTaggedPointer:  // Fall through.
    425     case MachineRepresentation::kTagged:  // Fall through.
    426     case MachineRepresentation::kWord32:
    427       opcode = kArmLdr;
    428       break;
    429     case MachineRepresentation::kWord64:   // Fall through.
    430     case MachineRepresentation::kSimd128:  // Fall through.
    431     case MachineRepresentation::kSimd1x4:  // Fall through.
    432     case MachineRepresentation::kSimd1x8:  // Fall through.
    433     case MachineRepresentation::kSimd1x16:  // Fall through.
    434     case MachineRepresentation::kNone:
    435       UNREACHABLE();
    436       return;
    437   }
    438 
    439   InstructionOperand output = g.DefineAsRegister(node);
    440   EmitLoad(this, opcode, &output, base, index);
    441 }
    442 
    443 void InstructionSelector::VisitProtectedLoad(Node* node) {
    444   // TODO(eholk)
    445   UNIMPLEMENTED();
    446 }
    447 
    448 void InstructionSelector::VisitStore(Node* node) {
    449   ArmOperandGenerator g(this);
    450   Node* base = node->InputAt(0);
    451   Node* index = node->InputAt(1);
    452   Node* value = node->InputAt(2);
    453 
    454   StoreRepresentation store_rep = StoreRepresentationOf(node->op());
    455   WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind();
    456   MachineRepresentation rep = store_rep.representation();
    457 
    458   if (write_barrier_kind != kNoWriteBarrier) {
    459     DCHECK(CanBeTaggedPointer(rep));
    460     AddressingMode addressing_mode;
    461     InstructionOperand inputs[3];
    462     size_t input_count = 0;
    463     inputs[input_count++] = g.UseUniqueRegister(base);
    464     // OutOfLineRecordWrite uses the index in an 'add' instruction as well as
    465     // for the store itself, so we must check compatibility with both.
    466     if (g.CanBeImmediate(index, kArmAdd) && g.CanBeImmediate(index, kArmStr)) {
    467       inputs[input_count++] = g.UseImmediate(index);
    468       addressing_mode = kMode_Offset_RI;
    469     } else {
    470       inputs[input_count++] = g.UseUniqueRegister(index);
    471       addressing_mode = kMode_Offset_RR;
    472     }
    473     inputs[input_count++] = g.UseUniqueRegister(value);
    474     RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny;
    475     switch (write_barrier_kind) {
    476       case kNoWriteBarrier:
    477         UNREACHABLE();
    478         break;
    479       case kMapWriteBarrier:
    480         record_write_mode = RecordWriteMode::kValueIsMap;
    481         break;
    482       case kPointerWriteBarrier:
    483         record_write_mode = RecordWriteMode::kValueIsPointer;
    484         break;
    485       case kFullWriteBarrier:
    486         record_write_mode = RecordWriteMode::kValueIsAny;
    487         break;
    488     }
    489     InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
    490     size_t const temp_count = arraysize(temps);
    491     InstructionCode code = kArchStoreWithWriteBarrier;
    492     code |= AddressingModeField::encode(addressing_mode);
    493     code |= MiscField::encode(static_cast<int>(record_write_mode));
    494     Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
    495   } else {
    496     InstructionCode opcode = kArchNop;
    497     switch (rep) {
    498       case MachineRepresentation::kFloat32:
    499         opcode = kArmVstrF32;
    500         break;
    501       case MachineRepresentation::kFloat64:
    502         opcode = kArmVstrF64;
    503         break;
    504       case MachineRepresentation::kBit:  // Fall through.
    505       case MachineRepresentation::kWord8:
    506         opcode = kArmStrb;
    507         break;
    508       case MachineRepresentation::kWord16:
    509         opcode = kArmStrh;
    510         break;
    511       case MachineRepresentation::kTaggedSigned:   // Fall through.
    512       case MachineRepresentation::kTaggedPointer:  // Fall through.
    513       case MachineRepresentation::kTagged:  // Fall through.
    514       case MachineRepresentation::kWord32:
    515         opcode = kArmStr;
    516         break;
    517       case MachineRepresentation::kWord64:   // Fall through.
    518       case MachineRepresentation::kSimd128:  // Fall through.
    519       case MachineRepresentation::kSimd1x4:  // Fall through.
    520       case MachineRepresentation::kSimd1x8:  // Fall through.
    521       case MachineRepresentation::kSimd1x16:  // Fall through.
    522       case MachineRepresentation::kNone:
    523         UNREACHABLE();
    524         return;
    525     }
    526 
    527     InstructionOperand inputs[4];
    528     size_t input_count = 0;
    529     inputs[input_count++] = g.UseRegister(value);
    530     inputs[input_count++] = g.UseRegister(base);
    531     EmitStore(this, opcode, input_count, inputs, index);
    532   }
    533 }
    534 
    535 void InstructionSelector::VisitProtectedStore(Node* node) {
    536   // TODO(eholk)
    537   UNIMPLEMENTED();
    538 }
    539 
    540 void InstructionSelector::VisitUnalignedLoad(Node* node) {
    541   UnalignedLoadRepresentation load_rep =
    542       UnalignedLoadRepresentationOf(node->op());
    543   ArmOperandGenerator g(this);
    544   Node* base = node->InputAt(0);
    545   Node* index = node->InputAt(1);
    546 
    547   InstructionCode opcode = kArmLdr;
    548   // Only floating point loads need to be specially handled; integer loads
    549   // support unaligned access. We support unaligned FP loads by loading to
    550   // integer registers first, then moving to the destination FP register.
    551   switch (load_rep.representation()) {
    552     case MachineRepresentation::kFloat32: {
    553       InstructionOperand temp = g.TempRegister();
    554       EmitLoad(this, opcode, &temp, base, index);
    555       Emit(kArmVmovF32U32, g.DefineAsRegister(node), temp);
    556       return;
    557     }
    558     case MachineRepresentation::kFloat64: {
    559       // TODO(arm): use vld1.8 for this when NEON is available.
    560       // Compute the address of the least-significant half of the FP value.
    561       // We assume that the base node is unlikely to be an encodable immediate
    562       // or the result of a shift operation, so only consider the addressing
    563       // mode that should be used for the index node.
    564       InstructionCode add_opcode = kArmAdd;
    565       InstructionOperand inputs[3];
    566       inputs[0] = g.UseRegister(base);
    567 
    568       size_t input_count;
    569       if (TryMatchImmediateOrShift(this, &add_opcode, index, &input_count,
    570                                    &inputs[1])) {
    571         // input_count has been set by TryMatchImmediateOrShift(), so increment
    572         // it to account for the base register in inputs[0].
    573         input_count++;
    574       } else {
    575         add_opcode |= AddressingModeField::encode(kMode_Operand2_R);
    576         inputs[1] = g.UseRegister(index);
    577         input_count = 2;  // Base register and index.
    578       }
    579 
    580       InstructionOperand addr = g.TempRegister();
    581       Emit(add_opcode, 1, &addr, input_count, inputs);
    582 
    583       // Load both halves and move to an FP register.
    584       InstructionOperand fp_lo = g.TempRegister();
    585       InstructionOperand fp_hi = g.TempRegister();
    586       opcode |= AddressingModeField::encode(kMode_Offset_RI);
    587       Emit(opcode, fp_lo, addr, g.TempImmediate(0));
    588       Emit(opcode, fp_hi, addr, g.TempImmediate(4));
    589       Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), fp_lo, fp_hi);
    590       return;
    591     }
    592     default:
    593       // All other cases should support unaligned accesses.
    594       UNREACHABLE();
    595       return;
    596   }
    597 }
    598 
    599 void InstructionSelector::VisitUnalignedStore(Node* node) {
    600   ArmOperandGenerator g(this);
    601   Node* base = node->InputAt(0);
    602   Node* index = node->InputAt(1);
    603   Node* value = node->InputAt(2);
    604 
    605   InstructionOperand inputs[4];
    606   size_t input_count = 0;
    607 
    608   UnalignedStoreRepresentation store_rep =
    609       UnalignedStoreRepresentationOf(node->op());
    610 
    611   // Only floating point stores need to be specially handled; integer stores
    612   // support unaligned access. We support unaligned FP stores by moving the
    613   // value to integer registers first, then storing to the destination address.
    614   switch (store_rep) {
    615     case MachineRepresentation::kFloat32: {
    616       inputs[input_count++] = g.TempRegister();
    617       Emit(kArmVmovU32F32, inputs[0], g.UseRegister(value));
    618       inputs[input_count++] = g.UseRegister(base);
    619       EmitStore(this, kArmStr, input_count, inputs, index);
    620       return;
    621     }
    622     case MachineRepresentation::kFloat64: {
    623       // TODO(arm): use vst1.8 for this when NEON is available.
    624       // Store a 64-bit floating point value using two 32-bit integer stores.
    625       // Computing the store address here would require three live temporary
    626       // registers (fp<63:32>, fp<31:0>, address), so compute base + 4 after
    627       // storing the least-significant half of the value.
    628 
    629       // First, move the 64-bit FP value into two temporary integer registers.
    630       InstructionOperand fp[] = {g.TempRegister(), g.TempRegister()};
    631       inputs[input_count++] = g.UseRegister(value);
    632       Emit(kArmVmovU32U32F64, arraysize(fp), fp, input_count,
    633            inputs);
    634 
    635       // Store the least-significant half.
    636       inputs[0] = fp[0];  // Low 32-bits of FP value.
    637       inputs[input_count++] = g.UseRegister(base);  // First store base address.
    638       EmitStore(this, kArmStr, input_count, inputs, index);
    639 
    640       // Store the most-significant half.
    641       InstructionOperand base4 = g.TempRegister();
    642       Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_I), base4,
    643            g.UseRegister(base), g.TempImmediate(4));  // Compute base + 4.
    644       inputs[0] = fp[1];  // High 32-bits of FP value.
    645       inputs[1] = base4;  // Second store base + 4 address.
    646       EmitStore(this, kArmStr, input_count, inputs, index);
    647       return;
    648     }
    649     default:
    650       // All other cases should support unaligned accesses.
    651       UNREACHABLE();
    652       return;
    653   }
    654 }
    655 
    656 void InstructionSelector::VisitCheckedLoad(Node* node) {
    657   CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op());
    658   ArmOperandGenerator g(this);
    659   Node* const buffer = node->InputAt(0);
    660   Node* const offset = node->InputAt(1);
    661   Node* const length = node->InputAt(2);
    662   ArchOpcode opcode = kArchNop;
    663   switch (load_rep.representation()) {
    664     case MachineRepresentation::kWord8:
    665       opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8;
    666       break;
    667     case MachineRepresentation::kWord16:
    668       opcode = load_rep.IsSigned() ? kCheckedLoadInt16 : kCheckedLoadUint16;
    669       break;
    670     case MachineRepresentation::kWord32:
    671       opcode = kCheckedLoadWord32;
    672       break;
    673     case MachineRepresentation::kFloat32:
    674       opcode = kCheckedLoadFloat32;
    675       break;
    676     case MachineRepresentation::kFloat64:
    677       opcode = kCheckedLoadFloat64;
    678       break;
    679     case MachineRepresentation::kBit:      // Fall through.
    680     case MachineRepresentation::kTaggedSigned:   // Fall through.
    681     case MachineRepresentation::kTaggedPointer:  // Fall through.
    682     case MachineRepresentation::kTagged:   // Fall through.
    683     case MachineRepresentation::kWord64:   // Fall through.
    684     case MachineRepresentation::kSimd128:  // Fall through.
    685     case MachineRepresentation::kSimd1x4:  // Fall through.
    686     case MachineRepresentation::kSimd1x8:  // Fall through.
    687     case MachineRepresentation::kSimd1x16:  // Fall through.
    688     case MachineRepresentation::kNone:
    689       UNREACHABLE();
    690       return;
    691   }
    692   InstructionOperand offset_operand = g.UseRegister(offset);
    693   InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp)
    694                                           ? g.UseImmediate(length)
    695                                           : g.UseRegister(length);
    696   Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
    697        g.DefineAsRegister(node), offset_operand, length_operand,
    698        g.UseRegister(buffer), offset_operand);
    699 }
    700 
    701 
    702 void InstructionSelector::VisitCheckedStore(Node* node) {
    703   MachineRepresentation rep = CheckedStoreRepresentationOf(node->op());
    704   ArmOperandGenerator g(this);
    705   Node* const buffer = node->InputAt(0);
    706   Node* const offset = node->InputAt(1);
    707   Node* const length = node->InputAt(2);
    708   Node* const value = node->InputAt(3);
    709   ArchOpcode opcode = kArchNop;
    710   switch (rep) {
    711     case MachineRepresentation::kWord8:
    712       opcode = kCheckedStoreWord8;
    713       break;
    714     case MachineRepresentation::kWord16:
    715       opcode = kCheckedStoreWord16;
    716       break;
    717     case MachineRepresentation::kWord32:
    718       opcode = kCheckedStoreWord32;
    719       break;
    720     case MachineRepresentation::kFloat32:
    721       opcode = kCheckedStoreFloat32;
    722       break;
    723     case MachineRepresentation::kFloat64:
    724       opcode = kCheckedStoreFloat64;
    725       break;
    726     case MachineRepresentation::kBit:      // Fall through.
    727     case MachineRepresentation::kTaggedSigned:   // Fall through.
    728     case MachineRepresentation::kTaggedPointer:  // Fall through.
    729     case MachineRepresentation::kTagged:   // Fall through.
    730     case MachineRepresentation::kWord64:   // Fall through.
    731     case MachineRepresentation::kSimd128:  // Fall through.
    732     case MachineRepresentation::kSimd1x4:  // Fall through.
    733     case MachineRepresentation::kSimd1x8:  // Fall through.
    734     case MachineRepresentation::kSimd1x16:  // Fall through.
    735     case MachineRepresentation::kNone:
    736       UNREACHABLE();
    737       return;
    738   }
    739   InstructionOperand offset_operand = g.UseRegister(offset);
    740   InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp)
    741                                           ? g.UseImmediate(length)
    742                                           : g.UseRegister(length);
    743   Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), g.NoOutput(),
    744        offset_operand, length_operand, g.UseRegister(value),
    745        g.UseRegister(buffer), offset_operand);
    746 }
    747 
    748 
    749 namespace {
    750 
    751 void EmitBic(InstructionSelector* selector, Node* node, Node* left,
    752              Node* right) {
    753   ArmOperandGenerator g(selector);
    754   InstructionCode opcode = kArmBic;
    755   InstructionOperand value_operand;
    756   InstructionOperand shift_operand;
    757   if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) {
    758     selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
    759                    value_operand, shift_operand);
    760     return;
    761   }
    762   selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
    763                  g.DefineAsRegister(node), g.UseRegister(left),
    764                  g.UseRegister(right));
    765 }
    766 
    767 
    768 void EmitUbfx(InstructionSelector* selector, Node* node, Node* left,
    769               uint32_t lsb, uint32_t width) {
    770   DCHECK_LE(1u, width);
    771   DCHECK_LE(width, 32u - lsb);
    772   ArmOperandGenerator g(selector);
    773   selector->Emit(kArmUbfx, g.DefineAsRegister(node), g.UseRegister(left),
    774                  g.TempImmediate(lsb), g.TempImmediate(width));
    775 }
    776 
    777 }  // namespace
    778 
    779 
    780 void InstructionSelector::VisitWord32And(Node* node) {
    781   ArmOperandGenerator g(this);
    782   Int32BinopMatcher m(node);
    783   if (m.left().IsWord32Xor() && CanCover(node, m.left().node())) {
    784     Int32BinopMatcher mleft(m.left().node());
    785     if (mleft.right().Is(-1)) {
    786       EmitBic(this, node, m.right().node(), mleft.left().node());
    787       return;
    788     }
    789   }
    790   if (m.right().IsWord32Xor() && CanCover(node, m.right().node())) {
    791     Int32BinopMatcher mright(m.right().node());
    792     if (mright.right().Is(-1)) {
    793       EmitBic(this, node, m.left().node(), mright.left().node());
    794       return;
    795     }
    796   }
    797   if (m.right().HasValue()) {
    798     uint32_t const value = m.right().Value();
    799     uint32_t width = base::bits::CountPopulation32(value);
    800     uint32_t leading_zeros = base::bits::CountLeadingZeros32(value);
    801 
    802     // Try to merge SHR operations on the left hand input into this AND.
    803     if (m.left().IsWord32Shr()) {
    804       Int32BinopMatcher mshr(m.left().node());
    805       if (mshr.right().HasValue()) {
    806         uint32_t const shift = mshr.right().Value();
    807 
    808         if (((shift == 8) || (shift == 16) || (shift == 24)) &&
    809             ((value == 0xff) || (value == 0xffff))) {
    810           // Merge SHR into AND by emitting a UXTB or UXTH instruction with a
    811           // bytewise rotation.
    812           Emit((value == 0xff) ? kArmUxtb : kArmUxth,
    813                g.DefineAsRegister(m.node()), g.UseRegister(mshr.left().node()),
    814                g.TempImmediate(mshr.right().Value()));
    815           return;
    816         } else if (IsSupported(ARMv7) && (width != 0) &&
    817                    ((leading_zeros + width) == 32)) {
    818           // Merge Shr into And by emitting a UBFX instruction.
    819           DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value));
    820           if ((1 <= shift) && (shift <= 31)) {
    821             // UBFX cannot extract bits past the register size, however since
    822             // shifting the original value would have introduced some zeros we
    823             // can still use UBFX with a smaller mask and the remaining bits
    824             // will be zeros.
    825             EmitUbfx(this, node, mshr.left().node(), shift,
    826                      std::min(width, 32 - shift));
    827             return;
    828           }
    829         }
    830       }
    831     } else if (value == 0xffff) {
    832       // Emit UXTH for this AND. We don't bother testing for UXTB, as it's no
    833       // better than AND 0xff for this operation.
    834       Emit(kArmUxth, g.DefineAsRegister(m.node()),
    835            g.UseRegister(m.left().node()), g.TempImmediate(0));
    836       return;
    837     }
    838     if (g.CanBeImmediate(~value)) {
    839       // Emit BIC for this AND by inverting the immediate value first.
    840       Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I),
    841            g.DefineAsRegister(node), g.UseRegister(m.left().node()),
    842            g.TempImmediate(~value));
    843       return;
    844     }
    845     if (!g.CanBeImmediate(value) && IsSupported(ARMv7)) {
    846       // If value has 9 to 23 contiguous set bits, and has the lsb set, we can
    847       // replace this AND with UBFX. Other contiguous bit patterns have already
    848       // been handled by BIC or will be handled by AND.
    849       if ((width != 0) && ((leading_zeros + width) == 32) &&
    850           (9 <= leading_zeros) && (leading_zeros <= 23)) {
    851         DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value));
    852         EmitUbfx(this, node, m.left().node(), 0, width);
    853         return;
    854       }
    855 
    856       width = 32 - width;
    857       leading_zeros = base::bits::CountLeadingZeros32(~value);
    858       uint32_t lsb = base::bits::CountTrailingZeros32(~value);
    859       if ((leading_zeros + width + lsb) == 32) {
    860         // This AND can be replaced with BFC.
    861         Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
    862              g.TempImmediate(lsb), g.TempImmediate(width));
    863         return;
    864       }
    865     }
    866   }
    867   VisitBinop(this, node, kArmAnd, kArmAnd);
    868 }
    869 
    870 
    871 void InstructionSelector::VisitWord32Or(Node* node) {
    872   VisitBinop(this, node, kArmOrr, kArmOrr);
    873 }
    874 
    875 
    876 void InstructionSelector::VisitWord32Xor(Node* node) {
    877   ArmOperandGenerator g(this);
    878   Int32BinopMatcher m(node);
    879   if (m.right().Is(-1)) {
    880     InstructionCode opcode = kArmMvn;
    881     InstructionOperand value_operand;
    882     InstructionOperand shift_operand;
    883     if (TryMatchShift(this, &opcode, m.left().node(), &value_operand,
    884                       &shift_operand)) {
    885       Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand);
    886       return;
    887     }
    888     Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
    889          g.DefineAsRegister(node), g.UseRegister(m.left().node()));
    890     return;
    891   }
    892   VisitBinop(this, node, kArmEor, kArmEor);
    893 }
    894 
    895 
    896 namespace {
    897 
    898 template <typename TryMatchShift>
    899 void VisitShift(InstructionSelector* selector, Node* node,
    900                 TryMatchShift try_match_shift, FlagsContinuation* cont) {
    901   ArmOperandGenerator g(selector);
    902   InstructionCode opcode = kArmMov;
    903   InstructionOperand inputs[4];
    904   size_t input_count = 2;
    905   InstructionOperand outputs[2];
    906   size_t output_count = 0;
    907 
    908   CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1]));
    909 
    910   if (cont->IsBranch()) {
    911     inputs[input_count++] = g.Label(cont->true_block());
    912     inputs[input_count++] = g.Label(cont->false_block());
    913   }
    914 
    915   outputs[output_count++] = g.DefineAsRegister(node);
    916   if (cont->IsSet()) {
    917     outputs[output_count++] = g.DefineAsRegister(cont->result());
    918   }
    919 
    920   DCHECK_NE(0u, input_count);
    921   DCHECK_NE(0u, output_count);
    922   DCHECK_GE(arraysize(inputs), input_count);
    923   DCHECK_GE(arraysize(outputs), output_count);
    924   DCHECK_NE(kMode_None, AddressingModeField::decode(opcode));
    925 
    926   opcode = cont->Encode(opcode);
    927   if (cont->IsDeoptimize()) {
    928     selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
    929                              cont->kind(), cont->reason(), cont->frame_state());
    930   } else if (cont->IsTrap()) {
    931     inputs[input_count++] = g.UseImmediate(cont->trap_id());
    932     selector->Emit(opcode, output_count, outputs, input_count, inputs);
    933   } else {
    934     selector->Emit(opcode, output_count, outputs, input_count, inputs);
    935   }
    936 }
    937 
    938 
    939 template <typename TryMatchShift>
    940 void VisitShift(InstructionSelector* selector, Node* node,
    941                               TryMatchShift try_match_shift) {
    942   FlagsContinuation cont;
    943   VisitShift(selector, node, try_match_shift, &cont);
    944 }
    945 
    946 }  // namespace
    947 
    948 
    949 void InstructionSelector::VisitWord32Shl(Node* node) {
    950   VisitShift(this, node, TryMatchLSL);
    951 }
    952 
    953 
    954 void InstructionSelector::VisitWord32Shr(Node* node) {
    955   ArmOperandGenerator g(this);
    956   Int32BinopMatcher m(node);
    957   if (IsSupported(ARMv7) && m.left().IsWord32And() &&
    958       m.right().IsInRange(0, 31)) {
    959     uint32_t lsb = m.right().Value();
    960     Int32BinopMatcher mleft(m.left().node());
    961     if (mleft.right().HasValue()) {
    962       uint32_t value = (mleft.right().Value() >> lsb) << lsb;
    963       uint32_t width = base::bits::CountPopulation32(value);
    964       uint32_t msb = base::bits::CountLeadingZeros32(value);
    965       if (msb + width + lsb == 32) {
    966         DCHECK_EQ(lsb, base::bits::CountTrailingZeros32(value));
    967         return EmitUbfx(this, node, mleft.left().node(), lsb, width);
    968       }
    969     }
    970   }
    971   VisitShift(this, node, TryMatchLSR);
    972 }
    973 
    974 
    975 void InstructionSelector::VisitWord32Sar(Node* node) {
    976   ArmOperandGenerator g(this);
    977   Int32BinopMatcher m(node);
    978   if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) {
    979     Int32BinopMatcher mleft(m.left().node());
    980     if (m.right().HasValue() && mleft.right().HasValue()) {
    981       uint32_t sar = m.right().Value();
    982       uint32_t shl = mleft.right().Value();
    983       if ((sar == shl) && (sar == 16)) {
    984         Emit(kArmSxth, g.DefineAsRegister(node),
    985              g.UseRegister(mleft.left().node()), g.TempImmediate(0));
    986         return;
    987       } else if ((sar == shl) && (sar == 24)) {
    988         Emit(kArmSxtb, g.DefineAsRegister(node),
    989              g.UseRegister(mleft.left().node()), g.TempImmediate(0));
    990         return;
    991       } else if (IsSupported(ARMv7) && (sar >= shl)) {
    992         Emit(kArmSbfx, g.DefineAsRegister(node),
    993              g.UseRegister(mleft.left().node()), g.TempImmediate(sar - shl),
    994              g.TempImmediate(32 - sar));
    995         return;
    996       }
    997     }
    998   }
    999   VisitShift(this, node, TryMatchASR);
   1000 }
   1001 
   1002 void InstructionSelector::VisitInt32PairAdd(Node* node) {
   1003   ArmOperandGenerator g(this);
   1004 
   1005   Node* projection1 = NodeProperties::FindProjection(node, 1);
   1006   if (projection1) {
   1007     // We use UseUniqueRegister here to avoid register sharing with the output
   1008     // registers.
   1009     InstructionOperand inputs[] = {
   1010         g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
   1011         g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};
   1012 
   1013     InstructionOperand outputs[] = {
   1014         g.DefineAsRegister(node),
   1015         g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
   1016 
   1017     Emit(kArmAddPair, 2, outputs, 4, inputs);
   1018   } else {
   1019     // The high word of the result is not used, so we emit the standard 32 bit
   1020     // instruction.
   1021     Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_R),
   1022          g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
   1023          g.UseRegister(node->InputAt(2)));
   1024   }
   1025 }
   1026 
   1027 void InstructionSelector::VisitInt32PairSub(Node* node) {
   1028   ArmOperandGenerator g(this);
   1029 
   1030   Node* projection1 = NodeProperties::FindProjection(node, 1);
   1031   if (projection1) {
   1032     // We use UseUniqueRegister here to avoid register sharing with the output
   1033     // register.
   1034     InstructionOperand inputs[] = {
   1035         g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
   1036         g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};
   1037 
   1038     InstructionOperand outputs[] = {
   1039         g.DefineAsRegister(node),
   1040         g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
   1041 
   1042     Emit(kArmSubPair, 2, outputs, 4, inputs);
   1043   } else {
   1044     // The high word of the result is not used, so we emit the standard 32 bit
   1045     // instruction.
   1046     Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_R),
   1047          g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
   1048          g.UseRegister(node->InputAt(2)));
   1049   }
   1050 }
   1051 
   1052 void InstructionSelector::VisitInt32PairMul(Node* node) {
   1053   ArmOperandGenerator g(this);
   1054   Node* projection1 = NodeProperties::FindProjection(node, 1);
   1055   if (projection1) {
   1056     InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
   1057                                    g.UseUniqueRegister(node->InputAt(1)),
   1058                                    g.UseUniqueRegister(node->InputAt(2)),
   1059                                    g.UseUniqueRegister(node->InputAt(3))};
   1060 
   1061     InstructionOperand outputs[] = {
   1062         g.DefineAsRegister(node),
   1063         g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
   1064 
   1065     Emit(kArmMulPair, 2, outputs, 4, inputs);
   1066   } else {
   1067     // The high word of the result is not used, so we emit the standard 32 bit
   1068     // instruction.
   1069     Emit(kArmMul | AddressingModeField::encode(kMode_Operand2_R),
   1070          g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)),
   1071          g.UseRegister(node->InputAt(2)));
   1072   }
   1073 }
   1074 
   1075 namespace {
   1076 // Shared routine for multiple shift operations.
   1077 void VisitWord32PairShift(InstructionSelector* selector, InstructionCode opcode,
   1078                           Node* node) {
   1079   ArmOperandGenerator g(selector);
   1080   // We use g.UseUniqueRegister here to guarantee that there is
   1081   // no register aliasing of input registers with output registers.
   1082   Int32Matcher m(node->InputAt(2));
   1083   InstructionOperand shift_operand;
   1084   if (m.HasValue()) {
   1085     shift_operand = g.UseImmediate(m.node());
   1086   } else {
   1087     shift_operand = g.UseUniqueRegister(m.node());
   1088   }
   1089 
   1090   InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
   1091                                  g.UseUniqueRegister(node->InputAt(1)),
   1092                                  shift_operand};
   1093 
   1094   Node* projection1 = NodeProperties::FindProjection(node, 1);
   1095 
   1096   InstructionOperand outputs[2];
   1097   InstructionOperand temps[1];
   1098   int32_t output_count = 0;
   1099   int32_t temp_count = 0;
   1100 
   1101   outputs[output_count++] = g.DefineAsRegister(node);
   1102   if (projection1) {
   1103     outputs[output_count++] = g.DefineAsRegister(projection1);
   1104   } else {
   1105     temps[temp_count++] = g.TempRegister();
   1106   }
   1107 
   1108   selector->Emit(opcode, output_count, outputs, 3, inputs, temp_count, temps);
   1109 }
   1110 }  // namespace
   1111 void InstructionSelector::VisitWord32PairShl(Node* node) {
   1112   VisitWord32PairShift(this, kArmLslPair, node);
   1113 }
   1114 
   1115 void InstructionSelector::VisitWord32PairShr(Node* node) {
   1116   VisitWord32PairShift(this, kArmLsrPair, node);
   1117 }
   1118 
   1119 void InstructionSelector::VisitWord32PairSar(Node* node) {
   1120   VisitWord32PairShift(this, kArmAsrPair, node);
   1121 }
   1122 
   1123 void InstructionSelector::VisitWord32Ror(Node* node) {
   1124   VisitShift(this, node, TryMatchROR);
   1125 }
   1126 
   1127 void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
   1128 
   1129 void InstructionSelector::VisitWord32ReverseBits(Node* node) {
   1130   DCHECK(IsSupported(ARMv7));
   1131   VisitRR(this, kArmRbit, node);
   1132 }
   1133 
   1134 void InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); }
   1135 
   1136 void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }
   1137 
   1138 void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
   1139 
   1140 
   1141 void InstructionSelector::VisitInt32Add(Node* node) {
   1142   ArmOperandGenerator g(this);
   1143   Int32BinopMatcher m(node);
   1144   if (CanCover(node, m.left().node())) {
   1145     switch (m.left().opcode()) {
   1146       case IrOpcode::kInt32Mul: {
   1147         Int32BinopMatcher mleft(m.left().node());
   1148         Emit(kArmMla, g.DefineAsRegister(node),
   1149              g.UseRegister(mleft.left().node()),
   1150              g.UseRegister(mleft.right().node()),
   1151              g.UseRegister(m.right().node()));
   1152         return;
   1153       }
   1154       case IrOpcode::kInt32MulHigh: {
   1155         Int32BinopMatcher mleft(m.left().node());
   1156         Emit(kArmSmmla, g.DefineAsRegister(node),
   1157              g.UseRegister(mleft.left().node()),
   1158              g.UseRegister(mleft.right().node()),
   1159              g.UseRegister(m.right().node()));
   1160         return;
   1161       }
   1162       case IrOpcode::kWord32And: {
   1163         Int32BinopMatcher mleft(m.left().node());
   1164         if (mleft.right().Is(0xff)) {
   1165           Emit(kArmUxtab, g.DefineAsRegister(node),
   1166                g.UseRegister(m.right().node()),
   1167                g.UseRegister(mleft.left().node()), g.TempImmediate(0));
   1168           return;
   1169         } else if (mleft.right().Is(0xffff)) {
   1170           Emit(kArmUxtah, g.DefineAsRegister(node),
   1171                g.UseRegister(m.right().node()),
   1172                g.UseRegister(mleft.left().node()), g.TempImmediate(0));
   1173           return;
   1174         }
   1175       }
   1176       case IrOpcode::kWord32Sar: {
   1177         Int32BinopMatcher mleft(m.left().node());
   1178         if (CanCover(mleft.node(), mleft.left().node()) &&
   1179             mleft.left().IsWord32Shl()) {
   1180           Int32BinopMatcher mleftleft(mleft.left().node());
   1181           if (mleft.right().Is(24) && mleftleft.right().Is(24)) {
   1182             Emit(kArmSxtab, g.DefineAsRegister(node),
   1183                  g.UseRegister(m.right().node()),
   1184                  g.UseRegister(mleftleft.left().node()), g.TempImmediate(0));
   1185             return;
   1186           } else if (mleft.right().Is(16) && mleftleft.right().Is(16)) {
   1187             Emit(kArmSxtah, g.DefineAsRegister(node),
   1188                  g.UseRegister(m.right().node()),
   1189                  g.UseRegister(mleftleft.left().node()), g.TempImmediate(0));
   1190             return;
   1191           }
   1192         }
   1193       }
   1194       default:
   1195         break;
   1196     }
   1197   }
   1198   if (CanCover(node, m.right().node())) {
   1199     switch (m.right().opcode()) {
   1200       case IrOpcode::kInt32Mul: {
   1201         Int32BinopMatcher mright(m.right().node());
   1202         Emit(kArmMla, g.DefineAsRegister(node),
   1203              g.UseRegister(mright.left().node()),
   1204              g.UseRegister(mright.right().node()),
   1205              g.UseRegister(m.left().node()));
   1206         return;
   1207       }
   1208       case IrOpcode::kInt32MulHigh: {
   1209         Int32BinopMatcher mright(m.right().node());
   1210         Emit(kArmSmmla, g.DefineAsRegister(node),
   1211              g.UseRegister(mright.left().node()),
   1212              g.UseRegister(mright.right().node()),
   1213              g.UseRegister(m.left().node()));
   1214         return;
   1215       }
   1216       case IrOpcode::kWord32And: {
   1217         Int32BinopMatcher mright(m.right().node());
   1218         if (mright.right().Is(0xff)) {
   1219           Emit(kArmUxtab, g.DefineAsRegister(node),
   1220                g.UseRegister(m.left().node()),
   1221                g.UseRegister(mright.left().node()), g.TempImmediate(0));
   1222           return;
   1223         } else if (mright.right().Is(0xffff)) {
   1224           Emit(kArmUxtah, g.DefineAsRegister(node),
   1225                g.UseRegister(m.left().node()),
   1226                g.UseRegister(mright.left().node()), g.TempImmediate(0));
   1227           return;
   1228         }
   1229       }
   1230       case IrOpcode::kWord32Sar: {
   1231         Int32BinopMatcher mright(m.right().node());
   1232         if (CanCover(mright.node(), mright.left().node()) &&
   1233             mright.left().IsWord32Shl()) {
   1234           Int32BinopMatcher mrightleft(mright.left().node());
   1235           if (mright.right().Is(24) && mrightleft.right().Is(24)) {
   1236             Emit(kArmSxtab, g.DefineAsRegister(node),
   1237                  g.UseRegister(m.left().node()),
   1238                  g.UseRegister(mrightleft.left().node()), g.TempImmediate(0));
   1239             return;
   1240           } else if (mright.right().Is(16) && mrightleft.right().Is(16)) {
   1241             Emit(kArmSxtah, g.DefineAsRegister(node),
   1242                  g.UseRegister(m.left().node()),
   1243                  g.UseRegister(mrightleft.left().node()), g.TempImmediate(0));
   1244             return;
   1245           }
   1246         }
   1247       }
   1248       default:
   1249         break;
   1250     }
   1251   }
   1252   VisitBinop(this, node, kArmAdd, kArmAdd);
   1253 }
   1254 
   1255 
   1256 void InstructionSelector::VisitInt32Sub(Node* node) {
   1257   ArmOperandGenerator g(this);
   1258   Int32BinopMatcher m(node);
   1259   if (IsSupported(ARMv7) && m.right().IsInt32Mul() &&
   1260       CanCover(node, m.right().node())) {
   1261     Int32BinopMatcher mright(m.right().node());
   1262     Emit(kArmMls, g.DefineAsRegister(node), g.UseRegister(mright.left().node()),
   1263          g.UseRegister(mright.right().node()), g.UseRegister(m.left().node()));
   1264     return;
   1265   }
   1266   VisitBinop(this, node, kArmSub, kArmRsb);
   1267 }
   1268 
   1269 namespace {
   1270 
   1271 void EmitInt32MulWithOverflow(InstructionSelector* selector, Node* node,
   1272                               FlagsContinuation* cont) {
   1273   ArmOperandGenerator g(selector);
   1274   Int32BinopMatcher m(node);
   1275   InstructionOperand result_operand = g.DefineAsRegister(node);
   1276   InstructionOperand temp_operand = g.TempRegister();
   1277   InstructionOperand outputs[] = {result_operand, temp_operand};
   1278   InstructionOperand inputs[] = {g.UseRegister(m.left().node()),
   1279                                  g.UseRegister(m.right().node())};
   1280   selector->Emit(kArmSmull, 2, outputs, 2, inputs);
   1281 
   1282   // result operand needs shift operator.
   1283   InstructionOperand shift_31 = g.UseImmediate(31);
   1284   InstructionCode opcode = cont->Encode(kArmCmp) |
   1285                            AddressingModeField::encode(kMode_Operand2_R_ASR_I);
   1286   if (cont->IsBranch()) {
   1287     selector->Emit(opcode, g.NoOutput(), temp_operand, result_operand, shift_31,
   1288                    g.Label(cont->true_block()), g.Label(cont->false_block()));
   1289   } else if (cont->IsDeoptimize()) {
   1290     InstructionOperand in[] = {temp_operand, result_operand, shift_31};
   1291     selector->EmitDeoptimize(opcode, 0, nullptr, 3, in, cont->kind(),
   1292                              cont->reason(), cont->frame_state());
   1293   } else if (cont->IsSet()) {
   1294     selector->Emit(opcode, g.DefineAsRegister(cont->result()), temp_operand,
   1295                    result_operand, shift_31);
   1296   } else {
   1297     DCHECK(cont->IsTrap());
   1298     InstructionOperand in[] = {temp_operand, result_operand, shift_31,
   1299                                g.UseImmediate(cont->trap_id())};
   1300     selector->Emit(opcode, 0, nullptr, 4, in);
   1301   }
   1302 }
   1303 
   1304 }  // namespace
   1305 
   1306 void InstructionSelector::VisitInt32Mul(Node* node) {
   1307   ArmOperandGenerator g(this);
   1308   Int32BinopMatcher m(node);
   1309   if (m.right().HasValue() && m.right().Value() > 0) {
   1310     int32_t value = m.right().Value();
   1311     if (base::bits::IsPowerOfTwo32(value - 1)) {
   1312       Emit(kArmAdd | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
   1313            g.DefineAsRegister(node), g.UseRegister(m.left().node()),
   1314            g.UseRegister(m.left().node()),
   1315            g.TempImmediate(WhichPowerOf2(value - 1)));
   1316       return;
   1317     }
   1318     if (value < kMaxInt && base::bits::IsPowerOfTwo32(value + 1)) {
   1319       Emit(kArmRsb | AddressingModeField::encode(kMode_Operand2_R_LSL_I),
   1320            g.DefineAsRegister(node), g.UseRegister(m.left().node()),
   1321            g.UseRegister(m.left().node()),
   1322            g.TempImmediate(WhichPowerOf2(value + 1)));
   1323       return;
   1324     }
   1325   }
   1326   VisitRRR(this, kArmMul, node);
   1327 }
   1328 
   1329 void InstructionSelector::VisitUint32MulHigh(Node* node) {
   1330   ArmOperandGenerator g(this);
   1331   InstructionOperand outputs[] = {g.TempRegister(), g.DefineAsRegister(node)};
   1332   InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0)),
   1333                                  g.UseRegister(node->InputAt(1))};
   1334   Emit(kArmUmull, arraysize(outputs), outputs, arraysize(inputs), inputs);
   1335 }
   1336 
   1337 
   1338 void InstructionSelector::VisitInt32Div(Node* node) {
   1339   VisitDiv(this, node, kArmSdiv, kArmVcvtF64S32, kArmVcvtS32F64);
   1340 }
   1341 
   1342 
   1343 void InstructionSelector::VisitUint32Div(Node* node) {
   1344   VisitDiv(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64);
   1345 }
   1346 
   1347 
   1348 void InstructionSelector::VisitInt32Mod(Node* node) {
   1349   VisitMod(this, node, kArmSdiv, kArmVcvtF64S32, kArmVcvtS32F64);
   1350 }
   1351 
   1352 
   1353 void InstructionSelector::VisitUint32Mod(Node* node) {
   1354   VisitMod(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64);
   1355 }
   1356 
   1357 #define RR_OP_LIST(V)                                \
   1358   V(Word32Clz, kArmClz)                              \
   1359   V(ChangeFloat32ToFloat64, kArmVcvtF64F32)          \
   1360   V(RoundInt32ToFloat32, kArmVcvtF32S32)             \
   1361   V(RoundUint32ToFloat32, kArmVcvtF32U32)            \
   1362   V(ChangeInt32ToFloat64, kArmVcvtF64S32)            \
   1363   V(ChangeUint32ToFloat64, kArmVcvtF64U32)           \
   1364   V(TruncateFloat32ToInt32, kArmVcvtS32F32)          \
   1365   V(TruncateFloat32ToUint32, kArmVcvtU32F32)         \
   1366   V(ChangeFloat64ToInt32, kArmVcvtS32F64)            \
   1367   V(ChangeFloat64ToUint32, kArmVcvtU32F64)           \
   1368   V(TruncateFloat64ToUint32, kArmVcvtU32F64)         \
   1369   V(TruncateFloat64ToFloat32, kArmVcvtF32F64)        \
   1370   V(TruncateFloat64ToWord32, kArchTruncateDoubleToI) \
   1371   V(RoundFloat64ToInt32, kArmVcvtS32F64)             \
   1372   V(BitcastFloat32ToInt32, kArmVmovU32F32)           \
   1373   V(BitcastInt32ToFloat32, kArmVmovF32U32)           \
   1374   V(Float64ExtractLowWord32, kArmVmovLowU32F64)      \
   1375   V(Float64ExtractHighWord32, kArmVmovHighU32F64)    \
   1376   V(Float64SilenceNaN, kArmFloat64SilenceNaN)        \
   1377   V(Float32Abs, kArmVabsF32)                         \
   1378   V(Float64Abs, kArmVabsF64)                         \
   1379   V(Float32Neg, kArmVnegF32)                         \
   1380   V(Float64Neg, kArmVnegF64)                         \
   1381   V(Float32Sqrt, kArmVsqrtF32)                       \
   1382   V(Float64Sqrt, kArmVsqrtF64)
   1383 
   1384 #define RR_OP_LIST_V8(V)                 \
   1385   V(Float32RoundDown, kArmVrintmF32)     \
   1386   V(Float64RoundDown, kArmVrintmF64)     \
   1387   V(Float32RoundUp, kArmVrintpF32)       \
   1388   V(Float64RoundUp, kArmVrintpF64)       \
   1389   V(Float32RoundTruncate, kArmVrintzF32) \
   1390   V(Float64RoundTruncate, kArmVrintzF64) \
   1391   V(Float64RoundTiesAway, kArmVrintaF64) \
   1392   V(Float32RoundTiesEven, kArmVrintnF32) \
   1393   V(Float64RoundTiesEven, kArmVrintnF64)
   1394 
   1395 #define RRR_OP_LIST(V)          \
   1396   V(Int32MulHigh, kArmSmmul)    \
   1397   V(Float32Mul, kArmVmulF32)    \
   1398   V(Float64Mul, kArmVmulF64)    \
   1399   V(Float32Div, kArmVdivF32)    \
   1400   V(Float64Div, kArmVdivF64)    \
   1401   V(Float32Max, kArmFloat32Max) \
   1402   V(Float64Max, kArmFloat64Max) \
   1403   V(Float32Min, kArmFloat32Min) \
   1404   V(Float64Min, kArmFloat64Min)
   1405 
   1406 #define RR_VISITOR(Name, opcode)                      \
   1407   void InstructionSelector::Visit##Name(Node* node) { \
   1408     VisitRR(this, opcode, node);                      \
   1409   }
   1410 RR_OP_LIST(RR_VISITOR)
   1411 #undef RR_VISITOR
   1412 
   1413 #define RR_VISITOR_V8(Name, opcode)                   \
   1414   void InstructionSelector::Visit##Name(Node* node) { \
   1415     DCHECK(CpuFeatures::IsSupported(ARMv8));          \
   1416     VisitRR(this, opcode, node);                      \
   1417   }
   1418 RR_OP_LIST_V8(RR_VISITOR_V8)
   1419 #undef RR_VISITOR_V8
   1420 
   1421 #define RRR_VISITOR(Name, opcode)                     \
   1422   void InstructionSelector::Visit##Name(Node* node) { \
   1423     VisitRRR(this, opcode, node);                     \
   1424   }
   1425 RRR_OP_LIST(RRR_VISITOR)
   1426 #undef RRR_VISITOR
   1427 
   1428 void InstructionSelector::VisitFloat32Add(Node* node) {
   1429   ArmOperandGenerator g(this);
   1430   Float32BinopMatcher m(node);
   1431   if (m.left().IsFloat32Mul() && CanCover(node, m.left().node())) {
   1432     Float32BinopMatcher mleft(m.left().node());
   1433     Emit(kArmVmlaF32, g.DefineSameAsFirst(node),
   1434          g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()),
   1435          g.UseRegister(mleft.right().node()));
   1436     return;
   1437   }
   1438   if (m.right().IsFloat32Mul() && CanCover(node, m.right().node())) {
   1439     Float32BinopMatcher mright(m.right().node());
   1440     Emit(kArmVmlaF32, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
   1441          g.UseRegister(mright.left().node()),
   1442          g.UseRegister(mright.right().node()));
   1443     return;
   1444   }
   1445   VisitRRR(this, kArmVaddF32, node);
   1446 }
   1447 
   1448 
   1449 void InstructionSelector::VisitFloat64Add(Node* node) {
   1450   ArmOperandGenerator g(this);
   1451   Float64BinopMatcher m(node);
   1452   if (m.left().IsFloat64Mul() && CanCover(node, m.left().node())) {
   1453     Float64BinopMatcher mleft(m.left().node());
   1454     Emit(kArmVmlaF64, g.DefineSameAsFirst(node),
   1455          g.UseRegister(m.right().node()), g.UseRegister(mleft.left().node()),
   1456          g.UseRegister(mleft.right().node()));
   1457     return;
   1458   }
   1459   if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
   1460     Float64BinopMatcher mright(m.right().node());
   1461     Emit(kArmVmlaF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
   1462          g.UseRegister(mright.left().node()),
   1463          g.UseRegister(mright.right().node()));
   1464     return;
   1465   }
   1466   VisitRRR(this, kArmVaddF64, node);
   1467 }
   1468 
   1469 void InstructionSelector::VisitFloat32Sub(Node* node) {
   1470   ArmOperandGenerator g(this);
   1471   Float32BinopMatcher m(node);
   1472   if (m.right().IsFloat32Mul() && CanCover(node, m.right().node())) {
   1473     Float32BinopMatcher mright(m.right().node());
   1474     Emit(kArmVmlsF32, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
   1475          g.UseRegister(mright.left().node()),
   1476          g.UseRegister(mright.right().node()));
   1477     return;
   1478   }
   1479   VisitRRR(this, kArmVsubF32, node);
   1480 }
   1481 
   1482 void InstructionSelector::VisitFloat64Sub(Node* node) {
   1483   ArmOperandGenerator g(this);
   1484   Float64BinopMatcher m(node);
   1485   if (m.right().IsFloat64Mul() && CanCover(node, m.right().node())) {
   1486     Float64BinopMatcher mright(m.right().node());
   1487     Emit(kArmVmlsF64, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
   1488          g.UseRegister(mright.left().node()),
   1489          g.UseRegister(mright.right().node()));
   1490     return;
   1491   }
   1492   VisitRRR(this, kArmVsubF64, node);
   1493 }
   1494 
   1495 void InstructionSelector::VisitFloat64Mod(Node* node) {
   1496   ArmOperandGenerator g(this);
   1497   Emit(kArmVmodF64, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0),
   1498        g.UseFixed(node->InputAt(1), d1))->MarkAsCall();
   1499 }
   1500 
   1501 void InstructionSelector::VisitFloat64Ieee754Binop(Node* node,
   1502                                                    InstructionCode opcode) {
   1503   ArmOperandGenerator g(this);
   1504   Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0),
   1505        g.UseFixed(node->InputAt(1), d1))
   1506       ->MarkAsCall();
   1507 }
   1508 
   1509 void InstructionSelector::VisitFloat64Ieee754Unop(Node* node,
   1510                                                   InstructionCode opcode) {
   1511   ArmOperandGenerator g(this);
   1512   Emit(opcode, g.DefineAsFixed(node, d0), g.UseFixed(node->InputAt(0), d0))
   1513       ->MarkAsCall();
   1514 }
   1515 
   1516 void InstructionSelector::EmitPrepareArguments(
   1517     ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
   1518     Node* node) {
   1519   ArmOperandGenerator g(this);
   1520 
   1521   // Prepare for C function call.
   1522   if (descriptor->IsCFunctionCall()) {
   1523     Emit(kArchPrepareCallCFunction |
   1524              MiscField::encode(static_cast<int>(descriptor->ParameterCount())),
   1525          0, nullptr, 0, nullptr);
   1526 
   1527     // Poke any stack arguments.
   1528     for (size_t n = 0; n < arguments->size(); ++n) {
   1529       PushParameter input = (*arguments)[n];
   1530       if (input.node()) {
   1531         int slot = static_cast<int>(n);
   1532         Emit(kArmPoke | MiscField::encode(slot), g.NoOutput(),
   1533              g.UseRegister(input.node()));
   1534       }
   1535     }
   1536   } else {
   1537     // Push any stack arguments.
   1538     for (PushParameter input : base::Reversed(*arguments)) {
   1539       // Skip any alignment holes in pushed nodes.
   1540       if (input.node() == nullptr) continue;
   1541       Emit(kArmPush, g.NoOutput(), g.UseRegister(input.node()));
   1542     }
   1543   }
   1544 }
   1545 
   1546 
   1547 bool InstructionSelector::IsTailCallAddressImmediate() { return false; }
   1548 
   1549 int InstructionSelector::GetTempsCountForTailCallFromJSFunction() { return 3; }
   1550 
   1551 namespace {
   1552 
   1553 // Shared routine for multiple compare operations.
   1554 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
   1555                   InstructionOperand left, InstructionOperand right,
   1556                   FlagsContinuation* cont) {
   1557   ArmOperandGenerator g(selector);
   1558   opcode = cont->Encode(opcode);
   1559   if (cont->IsBranch()) {
   1560     selector->Emit(opcode, g.NoOutput(), left, right,
   1561                    g.Label(cont->true_block()), g.Label(cont->false_block()));
   1562   } else if (cont->IsDeoptimize()) {
   1563     selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->kind(),
   1564                              cont->reason(), cont->frame_state());
   1565   } else if (cont->IsSet()) {
   1566     selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right);
   1567   } else {
   1568     DCHECK(cont->IsTrap());
   1569     selector->Emit(opcode, g.NoOutput(), left, right,
   1570                    g.UseImmediate(cont->trap_id()));
   1571   }
   1572 }
   1573 
   1574 
   1575 // Shared routine for multiple float32 compare operations.
   1576 void VisitFloat32Compare(InstructionSelector* selector, Node* node,
   1577                          FlagsContinuation* cont) {
   1578   ArmOperandGenerator g(selector);
   1579   Float32BinopMatcher m(node);
   1580   if (m.right().Is(0.0f)) {
   1581     VisitCompare(selector, kArmVcmpF32, g.UseRegister(m.left().node()),
   1582                  g.UseImmediate(m.right().node()), cont);
   1583   } else if (m.left().Is(0.0f)) {
   1584     cont->Commute();
   1585     VisitCompare(selector, kArmVcmpF32, g.UseRegister(m.right().node()),
   1586                  g.UseImmediate(m.left().node()), cont);
   1587   } else {
   1588     VisitCompare(selector, kArmVcmpF32, g.UseRegister(m.left().node()),
   1589                  g.UseRegister(m.right().node()), cont);
   1590   }
   1591 }
   1592 
   1593 
   1594 // Shared routine for multiple float64 compare operations.
   1595 void VisitFloat64Compare(InstructionSelector* selector, Node* node,
   1596                          FlagsContinuation* cont) {
   1597   ArmOperandGenerator g(selector);
   1598   Float64BinopMatcher m(node);
   1599   if (m.right().Is(0.0)) {
   1600     VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.left().node()),
   1601                  g.UseImmediate(m.right().node()), cont);
   1602   } else if (m.left().Is(0.0)) {
   1603     cont->Commute();
   1604     VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.right().node()),
   1605                  g.UseImmediate(m.left().node()), cont);
   1606   } else {
   1607     VisitCompare(selector, kArmVcmpF64, g.UseRegister(m.left().node()),
   1608                  g.UseRegister(m.right().node()), cont);
   1609   }
   1610 }
   1611 
   1612 // Check whether we can convert:
   1613 // ((a <op> b) cmp 0), b.<cond>
   1614 // to:
   1615 // (a <ops> b), b.<cond'>
   1616 // where <ops> is the flag setting version of <op>.
   1617 // We only generate conditions <cond'> that are a combination of the N
   1618 // and Z flags. This avoids the need to make this function dependent on
   1619 // the flag-setting operation.
   1620 bool CanUseFlagSettingBinop(FlagsCondition cond) {
   1621   switch (cond) {
   1622     case kEqual:
   1623     case kNotEqual:
   1624     case kSignedLessThan:
   1625     case kSignedGreaterThanOrEqual:
   1626     case kUnsignedLessThanOrEqual:  // x <= 0 -> x == 0
   1627     case kUnsignedGreaterThan:      // x > 0 -> x != 0
   1628       return true;
   1629     default:
   1630       return false;
   1631   }
   1632 }
   1633 
   1634 // Map <cond> to <cond'> so that the following transformation is possible:
   1635 // ((a <op> b) cmp 0), b.<cond>
   1636 // to:
   1637 // (a <ops> b), b.<cond'>
   1638 // where <ops> is the flag setting version of <op>.
   1639 FlagsCondition MapForFlagSettingBinop(FlagsCondition cond) {
   1640   DCHECK(CanUseFlagSettingBinop(cond));
   1641   switch (cond) {
   1642     case kEqual:
   1643     case kNotEqual:
   1644       return cond;
   1645     case kSignedLessThan:
   1646       return kNegative;
   1647     case kSignedGreaterThanOrEqual:
   1648       return kPositiveOrZero;
   1649     case kUnsignedLessThanOrEqual:  // x <= 0 -> x == 0
   1650       return kEqual;
   1651     case kUnsignedGreaterThan:  // x > 0 -> x != 0
   1652       return kNotEqual;
   1653     default:
   1654       UNREACHABLE();
   1655       return cond;
   1656   }
   1657 }
   1658 
   1659 // Check if we can perform the transformation:
   1660 // ((a <op> b) cmp 0), b.<cond>
   1661 // to:
   1662 // (a <ops> b), b.<cond'>
   1663 // where <ops> is the flag setting version of <op>, and if so,
   1664 // updates {node}, {opcode} and {cont} accordingly.
   1665 void MaybeReplaceCmpZeroWithFlagSettingBinop(InstructionSelector* selector,
   1666                                              Node** node, Node* binop,
   1667                                              InstructionCode* opcode,
   1668                                              FlagsCondition cond,
   1669                                              FlagsContinuation* cont) {
   1670   InstructionCode binop_opcode;
   1671   InstructionCode no_output_opcode;
   1672   switch (binop->opcode()) {
   1673     case IrOpcode::kInt32Add:
   1674       binop_opcode = kArmAdd;
   1675       no_output_opcode = kArmCmn;
   1676       break;
   1677     case IrOpcode::kWord32And:
   1678       binop_opcode = kArmAnd;
   1679       no_output_opcode = kArmTst;
   1680       break;
   1681     case IrOpcode::kWord32Or:
   1682       binop_opcode = kArmOrr;
   1683       no_output_opcode = kArmOrr;
   1684       break;
   1685     case IrOpcode::kWord32Xor:
   1686       binop_opcode = kArmEor;
   1687       no_output_opcode = kArmTeq;
   1688       break;
   1689     default:
   1690       UNREACHABLE();
   1691       return;
   1692   }
   1693   if (selector->CanCover(*node, binop)) {
   1694     // The comparison is the only user of {node}.
   1695     cont->Overwrite(MapForFlagSettingBinop(cond));
   1696     *opcode = no_output_opcode;
   1697     *node = binop;
   1698   } else if (selector->IsOnlyUserOfNodeInSameBlock(*node, binop)) {
   1699     // We can also handle the case where the {node} and the comparison are in
   1700     // the same basic block, and the comparison is the only user of {node} in
   1701     // this basic block ({node} has users in other basic blocks).
   1702     cont->Overwrite(MapForFlagSettingBinop(cond));
   1703     *opcode = binop_opcode;
   1704     *node = binop;
   1705   }
   1706 }
   1707 
   1708 // Shared routine for multiple word compare operations.
   1709 void VisitWordCompare(InstructionSelector* selector, Node* node,
   1710                       InstructionCode opcode, FlagsContinuation* cont) {
   1711   ArmOperandGenerator g(selector);
   1712   Int32BinopMatcher m(node);
   1713   InstructionOperand inputs[5];
   1714   size_t input_count = 0;
   1715   InstructionOperand outputs[2];
   1716   size_t output_count = 0;
   1717   bool has_result = (opcode != kArmCmp) && (opcode != kArmCmn) &&
   1718                     (opcode != kArmTst) && (opcode != kArmTeq);
   1719 
   1720   if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
   1721                                &input_count, &inputs[1])) {
   1722     inputs[0] = g.UseRegister(m.left().node());
   1723     input_count++;
   1724   } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
   1725                                       &input_count, &inputs[1])) {
   1726     if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
   1727     inputs[0] = g.UseRegister(m.right().node());
   1728     input_count++;
   1729   } else {
   1730     opcode |= AddressingModeField::encode(kMode_Operand2_R);
   1731     inputs[input_count++] = g.UseRegister(m.left().node());
   1732     inputs[input_count++] = g.UseRegister(m.right().node());
   1733   }
   1734 
   1735   if (has_result) {
   1736     if (cont->IsDeoptimize()) {
   1737       // If we can deoptimize as a result of the binop, we need to make sure
   1738       // that the deopt inputs are not overwritten by the binop result. One way
   1739       // to achieve that is to declare the output register as same-as-first.
   1740       outputs[output_count++] = g.DefineSameAsFirst(node);
   1741     } else {
   1742       outputs[output_count++] = g.DefineAsRegister(node);
   1743     }
   1744   }
   1745 
   1746   if (cont->IsBranch()) {
   1747     inputs[input_count++] = g.Label(cont->true_block());
   1748     inputs[input_count++] = g.Label(cont->false_block());
   1749   } else if (cont->IsSet()) {
   1750     outputs[output_count++] = g.DefineAsRegister(cont->result());
   1751   }
   1752 
   1753   DCHECK_NE(0u, input_count);
   1754   DCHECK_GE(arraysize(inputs), input_count);
   1755   DCHECK_GE(arraysize(outputs), output_count);
   1756 
   1757   opcode = cont->Encode(opcode);
   1758   if (cont->IsDeoptimize()) {
   1759     selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
   1760                              cont->kind(), cont->reason(), cont->frame_state());
   1761   } else if (cont->IsTrap()) {
   1762     inputs[input_count++] = g.UseImmediate(cont->trap_id());
   1763     selector->Emit(opcode, output_count, outputs, input_count, inputs);
   1764   } else {
   1765     selector->Emit(opcode, output_count, outputs, input_count, inputs);
   1766   }
   1767 }
   1768 
   1769 
   1770 void VisitWordCompare(InstructionSelector* selector, Node* node,
   1771                       FlagsContinuation* cont) {
   1772   InstructionCode opcode = kArmCmp;
   1773   Int32BinopMatcher m(node);
   1774 
   1775   FlagsCondition cond = cont->condition();
   1776   if (m.right().Is(0) && (m.left().IsInt32Add() || m.left().IsWord32Or() ||
   1777                           m.left().IsWord32And() || m.left().IsWord32Xor())) {
   1778     // Emit flag setting instructions for comparisons against zero.
   1779     if (CanUseFlagSettingBinop(cond)) {
   1780       Node* binop = m.left().node();
   1781       MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode,
   1782                                               cond, cont);
   1783     }
   1784   } else if (m.left().Is(0) &&
   1785              (m.right().IsInt32Add() || m.right().IsWord32Or() ||
   1786               m.right().IsWord32And() || m.right().IsWord32Xor())) {
   1787     // Same as above, but we need to commute the condition before we
   1788     // continue with the rest of the checks.
   1789     cond = CommuteFlagsCondition(cond);
   1790     if (CanUseFlagSettingBinop(cond)) {
   1791       Node* binop = m.right().node();
   1792       MaybeReplaceCmpZeroWithFlagSettingBinop(selector, &node, binop, &opcode,
   1793                                               cond, cont);
   1794     }
   1795   }
   1796 
   1797   VisitWordCompare(selector, node, opcode, cont);
   1798 }
   1799 
   1800 
   1801 // Shared routine for word comparisons against zero.
   1802 void VisitWordCompareZero(InstructionSelector* selector, Node* user,
   1803                           Node* value, FlagsContinuation* cont) {
   1804   // Try to combine with comparisons against 0 by simply inverting the branch.
   1805   while (value->opcode() == IrOpcode::kWord32Equal &&
   1806          selector->CanCover(user, value)) {
   1807     Int32BinopMatcher m(value);
   1808     if (!m.right().Is(0)) break;
   1809 
   1810     user = value;
   1811     value = m.left().node();
   1812     cont->Negate();
   1813   }
   1814 
   1815   if (selector->CanCover(user, value)) {
   1816     switch (value->opcode()) {
   1817       case IrOpcode::kWord32Equal:
   1818         cont->OverwriteAndNegateIfEqual(kEqual);
   1819         return VisitWordCompare(selector, value, cont);
   1820       case IrOpcode::kInt32LessThan:
   1821         cont->OverwriteAndNegateIfEqual(kSignedLessThan);
   1822         return VisitWordCompare(selector, value, cont);
   1823       case IrOpcode::kInt32LessThanOrEqual:
   1824         cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
   1825         return VisitWordCompare(selector, value, cont);
   1826       case IrOpcode::kUint32LessThan:
   1827         cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
   1828         return VisitWordCompare(selector, value, cont);
   1829       case IrOpcode::kUint32LessThanOrEqual:
   1830         cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
   1831         return VisitWordCompare(selector, value, cont);
   1832       case IrOpcode::kFloat32Equal:
   1833         cont->OverwriteAndNegateIfEqual(kEqual);
   1834         return VisitFloat32Compare(selector, value, cont);
   1835       case IrOpcode::kFloat32LessThan:
   1836         cont->OverwriteAndNegateIfEqual(kFloatLessThan);
   1837         return VisitFloat32Compare(selector, value, cont);
   1838       case IrOpcode::kFloat32LessThanOrEqual:
   1839         cont->OverwriteAndNegateIfEqual(kFloatLessThanOrEqual);
   1840         return VisitFloat32Compare(selector, value, cont);
   1841       case IrOpcode::kFloat64Equal:
   1842         cont->OverwriteAndNegateIfEqual(kEqual);
   1843         return VisitFloat64Compare(selector, value, cont);
   1844       case IrOpcode::kFloat64LessThan:
   1845         cont->OverwriteAndNegateIfEqual(kFloatLessThan);
   1846         return VisitFloat64Compare(selector, value, cont);
   1847       case IrOpcode::kFloat64LessThanOrEqual:
   1848         cont->OverwriteAndNegateIfEqual(kFloatLessThanOrEqual);
   1849         return VisitFloat64Compare(selector, value, cont);
   1850       case IrOpcode::kProjection:
   1851         // Check if this is the overflow output projection of an
   1852         // <Operation>WithOverflow node.
   1853         if (ProjectionIndexOf(value->op()) == 1u) {
   1854           // We cannot combine the <Operation>WithOverflow with this branch
   1855           // unless the 0th projection (the use of the actual value of the
   1856           // <Operation> is either nullptr, which means there's no use of the
   1857           // actual value, or was already defined, which means it is scheduled
   1858           // *AFTER* this branch).
   1859           Node* const node = value->InputAt(0);
   1860           Node* const result = NodeProperties::FindProjection(node, 0);
   1861           if (!result || selector->IsDefined(result)) {
   1862             switch (node->opcode()) {
   1863               case IrOpcode::kInt32AddWithOverflow:
   1864                 cont->OverwriteAndNegateIfEqual(kOverflow);
   1865                 return VisitBinop(selector, node, kArmAdd, kArmAdd, cont);
   1866               case IrOpcode::kInt32SubWithOverflow:
   1867                 cont->OverwriteAndNegateIfEqual(kOverflow);
   1868                 return VisitBinop(selector, node, kArmSub, kArmRsb, cont);
   1869               case IrOpcode::kInt32MulWithOverflow:
   1870                 // ARM doesn't set the overflow flag for multiplication, so we
   1871                 // need to test on kNotEqual. Here is the code sequence used:
   1872                 //   smull resultlow, resulthigh, left, right
   1873                 //   cmp resulthigh, Operand(resultlow, ASR, 31)
   1874                 cont->OverwriteAndNegateIfEqual(kNotEqual);
   1875                 return EmitInt32MulWithOverflow(selector, node, cont);
   1876               default:
   1877                 break;
   1878             }
   1879           }
   1880         }
   1881         break;
   1882       case IrOpcode::kInt32Add:
   1883         return VisitWordCompare(selector, value, kArmCmn, cont);
   1884       case IrOpcode::kInt32Sub:
   1885         return VisitWordCompare(selector, value, kArmCmp, cont);
   1886       case IrOpcode::kWord32And:
   1887         return VisitWordCompare(selector, value, kArmTst, cont);
   1888       case IrOpcode::kWord32Or:
   1889         return VisitBinop(selector, value, kArmOrr, kArmOrr, cont);
   1890       case IrOpcode::kWord32Xor:
   1891         return VisitWordCompare(selector, value, kArmTeq, cont);
   1892       case IrOpcode::kWord32Sar:
   1893         return VisitShift(selector, value, TryMatchASR, cont);
   1894       case IrOpcode::kWord32Shl:
   1895         return VisitShift(selector, value, TryMatchLSL, cont);
   1896       case IrOpcode::kWord32Shr:
   1897         return VisitShift(selector, value, TryMatchLSR, cont);
   1898       case IrOpcode::kWord32Ror:
   1899         return VisitShift(selector, value, TryMatchROR, cont);
   1900       default:
   1901         break;
   1902     }
   1903   }
   1904 
   1905   if (user->opcode() == IrOpcode::kWord32Equal) {
   1906     return VisitWordCompare(selector, user, cont);
   1907   }
   1908 
   1909   // Continuation could not be combined with a compare, emit compare against 0.
   1910   ArmOperandGenerator g(selector);
   1911   InstructionCode const opcode =
   1912       cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
   1913   InstructionOperand const value_operand = g.UseRegister(value);
   1914   if (cont->IsBranch()) {
   1915     selector->Emit(opcode, g.NoOutput(), value_operand, value_operand,
   1916                    g.Label(cont->true_block()), g.Label(cont->false_block()));
   1917   } else if (cont->IsDeoptimize()) {
   1918     selector->EmitDeoptimize(opcode, g.NoOutput(), value_operand, value_operand,
   1919                              cont->kind(), cont->reason(), cont->frame_state());
   1920   } else if (cont->IsSet()) {
   1921     selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand,
   1922                    value_operand);
   1923   } else {
   1924     DCHECK(cont->IsTrap());
   1925     selector->Emit(opcode, g.NoOutput(), value_operand, value_operand,
   1926                    g.UseImmediate(cont->trap_id()));
   1927   }
   1928 }
   1929 
   1930 }  // namespace
   1931 
   1932 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
   1933                                       BasicBlock* fbranch) {
   1934   FlagsContinuation cont(kNotEqual, tbranch, fbranch);
   1935   VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
   1936 }
   1937 
   1938 void InstructionSelector::VisitDeoptimizeIf(Node* node) {
   1939   DeoptimizeParameters p = DeoptimizeParametersOf(node->op());
   1940   FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
   1941       kNotEqual, p.kind(), p.reason(), node->InputAt(1));
   1942   VisitWordCompareZero(this, node, node->InputAt(0), &cont);
   1943 }
   1944 
   1945 void InstructionSelector::VisitDeoptimizeUnless(Node* node) {
   1946   DeoptimizeParameters p = DeoptimizeParametersOf(node->op());
   1947   FlagsContinuation cont = FlagsContinuation::ForDeoptimize(
   1948       kEqual, p.kind(), p.reason(), node->InputAt(1));
   1949   VisitWordCompareZero(this, node, node->InputAt(0), &cont);
   1950 }
   1951 
   1952 void InstructionSelector::VisitTrapIf(Node* node, Runtime::FunctionId func_id) {
   1953   FlagsContinuation cont =
   1954       FlagsContinuation::ForTrap(kNotEqual, func_id, node->InputAt(1));
   1955   VisitWordCompareZero(this, node, node->InputAt(0), &cont);
   1956 }
   1957 
   1958 void InstructionSelector::VisitTrapUnless(Node* node,
   1959                                           Runtime::FunctionId func_id) {
   1960   FlagsContinuation cont =
   1961       FlagsContinuation::ForTrap(kEqual, func_id, node->InputAt(1));
   1962   VisitWordCompareZero(this, node, node->InputAt(0), &cont);
   1963 }
   1964 
   1965 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
   1966   ArmOperandGenerator g(this);
   1967   InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
   1968 
   1969   // Emit either ArchTableSwitch or ArchLookupSwitch.
   1970   size_t table_space_cost = 4 + sw.value_range;
   1971   size_t table_time_cost = 3;
   1972   size_t lookup_space_cost = 3 + 2 * sw.case_count;
   1973   size_t lookup_time_cost = sw.case_count;
   1974   if (sw.case_count > 0 &&
   1975       table_space_cost + 3 * table_time_cost <=
   1976           lookup_space_cost + 3 * lookup_time_cost &&
   1977       sw.min_value > std::numeric_limits<int32_t>::min()) {
   1978     InstructionOperand index_operand = value_operand;
   1979     if (sw.min_value) {
   1980       index_operand = g.TempRegister();
   1981       Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_I),
   1982            index_operand, value_operand, g.TempImmediate(sw.min_value));
   1983     }
   1984     // Generate a table lookup.
   1985     return EmitTableSwitch(sw, index_operand);
   1986   }
   1987 
   1988   // Generate a sequence of conditional jumps.
   1989   return EmitLookupSwitch(sw, value_operand);
   1990 }
   1991 
   1992 
   1993 void InstructionSelector::VisitWord32Equal(Node* const node) {
   1994   FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
   1995   Int32BinopMatcher m(node);
   1996   if (m.right().Is(0)) {
   1997     return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
   1998   }
   1999   VisitWordCompare(this, node, &cont);
   2000 }
   2001 
   2002 
   2003 void InstructionSelector::VisitInt32LessThan(Node* node) {
   2004   FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
   2005   VisitWordCompare(this, node, &cont);
   2006 }
   2007 
   2008 
   2009 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
   2010   FlagsContinuation cont =
   2011       FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
   2012   VisitWordCompare(this, node, &cont);
   2013 }
   2014 
   2015 
   2016 void InstructionSelector::VisitUint32LessThan(Node* node) {
   2017   FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
   2018   VisitWordCompare(this, node, &cont);
   2019 }
   2020 
   2021 
   2022 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
   2023   FlagsContinuation cont =
   2024       FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
   2025   VisitWordCompare(this, node, &cont);
   2026 }
   2027 
   2028 
   2029 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
   2030   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
   2031     FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
   2032     return VisitBinop(this, node, kArmAdd, kArmAdd, &cont);
   2033   }
   2034   FlagsContinuation cont;
   2035   VisitBinop(this, node, kArmAdd, kArmAdd, &cont);
   2036 }
   2037 
   2038 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
   2039   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
   2040     FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
   2041     return VisitBinop(this, node, kArmSub, kArmRsb, &cont);
   2042   }
   2043   FlagsContinuation cont;
   2044   VisitBinop(this, node, kArmSub, kArmRsb, &cont);
   2045 }
   2046 
   2047 void InstructionSelector::VisitInt32MulWithOverflow(Node* node) {
   2048   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
   2049     // ARM doesn't set the overflow flag for multiplication, so we need to test
   2050     // on kNotEqual. Here is the code sequence used:
   2051     //   smull resultlow, resulthigh, left, right
   2052     //   cmp resulthigh, Operand(resultlow, ASR, 31)
   2053     FlagsContinuation cont = FlagsContinuation::ForSet(kNotEqual, ovf);
   2054     return EmitInt32MulWithOverflow(this, node, &cont);
   2055   }
   2056   FlagsContinuation cont;
   2057   EmitInt32MulWithOverflow(this, node, &cont);
   2058 }
   2059 
   2060 void InstructionSelector::VisitFloat32Equal(Node* node) {
   2061   FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
   2062   VisitFloat32Compare(this, node, &cont);
   2063 }
   2064 
   2065 
   2066 void InstructionSelector::VisitFloat32LessThan(Node* node) {
   2067   FlagsContinuation cont = FlagsContinuation::ForSet(kFloatLessThan, node);
   2068   VisitFloat32Compare(this, node, &cont);
   2069 }
   2070 
   2071 
   2072 void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) {
   2073   FlagsContinuation cont =
   2074       FlagsContinuation::ForSet(kFloatLessThanOrEqual, node);
   2075   VisitFloat32Compare(this, node, &cont);
   2076 }
   2077 
   2078 
   2079 void InstructionSelector::VisitFloat64Equal(Node* node) {
   2080   FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
   2081   VisitFloat64Compare(this, node, &cont);
   2082 }
   2083 
   2084 
   2085 void InstructionSelector::VisitFloat64LessThan(Node* node) {
   2086   FlagsContinuation cont = FlagsContinuation::ForSet(kFloatLessThan, node);
   2087   VisitFloat64Compare(this, node, &cont);
   2088 }
   2089 
   2090 
   2091 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
   2092   FlagsContinuation cont =
   2093       FlagsContinuation::ForSet(kFloatLessThanOrEqual, node);
   2094   VisitFloat64Compare(this, node, &cont);
   2095 }
   2096 
   2097 void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) {
   2098   ArmOperandGenerator g(this);
   2099   Node* left = node->InputAt(0);
   2100   Node* right = node->InputAt(1);
   2101   if (left->opcode() == IrOpcode::kFloat64InsertHighWord32 &&
   2102       CanCover(node, left)) {
   2103     left = left->InputAt(1);
   2104     Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), g.UseRegister(right),
   2105          g.UseRegister(left));
   2106     return;
   2107   }
   2108   Emit(kArmVmovLowF64U32, g.DefineSameAsFirst(node), g.UseRegister(left),
   2109        g.UseRegister(right));
   2110 }
   2111 
   2112 
   2113 void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) {
   2114   ArmOperandGenerator g(this);
   2115   Node* left = node->InputAt(0);
   2116   Node* right = node->InputAt(1);
   2117   if (left->opcode() == IrOpcode::kFloat64InsertLowWord32 &&
   2118       CanCover(node, left)) {
   2119     left = left->InputAt(1);
   2120     Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), g.UseRegister(left),
   2121          g.UseRegister(right));
   2122     return;
   2123   }
   2124   Emit(kArmVmovHighF64U32, g.DefineSameAsFirst(node), g.UseRegister(left),
   2125        g.UseRegister(right));
   2126 }
   2127 
   2128 void InstructionSelector::VisitAtomicLoad(Node* node) {
   2129   LoadRepresentation load_rep = LoadRepresentationOf(node->op());
   2130   ArmOperandGenerator g(this);
   2131   Node* base = node->InputAt(0);
   2132   Node* index = node->InputAt(1);
   2133   ArchOpcode opcode = kArchNop;
   2134   switch (load_rep.representation()) {
   2135     case MachineRepresentation::kWord8:
   2136       opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
   2137       break;
   2138     case MachineRepresentation::kWord16:
   2139       opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
   2140       break;
   2141     case MachineRepresentation::kWord32:
   2142       opcode = kAtomicLoadWord32;
   2143       break;
   2144     default:
   2145       UNREACHABLE();
   2146       return;
   2147   }
   2148   Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
   2149        g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
   2150 }
   2151 
   2152 void InstructionSelector::VisitAtomicStore(Node* node) {
   2153   MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
   2154   ArmOperandGenerator g(this);
   2155   Node* base = node->InputAt(0);
   2156   Node* index = node->InputAt(1);
   2157   Node* value = node->InputAt(2);
   2158   ArchOpcode opcode = kArchNop;
   2159   switch (rep) {
   2160     case MachineRepresentation::kWord8:
   2161       opcode = kAtomicStoreWord8;
   2162       break;
   2163     case MachineRepresentation::kWord16:
   2164       opcode = kAtomicStoreWord16;
   2165       break;
   2166     case MachineRepresentation::kWord32:
   2167       opcode = kAtomicStoreWord32;
   2168       break;
   2169     default:
   2170       UNREACHABLE();
   2171       return;
   2172   }
   2173 
   2174   AddressingMode addressing_mode = kMode_Offset_RR;
   2175   InstructionOperand inputs[4];
   2176   size_t input_count = 0;
   2177   inputs[input_count++] = g.UseUniqueRegister(base);
   2178   inputs[input_count++] = g.UseUniqueRegister(index);
   2179   inputs[input_count++] = g.UseUniqueRegister(value);
   2180   InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
   2181   Emit(code, 0, nullptr, input_count, inputs);
   2182 }
   2183 
   2184 #define SIMD_TYPE_LIST(V) \
   2185   V(Float32x4)            \
   2186   V(Int32x4)              \
   2187   V(Int16x8)              \
   2188   V(Int8x16)
   2189 
   2190 #define SIMD_FORMAT_LIST(V) \
   2191   V(32x4)                   \
   2192   V(16x8)                   \
   2193   V(8x16)
   2194 
   2195 #define SIMD_UNOP_LIST(V)  \
   2196   V(Float32x4FromInt32x4)  \
   2197   V(Float32x4FromUint32x4) \
   2198   V(Float32x4Abs)          \
   2199   V(Float32x4Neg)          \
   2200   V(Int32x4FromFloat32x4)  \
   2201   V(Uint32x4FromFloat32x4) \
   2202   V(Int32x4Neg)            \
   2203   V(Int16x8Neg)            \
   2204   V(Int8x16Neg)            \
   2205   V(Simd128Not)
   2206 
   2207 #define SIMD_BINOP_LIST(V)      \
   2208   V(Float32x4Add)               \
   2209   V(Float32x4Sub)               \
   2210   V(Float32x4Equal)             \
   2211   V(Float32x4NotEqual)          \
   2212   V(Int32x4Add)                 \
   2213   V(Int32x4Sub)                 \
   2214   V(Int32x4Mul)                 \
   2215   V(Int32x4Min)                 \
   2216   V(Int32x4Max)                 \
   2217   V(Int32x4Equal)               \
   2218   V(Int32x4NotEqual)            \
   2219   V(Int32x4GreaterThan)         \
   2220   V(Int32x4GreaterThanOrEqual)  \
   2221   V(Uint32x4Min)                \
   2222   V(Uint32x4Max)                \
   2223   V(Uint32x4GreaterThan)        \
   2224   V(Uint32x4GreaterThanOrEqual) \
   2225   V(Int16x8Add)                 \
   2226   V(Int16x8AddSaturate)         \
   2227   V(Int16x8Sub)                 \
   2228   V(Int16x8SubSaturate)         \
   2229   V(Int16x8Mul)                 \
   2230   V(Int16x8Min)                 \
   2231   V(Int16x8Max)                 \
   2232   V(Int16x8Equal)               \
   2233   V(Int16x8NotEqual)            \
   2234   V(Int16x8GreaterThan)         \
   2235   V(Int16x8GreaterThanOrEqual)  \
   2236   V(Uint16x8AddSaturate)        \
   2237   V(Uint16x8SubSaturate)        \
   2238   V(Uint16x8Min)                \
   2239   V(Uint16x8Max)                \
   2240   V(Uint16x8GreaterThan)        \
   2241   V(Uint16x8GreaterThanOrEqual) \
   2242   V(Int8x16Add)                 \
   2243   V(Int8x16AddSaturate)         \
   2244   V(Int8x16Sub)                 \
   2245   V(Int8x16SubSaturate)         \
   2246   V(Int8x16Mul)                 \
   2247   V(Int8x16Min)                 \
   2248   V(Int8x16Max)                 \
   2249   V(Int8x16Equal)               \
   2250   V(Int8x16NotEqual)            \
   2251   V(Int8x16GreaterThan)         \
   2252   V(Int8x16GreaterThanOrEqual)  \
   2253   V(Uint8x16AddSaturate)        \
   2254   V(Uint8x16SubSaturate)        \
   2255   V(Uint8x16Min)                \
   2256   V(Uint8x16Max)                \
   2257   V(Uint8x16GreaterThan)        \
   2258   V(Uint8x16GreaterThanOrEqual) \
   2259   V(Simd128And)                 \
   2260   V(Simd128Or)                  \
   2261   V(Simd128Xor)
   2262 
   2263 #define SIMD_SHIFT_OP_LIST(V)   \
   2264   V(Int32x4ShiftLeftByScalar)   \
   2265   V(Int32x4ShiftRightByScalar)  \
   2266   V(Uint32x4ShiftRightByScalar) \
   2267   V(Int16x8ShiftLeftByScalar)   \
   2268   V(Int16x8ShiftRightByScalar)  \
   2269   V(Uint16x8ShiftRightByScalar) \
   2270   V(Int8x16ShiftLeftByScalar)   \
   2271   V(Int8x16ShiftRightByScalar)  \
   2272   V(Uint8x16ShiftRightByScalar)
   2273 
   2274 #define SIMD_VISIT_SPLAT(Type)                              \
   2275   void InstructionSelector::VisitCreate##Type(Node* node) { \
   2276     VisitRR(this, kArm##Type##Splat, node);                 \
   2277   }
   2278 SIMD_TYPE_LIST(SIMD_VISIT_SPLAT)
   2279 #undef SIMD_VISIT_SPLAT
   2280 
   2281 #define SIMD_VISIT_EXTRACT_LANE(Type)                              \
   2282   void InstructionSelector::Visit##Type##ExtractLane(Node* node) { \
   2283     VisitRRI(this, kArm##Type##ExtractLane, node);                 \
   2284   }
   2285 SIMD_TYPE_LIST(SIMD_VISIT_EXTRACT_LANE)
   2286 #undef SIMD_VISIT_EXTRACT_LANE
   2287 
   2288 #define SIMD_VISIT_REPLACE_LANE(Type)                              \
   2289   void InstructionSelector::Visit##Type##ReplaceLane(Node* node) { \
   2290     VisitRRIR(this, kArm##Type##ReplaceLane, node);                \
   2291   }
   2292 SIMD_TYPE_LIST(SIMD_VISIT_REPLACE_LANE)
   2293 #undef SIMD_VISIT_REPLACE_LANE
   2294 
   2295 #define SIMD_VISIT_UNOP(Name)                         \
   2296   void InstructionSelector::Visit##Name(Node* node) { \
   2297     VisitRR(this, kArm##Name, node);                  \
   2298   }
   2299 SIMD_UNOP_LIST(SIMD_VISIT_UNOP)
   2300 #undef SIMD_VISIT_UNOP
   2301 
   2302 #define SIMD_VISIT_BINOP(Name)                        \
   2303   void InstructionSelector::Visit##Name(Node* node) { \
   2304     VisitRRR(this, kArm##Name, node);                 \
   2305   }
   2306 SIMD_BINOP_LIST(SIMD_VISIT_BINOP)
   2307 #undef SIMD_VISIT_BINOP
   2308 
   2309 #define SIMD_VISIT_SHIFT_OP(Name)                     \
   2310   void InstructionSelector::Visit##Name(Node* node) { \
   2311     VisitRRI(this, kArm##Name, node);                 \
   2312   }
   2313 SIMD_SHIFT_OP_LIST(SIMD_VISIT_SHIFT_OP)
   2314 #undef SIMD_VISIT_SHIFT_OP
   2315 
   2316 #define SIMD_VISIT_SELECT_OP(format)                                \
   2317   void InstructionSelector::VisitSimd##format##Select(Node* node) { \
   2318     VisitRRRR(this, kArmSimd##format##Select, node);                \
   2319   }
   2320 SIMD_FORMAT_LIST(SIMD_VISIT_SELECT_OP)
   2321 #undef SIMD_VISIT_SELECT_OP
   2322 
   2323 // static
   2324 MachineOperatorBuilder::Flags
   2325 InstructionSelector::SupportedMachineOperatorFlags() {
   2326   MachineOperatorBuilder::Flags flags;
   2327   if (CpuFeatures::IsSupported(SUDIV)) {
   2328     // The sdiv and udiv instructions correctly return 0 if the divisor is 0,
   2329     // but the fall-back implementation does not.
   2330     flags |= MachineOperatorBuilder::kInt32DivIsSafe |
   2331              MachineOperatorBuilder::kUint32DivIsSafe;
   2332   }
   2333   if (CpuFeatures::IsSupported(ARMv7)) {
   2334     flags |= MachineOperatorBuilder::kWord32ReverseBits;
   2335   }
   2336   if (CpuFeatures::IsSupported(ARMv8)) {
   2337     flags |= MachineOperatorBuilder::kFloat32RoundDown |
   2338              MachineOperatorBuilder::kFloat64RoundDown |
   2339              MachineOperatorBuilder::kFloat32RoundUp |
   2340              MachineOperatorBuilder::kFloat64RoundUp |
   2341              MachineOperatorBuilder::kFloat32RoundTruncate |
   2342              MachineOperatorBuilder::kFloat64RoundTruncate |
   2343              MachineOperatorBuilder::kFloat64RoundTiesAway |
   2344              MachineOperatorBuilder::kFloat32RoundTiesEven |
   2345              MachineOperatorBuilder::kFloat64RoundTiesEven;
   2346   }
   2347   return flags;
   2348 }
   2349 
   2350 // static
   2351 MachineOperatorBuilder::AlignmentRequirements
   2352 InstructionSelector::AlignmentRequirements() {
   2353   Vector<MachineType> req_aligned = Vector<MachineType>::New(2);
   2354   req_aligned[0] = MachineType::Float32();
   2355   req_aligned[1] = MachineType::Float64();
   2356   return MachineOperatorBuilder::AlignmentRequirements::
   2357       SomeUnalignedAccessUnsupported(req_aligned, req_aligned);
   2358 }
   2359 
   2360 }  // namespace compiler
   2361 }  // namespace internal
   2362 }  // namespace v8
   2363