deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / compiler / x64 / instruction-selector-x64.cc
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 <algorithm>
6
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 X64-specific methods for generating operands.
16 class X64OperandGenerator FINAL : public OperandGenerator {
17  public:
18   explicit X64OperandGenerator(InstructionSelector* selector)
19       : OperandGenerator(selector) {}
20
21   bool CanBeImmediate(Node* node) {
22     switch (node->opcode()) {
23       case IrOpcode::kInt32Constant:
24         return true;
25       case IrOpcode::kInt64Constant: {
26         const int64_t value = OpParameter<int64_t>(node);
27         return value == static_cast<int64_t>(static_cast<int32_t>(value));
28       }
29       default:
30         return false;
31     }
32   }
33
34   AddressingMode GenerateMemoryOperandInputs(Node* index, int scale_exponent,
35                                              Node* base, Node* displacement,
36                                              InstructionOperand inputs[],
37                                              size_t* input_count) {
38     AddressingMode mode = kMode_MRI;
39     if (base != NULL) {
40       inputs[(*input_count)++] = UseRegister(base);
41       if (index != NULL) {
42         DCHECK(scale_exponent >= 0 && scale_exponent <= 3);
43         inputs[(*input_count)++] = UseRegister(index);
44         if (displacement != NULL) {
45           inputs[(*input_count)++] = UseImmediate(displacement);
46           static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I,
47                                                        kMode_MR4I, kMode_MR8I};
48           mode = kMRnI_modes[scale_exponent];
49         } else {
50           static const AddressingMode kMRn_modes[] = {kMode_MR1, kMode_MR2,
51                                                       kMode_MR4, kMode_MR8};
52           mode = kMRn_modes[scale_exponent];
53         }
54       } else {
55         if (displacement == NULL) {
56           mode = kMode_MR;
57         } else {
58           inputs[(*input_count)++] = UseImmediate(displacement);
59           mode = kMode_MRI;
60         }
61       }
62     } else {
63       DCHECK(index != NULL);
64       DCHECK(scale_exponent >= 0 && scale_exponent <= 3);
65       inputs[(*input_count)++] = UseRegister(index);
66       if (displacement != NULL) {
67         inputs[(*input_count)++] = UseImmediate(displacement);
68         static const AddressingMode kMnI_modes[] = {kMode_MRI, kMode_M2I,
69                                                     kMode_M4I, kMode_M8I};
70         mode = kMnI_modes[scale_exponent];
71       } else {
72         static const AddressingMode kMn_modes[] = {kMode_MR, kMode_MR1,
73                                                    kMode_M4, kMode_M8};
74         mode = kMn_modes[scale_exponent];
75         if (mode == kMode_MR1) {
76           // [%r1 + %r1*1] has a smaller encoding than [%r1*2+0]
77           inputs[(*input_count)++] = UseRegister(index);
78         }
79       }
80     }
81     return mode;
82   }
83
84   AddressingMode GetEffectiveAddressMemoryOperand(Node* operand,
85                                                   InstructionOperand inputs[],
86                                                   size_t* input_count) {
87     BaseWithIndexAndDisplacement64Matcher m(operand, true);
88     DCHECK(m.matches());
89     if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) {
90       return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(),
91                                          m.displacement(), inputs, input_count);
92     } else {
93       inputs[(*input_count)++] = UseRegister(operand->InputAt(0));
94       inputs[(*input_count)++] = UseRegister(operand->InputAt(1));
95       return kMode_MR1;
96     }
97   }
98
99   bool CanBeBetterLeftOperand(Node* node) const {
100     return !selector()->IsLive(node);
101   }
102 };
103
104
105 void InstructionSelector::VisitLoad(Node* node) {
106   MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
107   MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
108   X64OperandGenerator g(this);
109
110   ArchOpcode opcode;
111   switch (rep) {
112     case kRepFloat32:
113       opcode = kX64Movss;
114       break;
115     case kRepFloat64:
116       opcode = kX64Movsd;
117       break;
118     case kRepBit:  // Fall through.
119     case kRepWord8:
120       opcode = typ == kTypeInt32 ? kX64Movsxbl : kX64Movzxbl;
121       break;
122     case kRepWord16:
123       opcode = typ == kTypeInt32 ? kX64Movsxwl : kX64Movzxwl;
124       break;
125     case kRepWord32:
126       opcode = kX64Movl;
127       break;
128     case kRepTagged:  // Fall through.
129     case kRepWord64:
130       opcode = kX64Movq;
131       break;
132     default:
133       UNREACHABLE();
134       return;
135   }
136
137   InstructionOperand outputs[1];
138   outputs[0] = g.DefineAsRegister(node);
139   InstructionOperand inputs[3];
140   size_t input_count = 0;
141   AddressingMode mode =
142       g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
143   InstructionCode code = opcode | AddressingModeField::encode(mode);
144   Emit(code, 1, outputs, input_count, inputs);
145 }
146
147
148 void InstructionSelector::VisitStore(Node* node) {
149   X64OperandGenerator g(this);
150   Node* base = node->InputAt(0);
151   Node* index = node->InputAt(1);
152   Node* value = node->InputAt(2);
153
154   StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
155   MachineType rep = RepresentationOf(store_rep.machine_type());
156   if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
157     DCHECK(rep == kRepTagged);
158     // TODO(dcarney): refactor RecordWrite function to take temp registers
159     //                and pass them here instead of using fixed regs
160     // TODO(dcarney): handle immediate indices.
161     InstructionOperand temps[] = {g.TempRegister(rcx), g.TempRegister(rdx)};
162     Emit(kX64StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, rbx),
163          g.UseFixed(index, rcx), g.UseFixed(value, rdx), arraysize(temps),
164          temps);
165     return;
166   }
167   DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
168   ArchOpcode opcode;
169   switch (rep) {
170     case kRepFloat32:
171       opcode = kX64Movss;
172       break;
173     case kRepFloat64:
174       opcode = kX64Movsd;
175       break;
176     case kRepBit:  // Fall through.
177     case kRepWord8:
178       opcode = kX64Movb;
179       break;
180     case kRepWord16:
181       opcode = kX64Movw;
182       break;
183     case kRepWord32:
184       opcode = kX64Movl;
185       break;
186     case kRepTagged:  // Fall through.
187     case kRepWord64:
188       opcode = kX64Movq;
189       break;
190     default:
191       UNREACHABLE();
192       return;
193   }
194   InstructionOperand inputs[4];
195   size_t input_count = 0;
196   AddressingMode mode =
197       g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
198   InstructionCode code = opcode | AddressingModeField::encode(mode);
199   InstructionOperand value_operand =
200       g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value);
201   inputs[input_count++] = value_operand;
202   Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs);
203 }
204
205
206 void InstructionSelector::VisitCheckedLoad(Node* node) {
207   MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
208   MachineType typ = TypeOf(OpParameter<MachineType>(node));
209   X64OperandGenerator g(this);
210   Node* const buffer = node->InputAt(0);
211   Node* const offset = node->InputAt(1);
212   Node* const length = node->InputAt(2);
213   ArchOpcode opcode;
214   switch (rep) {
215     case kRepWord8:
216       opcode = typ == kTypeInt32 ? kCheckedLoadInt8 : kCheckedLoadUint8;
217       break;
218     case kRepWord16:
219       opcode = typ == kTypeInt32 ? kCheckedLoadInt16 : kCheckedLoadUint16;
220       break;
221     case kRepWord32:
222       opcode = kCheckedLoadWord32;
223       break;
224     case kRepFloat32:
225       opcode = kCheckedLoadFloat32;
226       break;
227     case kRepFloat64:
228       opcode = kCheckedLoadFloat64;
229       break;
230     default:
231       UNREACHABLE();
232       return;
233   }
234   if (offset->opcode() == IrOpcode::kInt32Add && CanCover(node, offset)) {
235     Int32Matcher mlength(length);
236     Int32BinopMatcher moffset(offset);
237     if (mlength.HasValue() && moffset.right().HasValue() &&
238         moffset.right().Value() >= 0 &&
239         mlength.Value() >= moffset.right().Value()) {
240       Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer),
241            g.UseRegister(moffset.left().node()),
242            g.UseImmediate(moffset.right().node()), g.UseImmediate(length));
243       return;
244     }
245   }
246   InstructionOperand length_operand =
247       g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
248   Emit(opcode, g.DefineAsRegister(node), g.UseRegister(buffer),
249        g.UseRegister(offset), g.TempImmediate(0), length_operand);
250 }
251
252
253 void InstructionSelector::VisitCheckedStore(Node* node) {
254   MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
255   X64OperandGenerator g(this);
256   Node* const buffer = node->InputAt(0);
257   Node* const offset = node->InputAt(1);
258   Node* const length = node->InputAt(2);
259   Node* const value = node->InputAt(3);
260   ArchOpcode opcode;
261   switch (rep) {
262     case kRepWord8:
263       opcode = kCheckedStoreWord8;
264       break;
265     case kRepWord16:
266       opcode = kCheckedStoreWord16;
267       break;
268     case kRepWord32:
269       opcode = kCheckedStoreWord32;
270       break;
271     case kRepFloat32:
272       opcode = kCheckedStoreFloat32;
273       break;
274     case kRepFloat64:
275       opcode = kCheckedStoreFloat64;
276       break;
277     default:
278       UNREACHABLE();
279       return;
280   }
281   InstructionOperand value_operand =
282       g.CanBeImmediate(value) ? g.UseImmediate(value) : g.UseRegister(value);
283   if (offset->opcode() == IrOpcode::kInt32Add && CanCover(node, offset)) {
284     Int32Matcher mlength(length);
285     Int32BinopMatcher moffset(offset);
286     if (mlength.HasValue() && moffset.right().HasValue() &&
287         moffset.right().Value() >= 0 &&
288         mlength.Value() >= moffset.right().Value()) {
289       Emit(opcode, g.NoOutput(), g.UseRegister(buffer),
290            g.UseRegister(moffset.left().node()),
291            g.UseImmediate(moffset.right().node()), g.UseImmediate(length),
292            value_operand);
293       return;
294     }
295   }
296   InstructionOperand length_operand =
297       g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
298   Emit(opcode, g.NoOutput(), g.UseRegister(buffer), g.UseRegister(offset),
299        g.TempImmediate(0), length_operand, value_operand);
300 }
301
302
303 // Shared routine for multiple binary operations.
304 static void VisitBinop(InstructionSelector* selector, Node* node,
305                        InstructionCode opcode, FlagsContinuation* cont) {
306   X64OperandGenerator g(selector);
307   Int32BinopMatcher m(node);
308   Node* left = m.left().node();
309   Node* right = m.right().node();
310   InstructionOperand inputs[4];
311   size_t input_count = 0;
312   InstructionOperand outputs[2];
313   size_t output_count = 0;
314
315   // TODO(turbofan): match complex addressing modes.
316   if (left == right) {
317     // If both inputs refer to the same operand, enforce allocating a register
318     // for both of them to ensure that we don't end up generating code like
319     // this:
320     //
321     //   mov rax, [rbp-0x10]
322     //   add rax, [rbp-0x10]
323     //   jo label
324     InstructionOperand const input = g.UseRegister(left);
325     inputs[input_count++] = input;
326     inputs[input_count++] = input;
327   } else if (g.CanBeImmediate(right)) {
328     inputs[input_count++] = g.UseRegister(left);
329     inputs[input_count++] = g.UseImmediate(right);
330   } else {
331     if (node->op()->HasProperty(Operator::kCommutative) &&
332         g.CanBeBetterLeftOperand(right)) {
333       std::swap(left, right);
334     }
335     inputs[input_count++] = g.UseRegister(left);
336     inputs[input_count++] = g.Use(right);
337   }
338
339   if (cont->IsBranch()) {
340     inputs[input_count++] = g.Label(cont->true_block());
341     inputs[input_count++] = g.Label(cont->false_block());
342   }
343
344   outputs[output_count++] = g.DefineSameAsFirst(node);
345   if (cont->IsSet()) {
346     outputs[output_count++] = g.DefineAsRegister(cont->result());
347   }
348
349   DCHECK_NE(0u, input_count);
350   DCHECK_NE(0u, output_count);
351   DCHECK_GE(arraysize(inputs), input_count);
352   DCHECK_GE(arraysize(outputs), output_count);
353
354   selector->Emit(cont->Encode(opcode), output_count, outputs, input_count,
355                  inputs);
356 }
357
358
359 // Shared routine for multiple binary operations.
360 static void VisitBinop(InstructionSelector* selector, Node* node,
361                        InstructionCode opcode) {
362   FlagsContinuation cont;
363   VisitBinop(selector, node, opcode, &cont);
364 }
365
366
367 void InstructionSelector::VisitWord32And(Node* node) {
368   X64OperandGenerator g(this);
369   Uint32BinopMatcher m(node);
370   if (m.right().Is(0xff)) {
371     Emit(kX64Movzxbl, g.DefineAsRegister(node), g.Use(m.left().node()));
372   } else if (m.right().Is(0xffff)) {
373     Emit(kX64Movzxwl, g.DefineAsRegister(node), g.Use(m.left().node()));
374   } else {
375     VisitBinop(this, node, kX64And32);
376   }
377 }
378
379
380 void InstructionSelector::VisitWord64And(Node* node) {
381   VisitBinop(this, node, kX64And);
382 }
383
384
385 void InstructionSelector::VisitWord32Or(Node* node) {
386   VisitBinop(this, node, kX64Or32);
387 }
388
389
390 void InstructionSelector::VisitWord64Or(Node* node) {
391   VisitBinop(this, node, kX64Or);
392 }
393
394
395 void InstructionSelector::VisitWord32Xor(Node* node) {
396   X64OperandGenerator g(this);
397   Uint32BinopMatcher m(node);
398   if (m.right().Is(-1)) {
399     Emit(kX64Not32, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()));
400   } else {
401     VisitBinop(this, node, kX64Xor32);
402   }
403 }
404
405
406 void InstructionSelector::VisitWord64Xor(Node* node) {
407   X64OperandGenerator g(this);
408   Uint64BinopMatcher m(node);
409   if (m.right().Is(-1)) {
410     Emit(kX64Not, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()));
411   } else {
412     VisitBinop(this, node, kX64Xor);
413   }
414 }
415
416
417 namespace {
418
419 // Shared routine for multiple 32-bit shift operations.
420 // TODO(bmeurer): Merge this with VisitWord64Shift using template magic?
421 void VisitWord32Shift(InstructionSelector* selector, Node* node,
422                       ArchOpcode opcode) {
423   X64OperandGenerator g(selector);
424   Int32BinopMatcher m(node);
425   Node* left = m.left().node();
426   Node* right = m.right().node();
427
428   if (g.CanBeImmediate(right)) {
429     selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
430                    g.UseImmediate(right));
431   } else {
432     selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
433                    g.UseFixed(right, rcx));
434   }
435 }
436
437
438 // Shared routine for multiple 64-bit shift operations.
439 // TODO(bmeurer): Merge this with VisitWord32Shift using template magic?
440 void VisitWord64Shift(InstructionSelector* selector, Node* node,
441                       ArchOpcode opcode) {
442   X64OperandGenerator g(selector);
443   Int64BinopMatcher m(node);
444   Node* left = m.left().node();
445   Node* right = m.right().node();
446
447   if (g.CanBeImmediate(right)) {
448     selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
449                    g.UseImmediate(right));
450   } else {
451     if (m.right().IsWord64And()) {
452       Int64BinopMatcher mright(right);
453       if (mright.right().Is(0x3F)) {
454         right = mright.left().node();
455       }
456     }
457     selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
458                    g.UseFixed(right, rcx));
459   }
460 }
461
462
463 void EmitLea(InstructionSelector* selector, InstructionCode opcode,
464              Node* result, Node* index, int scale, Node* base,
465              Node* displacement) {
466   X64OperandGenerator g(selector);
467
468   InstructionOperand inputs[4];
469   size_t input_count = 0;
470   AddressingMode mode = g.GenerateMemoryOperandInputs(
471       index, scale, base, displacement, inputs, &input_count);
472
473   DCHECK_NE(0u, input_count);
474   DCHECK_GE(arraysize(inputs), input_count);
475
476   InstructionOperand outputs[1];
477   outputs[0] = g.DefineAsRegister(result);
478
479   opcode = AddressingModeField::encode(mode) | opcode;
480
481   selector->Emit(opcode, 1, outputs, input_count, inputs);
482 }
483
484 }  // namespace
485
486
487 void InstructionSelector::VisitWord32Shl(Node* node) {
488   Int32ScaleMatcher m(node, true);
489   if (m.matches()) {
490     Node* index = node->InputAt(0);
491     Node* base = m.power_of_two_plus_one() ? index : NULL;
492     EmitLea(this, kX64Lea32, node, index, m.scale(), base, NULL);
493     return;
494   }
495   VisitWord32Shift(this, node, kX64Shl32);
496 }
497
498
499 void InstructionSelector::VisitWord64Shl(Node* node) {
500   X64OperandGenerator g(this);
501   Int64BinopMatcher m(node);
502   if ((m.left().IsChangeInt32ToInt64() || m.left().IsChangeUint32ToUint64()) &&
503       m.right().IsInRange(32, 63)) {
504     // There's no need to sign/zero-extend to 64-bit if we shift out the upper
505     // 32 bits anyway.
506     Emit(kX64Shl, g.DefineSameAsFirst(node),
507          g.UseRegister(m.left().node()->InputAt(0)),
508          g.UseImmediate(m.right().node()));
509     return;
510   }
511   VisitWord64Shift(this, node, kX64Shl);
512 }
513
514
515 void InstructionSelector::VisitWord32Shr(Node* node) {
516   VisitWord32Shift(this, node, kX64Shr32);
517 }
518
519
520 void InstructionSelector::VisitWord64Shr(Node* node) {
521   VisitWord64Shift(this, node, kX64Shr);
522 }
523
524
525 void InstructionSelector::VisitWord32Sar(Node* node) {
526   X64OperandGenerator g(this);
527   Int32BinopMatcher m(node);
528   if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) {
529     Int32BinopMatcher mleft(m.left().node());
530     if (mleft.right().Is(16) && m.right().Is(16)) {
531       Emit(kX64Movsxwl, g.DefineAsRegister(node), g.Use(mleft.left().node()));
532       return;
533     } else if (mleft.right().Is(24) && m.right().Is(24)) {
534       Emit(kX64Movsxbl, g.DefineAsRegister(node), g.Use(mleft.left().node()));
535       return;
536     }
537   }
538   VisitWord32Shift(this, node, kX64Sar32);
539 }
540
541
542 void InstructionSelector::VisitWord64Sar(Node* node) {
543   VisitWord64Shift(this, node, kX64Sar);
544 }
545
546
547 void InstructionSelector::VisitWord32Ror(Node* node) {
548   VisitWord32Shift(this, node, kX64Ror32);
549 }
550
551
552 void InstructionSelector::VisitWord64Ror(Node* node) {
553   VisitWord64Shift(this, node, kX64Ror);
554 }
555
556
557 void InstructionSelector::VisitWord32Clz(Node* node) {
558   X64OperandGenerator g(this);
559   Emit(kX64Lzcnt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
560 }
561
562
563 void InstructionSelector::VisitInt32Add(Node* node) {
564   X64OperandGenerator g(this);
565
566   // Try to match the Add to a leal pattern
567   BaseWithIndexAndDisplacement32Matcher m(node);
568   if (m.matches() &&
569       (m.displacement() == NULL || g.CanBeImmediate(m.displacement()))) {
570     EmitLea(this, kX64Lea32, node, m.index(), m.scale(), m.base(),
571             m.displacement());
572     return;
573   }
574
575   // No leal pattern match, use addl
576   VisitBinop(this, node, kX64Add32);
577 }
578
579
580 void InstructionSelector::VisitInt64Add(Node* node) {
581   VisitBinop(this, node, kX64Add);
582 }
583
584
585 void InstructionSelector::VisitInt32Sub(Node* node) {
586   X64OperandGenerator g(this);
587   Int32BinopMatcher m(node);
588   if (m.left().Is(0)) {
589     Emit(kX64Neg32, g.DefineSameAsFirst(node), g.UseRegister(m.right().node()));
590   } else {
591     if (m.right().HasValue() && g.CanBeImmediate(m.right().node())) {
592       // Turn subtractions of constant values into immediate "leal" instructions
593       // by negating the value.
594       Emit(kX64Lea32 | AddressingModeField::encode(kMode_MRI),
595            g.DefineAsRegister(node), g.UseRegister(m.left().node()),
596            g.TempImmediate(-m.right().Value()));
597       return;
598     }
599     VisitBinop(this, node, kX64Sub32);
600   }
601 }
602
603
604 void InstructionSelector::VisitInt64Sub(Node* node) {
605   X64OperandGenerator g(this);
606   Int64BinopMatcher m(node);
607   if (m.left().Is(0)) {
608     Emit(kX64Neg, g.DefineSameAsFirst(node), g.UseRegister(m.right().node()));
609   } else {
610     VisitBinop(this, node, kX64Sub);
611   }
612 }
613
614
615 namespace {
616
617 void VisitMul(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
618   X64OperandGenerator g(selector);
619   Int32BinopMatcher m(node);
620   Node* left = m.left().node();
621   Node* right = m.right().node();
622   if (g.CanBeImmediate(right)) {
623     selector->Emit(opcode, g.DefineAsRegister(node), g.Use(left),
624                    g.UseImmediate(right));
625   } else {
626     if (g.CanBeBetterLeftOperand(right)) {
627       std::swap(left, right);
628     }
629     selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
630                    g.Use(right));
631   }
632 }
633
634
635 void VisitMulHigh(InstructionSelector* selector, Node* node,
636                   ArchOpcode opcode) {
637   X64OperandGenerator g(selector);
638   Node* left = node->InputAt(0);
639   Node* right = node->InputAt(1);
640   if (selector->IsLive(left) && !selector->IsLive(right)) {
641     std::swap(left, right);
642   }
643   // TODO(turbofan): We use UseUniqueRegister here to improve register
644   // allocation.
645   selector->Emit(opcode, g.DefineAsFixed(node, rdx), g.UseFixed(left, rax),
646                  g.UseUniqueRegister(right));
647 }
648
649
650 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
651   X64OperandGenerator g(selector);
652   InstructionOperand temps[] = {g.TempRegister(rdx)};
653   selector->Emit(
654       opcode, g.DefineAsFixed(node, rax), g.UseFixed(node->InputAt(0), rax),
655       g.UseUniqueRegister(node->InputAt(1)), arraysize(temps), temps);
656 }
657
658
659 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
660   X64OperandGenerator g(selector);
661   selector->Emit(opcode, g.DefineAsFixed(node, rdx),
662                  g.UseFixed(node->InputAt(0), rax),
663                  g.UseUniqueRegister(node->InputAt(1)));
664 }
665
666 }  // namespace
667
668
669 void InstructionSelector::VisitInt32Mul(Node* node) {
670   Int32ScaleMatcher m(node, true);
671   if (m.matches()) {
672     Node* index = node->InputAt(0);
673     Node* base = m.power_of_two_plus_one() ? index : NULL;
674     EmitLea(this, kX64Lea32, node, index, m.scale(), base, NULL);
675     return;
676   }
677   VisitMul(this, node, kX64Imul32);
678 }
679
680
681 void InstructionSelector::VisitInt64Mul(Node* node) {
682   VisitMul(this, node, kX64Imul);
683 }
684
685
686 void InstructionSelector::VisitInt32MulHigh(Node* node) {
687   VisitMulHigh(this, node, kX64ImulHigh32);
688 }
689
690
691 void InstructionSelector::VisitInt32Div(Node* node) {
692   VisitDiv(this, node, kX64Idiv32);
693 }
694
695
696 void InstructionSelector::VisitInt64Div(Node* node) {
697   VisitDiv(this, node, kX64Idiv);
698 }
699
700
701 void InstructionSelector::VisitUint32Div(Node* node) {
702   VisitDiv(this, node, kX64Udiv32);
703 }
704
705
706 void InstructionSelector::VisitUint64Div(Node* node) {
707   VisitDiv(this, node, kX64Udiv);
708 }
709
710
711 void InstructionSelector::VisitInt32Mod(Node* node) {
712   VisitMod(this, node, kX64Idiv32);
713 }
714
715
716 void InstructionSelector::VisitInt64Mod(Node* node) {
717   VisitMod(this, node, kX64Idiv);
718 }
719
720
721 void InstructionSelector::VisitUint32Mod(Node* node) {
722   VisitMod(this, node, kX64Udiv32);
723 }
724
725
726 void InstructionSelector::VisitUint64Mod(Node* node) {
727   VisitMod(this, node, kX64Udiv);
728 }
729
730
731 void InstructionSelector::VisitUint32MulHigh(Node* node) {
732   VisitMulHigh(this, node, kX64UmulHigh32);
733 }
734
735
736 void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) {
737   X64OperandGenerator g(this);
738   Emit(kSSECvtss2sd, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
739 }
740
741
742 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
743   X64OperandGenerator g(this);
744   Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
745 }
746
747
748 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
749   X64OperandGenerator g(this);
750   Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
751 }
752
753
754 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
755   X64OperandGenerator g(this);
756   Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
757 }
758
759
760 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
761   X64OperandGenerator g(this);
762   Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
763 }
764
765
766 void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
767   X64OperandGenerator g(this);
768   Emit(kX64Movsxlq, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
769 }
770
771
772 void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
773   X64OperandGenerator g(this);
774   Node* value = node->InputAt(0);
775   switch (value->opcode()) {
776     case IrOpcode::kWord32And:
777     case IrOpcode::kWord32Or:
778     case IrOpcode::kWord32Xor:
779     case IrOpcode::kWord32Shl:
780     case IrOpcode::kWord32Shr:
781     case IrOpcode::kWord32Sar:
782     case IrOpcode::kWord32Ror:
783     case IrOpcode::kWord32Equal:
784     case IrOpcode::kInt32Add:
785     case IrOpcode::kInt32Sub:
786     case IrOpcode::kInt32Mul:
787     case IrOpcode::kInt32MulHigh:
788     case IrOpcode::kInt32Div:
789     case IrOpcode::kInt32LessThan:
790     case IrOpcode::kInt32LessThanOrEqual:
791     case IrOpcode::kInt32Mod:
792     case IrOpcode::kUint32Div:
793     case IrOpcode::kUint32LessThan:
794     case IrOpcode::kUint32LessThanOrEqual:
795     case IrOpcode::kUint32Mod:
796     case IrOpcode::kUint32MulHigh: {
797       // These 32-bit operations implicitly zero-extend to 64-bit on x64, so the
798       // zero-extension is a no-op.
799       Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value));
800       return;
801     }
802     default:
803       break;
804   }
805   Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
806 }
807
808
809 void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
810   X64OperandGenerator g(this);
811   Emit(kSSECvtsd2ss, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
812 }
813
814
815 void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
816   X64OperandGenerator g(this);
817   Node* value = node->InputAt(0);
818   if (CanCover(node, value)) {
819     switch (value->opcode()) {
820       case IrOpcode::kWord64Sar:
821       case IrOpcode::kWord64Shr: {
822         Int64BinopMatcher m(value);
823         if (m.right().Is(32)) {
824           Emit(kX64Shr, g.DefineSameAsFirst(node),
825                g.UseRegister(m.left().node()), g.TempImmediate(32));
826           return;
827         }
828         break;
829       }
830       default:
831         break;
832     }
833   }
834   Emit(kX64Movl, g.DefineAsRegister(node), g.Use(value));
835 }
836
837
838 void InstructionSelector::VisitFloat64Add(Node* node) {
839   X64OperandGenerator g(this);
840   if (IsSupported(AVX)) {
841     Emit(kAVXFloat64Add, g.DefineAsRegister(node),
842          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
843   } else {
844     Emit(kSSEFloat64Add, g.DefineSameAsFirst(node),
845          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
846   }
847 }
848
849
850 void InstructionSelector::VisitFloat64Sub(Node* node) {
851   X64OperandGenerator g(this);
852   Float64BinopMatcher m(node);
853   if (m.left().IsMinusZero() && m.right().IsFloat64RoundDown() &&
854       CanCover(m.node(), m.right().node())) {
855     if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub &&
856         CanCover(m.right().node(), m.right().InputAt(0))) {
857       Float64BinopMatcher mright0(m.right().InputAt(0));
858       if (mright0.left().IsMinusZero()) {
859         Emit(kSSEFloat64Round | MiscField::encode(kRoundUp),
860              g.DefineAsRegister(node), g.UseRegister(mright0.right().node()));
861         return;
862       }
863     }
864   }
865   if (IsSupported(AVX)) {
866     Emit(kAVXFloat64Sub, g.DefineAsRegister(node),
867          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
868   } else {
869     Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node),
870          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
871   }
872 }
873
874
875 void InstructionSelector::VisitFloat64Mul(Node* node) {
876   X64OperandGenerator g(this);
877   if (IsSupported(AVX)) {
878     Emit(kAVXFloat64Mul, g.DefineAsRegister(node),
879          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
880   } else {
881     Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node),
882          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
883   }
884 }
885
886
887 void InstructionSelector::VisitFloat64Div(Node* node) {
888   X64OperandGenerator g(this);
889   if (IsSupported(AVX)) {
890     Emit(kAVXFloat64Div, g.DefineAsRegister(node),
891          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
892   } else {
893     Emit(kSSEFloat64Div, g.DefineSameAsFirst(node),
894          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
895   }
896 }
897
898
899 void InstructionSelector::VisitFloat64Mod(Node* node) {
900   X64OperandGenerator g(this);
901   InstructionOperand temps[] = {g.TempRegister(rax)};
902   Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
903        g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1,
904        temps);
905 }
906
907
908 void InstructionSelector::VisitFloat64Max(Node* node) {
909   X64OperandGenerator g(this);
910   if (IsSupported(AVX)) {
911     Emit(kAVXFloat64Max, g.DefineAsRegister(node),
912          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
913   } else {
914     Emit(kSSEFloat64Max, g.DefineSameAsFirst(node),
915          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
916   }
917 }
918
919
920 void InstructionSelector::VisitFloat64Min(Node* node) {
921   X64OperandGenerator g(this);
922   if (IsSupported(AVX)) {
923     Emit(kAVXFloat64Min, g.DefineAsRegister(node),
924          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
925   } else {
926     Emit(kSSEFloat64Min, g.DefineSameAsFirst(node),
927          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
928   }
929 }
930
931
932 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
933   X64OperandGenerator g(this);
934   Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
935 }
936
937
938 namespace {
939
940 void VisitRRFloat64(InstructionSelector* selector, InstructionCode opcode,
941                     Node* node) {
942   X64OperandGenerator g(selector);
943   selector->Emit(opcode, g.DefineAsRegister(node),
944                  g.UseRegister(node->InputAt(0)));
945 }
946
947 }  // namespace
948
949
950 void InstructionSelector::VisitFloat64RoundDown(Node* node) {
951   VisitRRFloat64(this, kSSEFloat64Round | MiscField::encode(kRoundDown), node);
952 }
953
954
955 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
956   VisitRRFloat64(this, kSSEFloat64Round | MiscField::encode(kRoundToZero),
957                  node);
958 }
959
960
961 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
962   UNREACHABLE();
963 }
964
965
966 void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) {
967   X64OperandGenerator g(this);
968   const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
969
970   FrameStateDescriptor* frame_state_descriptor = NULL;
971   if (descriptor->NeedsFrameState()) {
972     frame_state_descriptor = GetFrameStateDescriptor(
973         node->InputAt(static_cast<int>(descriptor->InputCount())));
974   }
975
976   CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
977
978   // Compute InstructionOperands for inputs and outputs.
979   InitializeCallBuffer(node, &buffer, true, true);
980
981   // Push any stack arguments.
982   for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
983        ++i) {
984     // TODO(titzer): handle pushing double parameters.
985     InstructionOperand value =
986         g.CanBeImmediate(*i) ? g.UseImmediate(*i) : IsSupported(ATOM)
987                                                         ? g.UseRegister(*i)
988                                                         : g.Use(*i);
989     Emit(kX64Push, g.NoOutput(), value);
990   }
991
992   // Pass label of exception handler block.
993   CallDescriptor::Flags flags = descriptor->flags();
994   if (handler != nullptr) {
995     flags |= CallDescriptor::kHasExceptionHandler;
996     buffer.instruction_args.push_back(g.Label(handler));
997   }
998
999   // Select the appropriate opcode based on the call type.
1000   InstructionCode opcode;
1001   switch (descriptor->kind()) {
1002     case CallDescriptor::kCallCodeObject: {
1003       opcode = kArchCallCodeObject;
1004       break;
1005     }
1006     case CallDescriptor::kCallJSFunction:
1007       opcode = kArchCallJSFunction;
1008       break;
1009     default:
1010       UNREACHABLE();
1011       return;
1012   }
1013   opcode |= MiscField::encode(flags);
1014
1015   // Emit the call instruction.
1016   InstructionOperand* first_output =
1017       buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
1018   Instruction* call_instr =
1019       Emit(opcode, buffer.outputs.size(), first_output,
1020            buffer.instruction_args.size(), &buffer.instruction_args.front());
1021   call_instr->MarkAsCall();
1022 }
1023
1024
1025 namespace {
1026
1027 // Shared routine for multiple compare operations.
1028 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
1029                   InstructionOperand left, InstructionOperand right,
1030                   FlagsContinuation* cont) {
1031   X64OperandGenerator g(selector);
1032   opcode = cont->Encode(opcode);
1033   if (cont->IsBranch()) {
1034     selector->Emit(opcode, g.NoOutput(), left, right,
1035                    g.Label(cont->true_block()), g.Label(cont->false_block()));
1036   } else {
1037     DCHECK(cont->IsSet());
1038     selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right);
1039   }
1040 }
1041
1042
1043 // Shared routine for multiple compare operations.
1044 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
1045                   Node* left, Node* right, FlagsContinuation* cont,
1046                   bool commutative) {
1047   X64OperandGenerator g(selector);
1048   if (commutative && g.CanBeBetterLeftOperand(right)) {
1049     std::swap(left, right);
1050   }
1051   VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
1052 }
1053
1054
1055 // Shared routine for multiple word compare operations.
1056 void VisitWordCompare(InstructionSelector* selector, Node* node,
1057                       InstructionCode opcode, FlagsContinuation* cont) {
1058   X64OperandGenerator g(selector);
1059   Node* const left = node->InputAt(0);
1060   Node* const right = node->InputAt(1);
1061
1062   // Match immediates on left or right side of comparison.
1063   if (g.CanBeImmediate(right)) {
1064     VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont);
1065   } else if (g.CanBeImmediate(left)) {
1066     if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
1067     VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont);
1068   } else {
1069     VisitCompare(selector, opcode, left, right, cont,
1070                  node->op()->HasProperty(Operator::kCommutative));
1071   }
1072 }
1073
1074
1075 // Shared routine for 64-bit word comparison operations.
1076 void VisitWord64Compare(InstructionSelector* selector, Node* node,
1077                         FlagsContinuation* cont) {
1078   X64OperandGenerator g(selector);
1079   Int64BinopMatcher m(node);
1080   if (m.left().IsLoad() && m.right().IsLoadStackPointer()) {
1081     LoadMatcher<ExternalReferenceMatcher> mleft(m.left().node());
1082     ExternalReference js_stack_limit =
1083         ExternalReference::address_of_stack_limit(selector->isolate());
1084     if (mleft.object().Is(js_stack_limit) && mleft.index().Is(0)) {
1085       // Compare(Load(js_stack_limit), LoadStackPointer)
1086       if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
1087       InstructionCode opcode = cont->Encode(kX64StackCheck);
1088       if (cont->IsBranch()) {
1089         selector->Emit(opcode, g.NoOutput(), g.Label(cont->true_block()),
1090                        g.Label(cont->false_block()));
1091       } else {
1092         DCHECK(cont->IsSet());
1093         selector->Emit(opcode, g.DefineAsRegister(cont->result()));
1094       }
1095       return;
1096     }
1097   }
1098   VisitWordCompare(selector, node, kX64Cmp, cont);
1099 }
1100
1101
1102 // Shared routine for comparison with zero.
1103 void VisitCompareZero(InstructionSelector* selector, Node* node,
1104                       InstructionCode opcode, FlagsContinuation* cont) {
1105   X64OperandGenerator g(selector);
1106   VisitCompare(selector, opcode, g.Use(node), g.TempImmediate(0), cont);
1107 }
1108
1109
1110 // Shared routine for multiple float64 compare operations (inputs commuted).
1111 void VisitFloat64Compare(InstructionSelector* selector, Node* node,
1112                          FlagsContinuation* cont) {
1113   Node* const left = node->InputAt(0);
1114   Node* const right = node->InputAt(1);
1115   VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false);
1116 }
1117
1118 }  // namespace
1119
1120
1121 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
1122                                       BasicBlock* fbranch) {
1123   X64OperandGenerator g(this);
1124   Node* user = branch;
1125   Node* value = branch->InputAt(0);
1126
1127   FlagsContinuation cont(kNotEqual, tbranch, fbranch);
1128
1129   // Try to combine with comparisons against 0 by simply inverting the branch.
1130   while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) {
1131     Int32BinopMatcher m(value);
1132     if (m.right().Is(0)) {
1133       user = value;
1134       value = m.left().node();
1135       cont.Negate();
1136     } else {
1137       break;
1138     }
1139   }
1140
1141   // Try to combine the branch with a comparison.
1142   if (CanCover(user, value)) {
1143     switch (value->opcode()) {
1144       case IrOpcode::kWord32Equal:
1145         cont.OverwriteAndNegateIfEqual(kEqual);
1146         return VisitWordCompare(this, value, kX64Cmp32, &cont);
1147       case IrOpcode::kInt32LessThan:
1148         cont.OverwriteAndNegateIfEqual(kSignedLessThan);
1149         return VisitWordCompare(this, value, kX64Cmp32, &cont);
1150       case IrOpcode::kInt32LessThanOrEqual:
1151         cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1152         return VisitWordCompare(this, value, kX64Cmp32, &cont);
1153       case IrOpcode::kUint32LessThan:
1154         cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
1155         return VisitWordCompare(this, value, kX64Cmp32, &cont);
1156       case IrOpcode::kUint32LessThanOrEqual:
1157         cont.OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1158         return VisitWordCompare(this, value, kX64Cmp32, &cont);
1159       case IrOpcode::kWord64Equal:
1160         cont.OverwriteAndNegateIfEqual(kEqual);
1161         return VisitWord64Compare(this, value, &cont);
1162       case IrOpcode::kInt64LessThan:
1163         cont.OverwriteAndNegateIfEqual(kSignedLessThan);
1164         return VisitWord64Compare(this, value, &cont);
1165       case IrOpcode::kInt64LessThanOrEqual:
1166         cont.OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1167         return VisitWord64Compare(this, value, &cont);
1168       case IrOpcode::kUint64LessThan:
1169         cont.OverwriteAndNegateIfEqual(kUnsignedLessThan);
1170         return VisitWord64Compare(this, value, &cont);
1171       case IrOpcode::kFloat64Equal:
1172         cont.OverwriteAndNegateIfEqual(kUnorderedEqual);
1173         return VisitFloat64Compare(this, value, &cont);
1174       case IrOpcode::kFloat64LessThan:
1175         cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
1176         return VisitFloat64Compare(this, value, &cont);
1177       case IrOpcode::kFloat64LessThanOrEqual:
1178         cont.OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
1179         return VisitFloat64Compare(this, value, &cont);
1180       case IrOpcode::kProjection:
1181         // Check if this is the overflow output projection of an
1182         // <Operation>WithOverflow node.
1183         if (ProjectionIndexOf(value->op()) == 1u) {
1184           // We cannot combine the <Operation>WithOverflow with this branch
1185           // unless the 0th projection (the use of the actual value of the
1186           // <Operation> is either NULL, which means there's no use of the
1187           // actual value, or was already defined, which means it is scheduled
1188           // *AFTER* this branch).
1189           Node* const node = value->InputAt(0);
1190           Node* const result = NodeProperties::FindProjection(node, 0);
1191           if (result == NULL || IsDefined(result)) {
1192             switch (node->opcode()) {
1193               case IrOpcode::kInt32AddWithOverflow:
1194                 cont.OverwriteAndNegateIfEqual(kOverflow);
1195                 return VisitBinop(this, node, kX64Add32, &cont);
1196               case IrOpcode::kInt32SubWithOverflow:
1197                 cont.OverwriteAndNegateIfEqual(kOverflow);
1198                 return VisitBinop(this, node, kX64Sub32, &cont);
1199               default:
1200                 break;
1201             }
1202           }
1203         }
1204         break;
1205       case IrOpcode::kInt32Sub:
1206         return VisitWordCompare(this, value, kX64Cmp32, &cont);
1207       case IrOpcode::kInt64Sub:
1208         return VisitWord64Compare(this, value, &cont);
1209       case IrOpcode::kWord32And:
1210         return VisitWordCompare(this, value, kX64Test32, &cont);
1211       case IrOpcode::kWord64And:
1212         return VisitWordCompare(this, value, kX64Test, &cont);
1213       default:
1214         break;
1215     }
1216   }
1217
1218   // Branch could not be combined with a compare, emit compare against 0.
1219   VisitCompareZero(this, value, kX64Cmp32, &cont);
1220 }
1221
1222
1223 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
1224   X64OperandGenerator g(this);
1225   InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
1226
1227   // Emit either ArchTableSwitch or ArchLookupSwitch.
1228   size_t table_space_cost = 4 + sw.value_range;
1229   size_t table_time_cost = 3;
1230   size_t lookup_space_cost = 3 + 2 * sw.case_count;
1231   size_t lookup_time_cost = sw.case_count;
1232   if (sw.case_count > 4 &&
1233       table_space_cost + 3 * table_time_cost <=
1234           lookup_space_cost + 3 * lookup_time_cost &&
1235       sw.min_value > std::numeric_limits<int32_t>::min()) {
1236     InstructionOperand index_operand = g.TempRegister();
1237     if (sw.min_value) {
1238       // The leal automatically zero extends, so result is a valid 64-bit index.
1239       Emit(kX64Lea32 | AddressingModeField::encode(kMode_MRI), index_operand,
1240            value_operand, g.TempImmediate(-sw.min_value));
1241     } else {
1242       // Zero extend, because we use it as 64-bit index into the jump table.
1243       Emit(kX64Movl, index_operand, value_operand);
1244     }
1245     // Generate a table lookup.
1246     return EmitTableSwitch(sw, index_operand);
1247   }
1248
1249   // Generate a sequence of conditional jumps.
1250   return EmitLookupSwitch(sw, value_operand);
1251 }
1252
1253
1254 void InstructionSelector::VisitWord32Equal(Node* const node) {
1255   Node* user = node;
1256   FlagsContinuation cont(kEqual, node);
1257   Int32BinopMatcher m(user);
1258   if (m.right().Is(0)) {
1259     Node* value = m.left().node();
1260
1261     // Try to combine with comparisons against 0 by simply inverting the branch.
1262     while (CanCover(user, value) && value->opcode() == IrOpcode::kWord32Equal) {
1263       Int32BinopMatcher m(value);
1264       if (m.right().Is(0)) {
1265         user = value;
1266         value = m.left().node();
1267         cont.Negate();
1268       } else {
1269         break;
1270       }
1271     }
1272
1273     // Try to combine the branch with a comparison.
1274     if (CanCover(user, value)) {
1275       switch (value->opcode()) {
1276         case IrOpcode::kInt32Sub:
1277           return VisitWordCompare(this, value, kX64Cmp32, &cont);
1278         case IrOpcode::kWord32And:
1279           return VisitWordCompare(this, value, kX64Test32, &cont);
1280         default:
1281           break;
1282       }
1283     }
1284     return VisitCompareZero(this, value, kX64Cmp32, &cont);
1285   }
1286   VisitWordCompare(this, node, kX64Cmp32, &cont);
1287 }
1288
1289
1290 void InstructionSelector::VisitInt32LessThan(Node* node) {
1291   FlagsContinuation cont(kSignedLessThan, node);
1292   VisitWordCompare(this, node, kX64Cmp32, &cont);
1293 }
1294
1295
1296 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
1297   FlagsContinuation cont(kSignedLessThanOrEqual, node);
1298   VisitWordCompare(this, node, kX64Cmp32, &cont);
1299 }
1300
1301
1302 void InstructionSelector::VisitUint32LessThan(Node* node) {
1303   FlagsContinuation cont(kUnsignedLessThan, node);
1304   VisitWordCompare(this, node, kX64Cmp32, &cont);
1305 }
1306
1307
1308 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
1309   FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
1310   VisitWordCompare(this, node, kX64Cmp32, &cont);
1311 }
1312
1313
1314 void InstructionSelector::VisitWord64Equal(Node* const node) {
1315   Node* user = node;
1316   FlagsContinuation cont(kEqual, node);
1317   Int64BinopMatcher m(user);
1318   if (m.right().Is(0)) {
1319     Node* value = m.left().node();
1320
1321     // Try to combine with comparisons against 0 by simply inverting the branch.
1322     while (CanCover(user, value) && value->opcode() == IrOpcode::kWord64Equal) {
1323       Int64BinopMatcher m(value);
1324       if (m.right().Is(0)) {
1325         user = value;
1326         value = m.left().node();
1327         cont.Negate();
1328       } else {
1329         break;
1330       }
1331     }
1332
1333     // Try to combine the branch with a comparison.
1334     if (CanCover(user, value)) {
1335       switch (value->opcode()) {
1336         case IrOpcode::kInt64Sub:
1337           return VisitWord64Compare(this, value, &cont);
1338         case IrOpcode::kWord64And:
1339           return VisitWordCompare(this, value, kX64Test, &cont);
1340         default:
1341           break;
1342       }
1343     }
1344     return VisitCompareZero(this, value, kX64Cmp, &cont);
1345   }
1346   VisitWord64Compare(this, node, &cont);
1347 }
1348
1349
1350 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
1351   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1352     FlagsContinuation cont(kOverflow, ovf);
1353     VisitBinop(this, node, kX64Add32, &cont);
1354   }
1355   FlagsContinuation cont;
1356   VisitBinop(this, node, kX64Add32, &cont);
1357 }
1358
1359
1360 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
1361   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1362     FlagsContinuation cont(kOverflow, ovf);
1363     return VisitBinop(this, node, kX64Sub32, &cont);
1364   }
1365   FlagsContinuation cont;
1366   VisitBinop(this, node, kX64Sub32, &cont);
1367 }
1368
1369
1370 void InstructionSelector::VisitInt64LessThan(Node* node) {
1371   FlagsContinuation cont(kSignedLessThan, node);
1372   VisitWord64Compare(this, node, &cont);
1373 }
1374
1375
1376 void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
1377   FlagsContinuation cont(kSignedLessThanOrEqual, node);
1378   VisitWord64Compare(this, node, &cont);
1379 }
1380
1381
1382 void InstructionSelector::VisitUint64LessThan(Node* node) {
1383   FlagsContinuation cont(kUnsignedLessThan, node);
1384   VisitWord64Compare(this, node, &cont);
1385 }
1386
1387
1388 void InstructionSelector::VisitFloat64Equal(Node* node) {
1389   FlagsContinuation cont(kUnorderedEqual, node);
1390   VisitFloat64Compare(this, node, &cont);
1391 }
1392
1393
1394 void InstructionSelector::VisitFloat64LessThan(Node* node) {
1395   FlagsContinuation cont(kUnsignedGreaterThan, node);
1396   VisitFloat64Compare(this, node, &cont);
1397 }
1398
1399
1400 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
1401   FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node);
1402   VisitFloat64Compare(this, node, &cont);
1403 }
1404
1405
1406 void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) {
1407   X64OperandGenerator g(this);
1408   Emit(kSSEFloat64ExtractLowWord32, g.DefineAsRegister(node),
1409        g.Use(node->InputAt(0)));
1410 }
1411
1412
1413 void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) {
1414   X64OperandGenerator g(this);
1415   Emit(kSSEFloat64ExtractHighWord32, g.DefineAsRegister(node),
1416        g.Use(node->InputAt(0)));
1417 }
1418
1419
1420 void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) {
1421   X64OperandGenerator g(this);
1422   Node* left = node->InputAt(0);
1423   Node* right = node->InputAt(1);
1424   Float64Matcher mleft(left);
1425   if (mleft.HasValue() && (bit_cast<uint64_t>(mleft.Value()) >> 32) == 0u) {
1426     Emit(kSSEFloat64LoadLowWord32, g.DefineAsRegister(node), g.Use(right));
1427     return;
1428   }
1429   Emit(kSSEFloat64InsertLowWord32, g.DefineSameAsFirst(node),
1430        g.UseRegister(left), g.Use(right));
1431 }
1432
1433
1434 void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) {
1435   X64OperandGenerator g(this);
1436   Node* left = node->InputAt(0);
1437   Node* right = node->InputAt(1);
1438   Emit(kSSEFloat64InsertHighWord32, g.DefineSameAsFirst(node),
1439        g.UseRegister(left), g.Use(right));
1440 }
1441
1442
1443 // static
1444 MachineOperatorBuilder::Flags
1445 InstructionSelector::SupportedMachineOperatorFlags() {
1446   MachineOperatorBuilder::Flags flags =
1447       MachineOperatorBuilder::kFloat64Max |
1448       MachineOperatorBuilder::kFloat64Min |
1449       MachineOperatorBuilder::kWord32ShiftIsSafe;
1450   if (CpuFeatures::IsSupported(SSE4_1)) {
1451     flags |= MachineOperatorBuilder::kFloat64RoundDown |
1452              MachineOperatorBuilder::kFloat64RoundTruncate;
1453   }
1454   return flags;
1455 }
1456
1457 }  // namespace compiler
1458 }  // namespace internal
1459 }  // namespace v8