beec701903ec4598f26fb3d093b7898b2ea27804
[platform/upstream/nodejs.git] / deps / v8 / src / compiler / ia32 / instruction-selector-ia32.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 "src/compiler/instruction-selector-impl.h"
6 #include "src/compiler/node-matchers.h"
7 #include "src/compiler/node-properties.h"
8
9 namespace v8 {
10 namespace internal {
11 namespace compiler {
12
13 // Adds IA32-specific methods for generating operands.
14 class IA32OperandGenerator FINAL : public OperandGenerator {
15  public:
16   explicit IA32OperandGenerator(InstructionSelector* selector)
17       : OperandGenerator(selector) {}
18
19   InstructionOperand UseByteRegister(Node* node) {
20     // TODO(dcarney): relax constraint.
21     return UseFixed(node, edx);
22   }
23
24   bool CanBeImmediate(Node* node) {
25     switch (node->opcode()) {
26       case IrOpcode::kInt32Constant:
27       case IrOpcode::kNumberConstant:
28       case IrOpcode::kExternalConstant:
29         return true;
30       case IrOpcode::kHeapConstant: {
31         // Constants in new space cannot be used as immediates in V8 because
32         // the GC does not scan code objects when collecting the new generation.
33         Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node);
34         Isolate* isolate = value.handle()->GetIsolate();
35         return !isolate->heap()->InNewSpace(*value.handle());
36       }
37       default:
38         return false;
39     }
40   }
41
42   AddressingMode GenerateMemoryOperandInputs(Node* index, int scale, Node* base,
43                                              Node* displacement_node,
44                                              InstructionOperand inputs[],
45                                              size_t* input_count) {
46     AddressingMode mode = kMode_MRI;
47     int32_t displacement = (displacement_node == NULL)
48                                ? 0
49                                : OpParameter<int32_t>(displacement_node);
50     if (base != NULL) {
51       if (base->opcode() == IrOpcode::kInt32Constant) {
52         displacement += OpParameter<int32_t>(base);
53         base = NULL;
54       }
55     }
56     if (base != NULL) {
57       inputs[(*input_count)++] = UseRegister(base);
58       if (index != NULL) {
59         DCHECK(scale >= 0 && scale <= 3);
60         inputs[(*input_count)++] = UseRegister(index);
61         if (displacement != 0) {
62           inputs[(*input_count)++] = TempImmediate(displacement);
63           static const AddressingMode kMRnI_modes[] = {kMode_MR1I, kMode_MR2I,
64                                                        kMode_MR4I, kMode_MR8I};
65           mode = kMRnI_modes[scale];
66         } else {
67           static const AddressingMode kMRn_modes[] = {kMode_MR1, kMode_MR2,
68                                                       kMode_MR4, kMode_MR8};
69           mode = kMRn_modes[scale];
70         }
71       } else {
72         if (displacement == 0) {
73           mode = kMode_MR;
74         } else {
75           inputs[(*input_count)++] = TempImmediate(displacement);
76           mode = kMode_MRI;
77         }
78       }
79     } else {
80       DCHECK(scale >= 0 && scale <= 3);
81       if (index != NULL) {
82         inputs[(*input_count)++] = UseRegister(index);
83         if (displacement != 0) {
84           inputs[(*input_count)++] = TempImmediate(displacement);
85           static const AddressingMode kMnI_modes[] = {kMode_MRI, kMode_M2I,
86                                                       kMode_M4I, kMode_M8I};
87           mode = kMnI_modes[scale];
88         } else {
89           static const AddressingMode kMn_modes[] = {kMode_MR, kMode_M2,
90                                                      kMode_M4, kMode_M8};
91           mode = kMn_modes[scale];
92         }
93       } else {
94         inputs[(*input_count)++] = TempImmediate(displacement);
95         return kMode_MI;
96       }
97     }
98     return mode;
99   }
100
101   AddressingMode GetEffectiveAddressMemoryOperand(Node* node,
102                                                   InstructionOperand inputs[],
103                                                   size_t* input_count) {
104     BaseWithIndexAndDisplacement32Matcher m(node, true);
105     DCHECK(m.matches());
106     if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) {
107       return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(),
108                                          m.displacement(), inputs, input_count);
109     } else {
110       inputs[(*input_count)++] = UseRegister(node->InputAt(0));
111       inputs[(*input_count)++] = UseRegister(node->InputAt(1));
112       return kMode_MR1;
113     }
114   }
115
116   bool CanBeBetterLeftOperand(Node* node) const {
117     return !selector()->IsLive(node);
118   }
119 };
120
121
122 static void VisitRRFloat64(InstructionSelector* selector, ArchOpcode opcode,
123                            Node* node) {
124   IA32OperandGenerator g(selector);
125   selector->Emit(opcode, g.DefineAsRegister(node),
126                  g.UseRegister(node->InputAt(0)));
127 }
128
129
130 void InstructionSelector::VisitLoad(Node* node) {
131   MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node));
132   MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node));
133
134   ArchOpcode opcode;
135   // TODO(titzer): signed/unsigned small loads
136   switch (rep) {
137     case kRepFloat32:
138       opcode = kIA32Movss;
139       break;
140     case kRepFloat64:
141       opcode = kIA32Movsd;
142       break;
143     case kRepBit:  // Fall through.
144     case kRepWord8:
145       opcode = typ == kTypeInt32 ? kIA32Movsxbl : kIA32Movzxbl;
146       break;
147     case kRepWord16:
148       opcode = typ == kTypeInt32 ? kIA32Movsxwl : kIA32Movzxwl;
149       break;
150     case kRepTagged:  // Fall through.
151     case kRepWord32:
152       opcode = kIA32Movl;
153       break;
154     default:
155       UNREACHABLE();
156       return;
157   }
158
159   IA32OperandGenerator g(this);
160   InstructionOperand outputs[1];
161   outputs[0] = g.DefineAsRegister(node);
162   InstructionOperand inputs[3];
163   size_t input_count = 0;
164   AddressingMode mode =
165       g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
166   InstructionCode code = opcode | AddressingModeField::encode(mode);
167   Emit(code, 1, outputs, input_count, inputs);
168 }
169
170
171 void InstructionSelector::VisitStore(Node* node) {
172   IA32OperandGenerator g(this);
173   Node* base = node->InputAt(0);
174   Node* index = node->InputAt(1);
175   Node* value = node->InputAt(2);
176
177   StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
178   MachineType rep = RepresentationOf(store_rep.machine_type());
179   if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
180     DCHECK_EQ(kRepTagged, rep);
181     // TODO(dcarney): refactor RecordWrite function to take temp registers
182     //                and pass them here instead of using fixed regs
183     // TODO(dcarney): handle immediate indices.
184     InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister(edx)};
185     Emit(kIA32StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx),
186          g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps),
187          temps);
188     return;
189   }
190   DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
191
192   ArchOpcode opcode;
193   switch (rep) {
194     case kRepFloat32:
195       opcode = kIA32Movss;
196       break;
197     case kRepFloat64:
198       opcode = kIA32Movsd;
199       break;
200     case kRepBit:  // Fall through.
201     case kRepWord8:
202       opcode = kIA32Movb;
203       break;
204     case kRepWord16:
205       opcode = kIA32Movw;
206       break;
207     case kRepTagged:  // Fall through.
208     case kRepWord32:
209       opcode = kIA32Movl;
210       break;
211     default:
212       UNREACHABLE();
213       return;
214   }
215
216   InstructionOperand val;
217   if (g.CanBeImmediate(value)) {
218     val = g.UseImmediate(value);
219   } else if (rep == kRepWord8 || rep == kRepBit) {
220     val = g.UseByteRegister(value);
221   } else {
222     val = g.UseRegister(value);
223   }
224
225   InstructionOperand inputs[4];
226   size_t input_count = 0;
227   AddressingMode mode =
228       g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
229   InstructionCode code = opcode | AddressingModeField::encode(mode);
230   inputs[input_count++] = val;
231   Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs);
232 }
233
234
235 void InstructionSelector::VisitCheckedLoad(Node* node) {
236   MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
237   MachineType typ = TypeOf(OpParameter<MachineType>(node));
238   IA32OperandGenerator g(this);
239   Node* const buffer = node->InputAt(0);
240   Node* const offset = node->InputAt(1);
241   Node* const length = node->InputAt(2);
242   ArchOpcode opcode;
243   switch (rep) {
244     case kRepWord8:
245       opcode = typ == kTypeInt32 ? kCheckedLoadInt8 : kCheckedLoadUint8;
246       break;
247     case kRepWord16:
248       opcode = typ == kTypeInt32 ? kCheckedLoadInt16 : kCheckedLoadUint16;
249       break;
250     case kRepWord32:
251       opcode = kCheckedLoadWord32;
252       break;
253     case kRepFloat32:
254       opcode = kCheckedLoadFloat32;
255       break;
256     case kRepFloat64:
257       opcode = kCheckedLoadFloat64;
258       break;
259     default:
260       UNREACHABLE();
261       return;
262   }
263   InstructionOperand offset_operand = g.UseRegister(offset);
264   InstructionOperand length_operand =
265       g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
266   if (g.CanBeImmediate(buffer)) {
267     Emit(opcode | AddressingModeField::encode(kMode_MRI),
268          g.DefineAsRegister(node), offset_operand, length_operand,
269          offset_operand, g.UseImmediate(buffer));
270   } else {
271     Emit(opcode | AddressingModeField::encode(kMode_MR1),
272          g.DefineAsRegister(node), offset_operand, length_operand,
273          g.UseRegister(buffer), offset_operand);
274   }
275 }
276
277
278 void InstructionSelector::VisitCheckedStore(Node* node) {
279   MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
280   IA32OperandGenerator g(this);
281   Node* const buffer = node->InputAt(0);
282   Node* const offset = node->InputAt(1);
283   Node* const length = node->InputAt(2);
284   Node* const value = node->InputAt(3);
285   ArchOpcode opcode;
286   switch (rep) {
287     case kRepWord8:
288       opcode = kCheckedStoreWord8;
289       break;
290     case kRepWord16:
291       opcode = kCheckedStoreWord16;
292       break;
293     case kRepWord32:
294       opcode = kCheckedStoreWord32;
295       break;
296     case kRepFloat32:
297       opcode = kCheckedStoreFloat32;
298       break;
299     case kRepFloat64:
300       opcode = kCheckedStoreFloat64;
301       break;
302     default:
303       UNREACHABLE();
304       return;
305   }
306   InstructionOperand value_operand =
307       g.CanBeImmediate(value)
308           ? g.UseImmediate(value)
309           : ((rep == kRepWord8 || rep == kRepBit) ? g.UseByteRegister(value)
310                                                   : g.UseRegister(value));
311   InstructionOperand offset_operand = g.UseRegister(offset);
312   InstructionOperand length_operand =
313       g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
314   if (g.CanBeImmediate(buffer)) {
315     Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
316          offset_operand, length_operand, value_operand, offset_operand,
317          g.UseImmediate(buffer));
318   } else {
319     Emit(opcode | AddressingModeField::encode(kMode_MR1), g.NoOutput(),
320          offset_operand, length_operand, value_operand, g.UseRegister(buffer),
321          offset_operand);
322   }
323 }
324
325
326 // Shared routine for multiple binary operations.
327 static void VisitBinop(InstructionSelector* selector, Node* node,
328                        InstructionCode opcode, FlagsContinuation* cont) {
329   IA32OperandGenerator g(selector);
330   Int32BinopMatcher m(node);
331   Node* left = m.left().node();
332   Node* right = m.right().node();
333   InstructionOperand inputs[4];
334   size_t input_count = 0;
335   InstructionOperand outputs[2];
336   size_t output_count = 0;
337
338   // TODO(turbofan): match complex addressing modes.
339   if (left == right) {
340     // If both inputs refer to the same operand, enforce allocating a register
341     // for both of them to ensure that we don't end up generating code like
342     // this:
343     //
344     //   mov eax, [ebp-0x10]
345     //   add eax, [ebp-0x10]
346     //   jo label
347     InstructionOperand const input = g.UseRegister(left);
348     inputs[input_count++] = input;
349     inputs[input_count++] = input;
350   } else if (g.CanBeImmediate(right)) {
351     inputs[input_count++] = g.UseRegister(left);
352     inputs[input_count++] = g.UseImmediate(right);
353   } else {
354     if (node->op()->HasProperty(Operator::kCommutative) &&
355         g.CanBeBetterLeftOperand(right)) {
356       std::swap(left, right);
357     }
358     inputs[input_count++] = g.UseRegister(left);
359     inputs[input_count++] = g.Use(right);
360   }
361
362   if (cont->IsBranch()) {
363     inputs[input_count++] = g.Label(cont->true_block());
364     inputs[input_count++] = g.Label(cont->false_block());
365   }
366
367   outputs[output_count++] = g.DefineSameAsFirst(node);
368   if (cont->IsSet()) {
369     // TODO(turbofan): Use byte register here.
370     outputs[output_count++] = g.DefineAsRegister(cont->result());
371   }
372
373   DCHECK_NE(0u, input_count);
374   DCHECK_NE(0u, output_count);
375   DCHECK_GE(arraysize(inputs), input_count);
376   DCHECK_GE(arraysize(outputs), output_count);
377
378   Instruction* instr = selector->Emit(cont->Encode(opcode), output_count,
379                                       outputs, input_count, inputs);
380   if (cont->IsBranch()) instr->MarkAsControl();
381 }
382
383
384 // Shared routine for multiple binary operations.
385 static void VisitBinop(InstructionSelector* selector, Node* node,
386                        InstructionCode opcode) {
387   FlagsContinuation cont;
388   VisitBinop(selector, node, opcode, &cont);
389 }
390
391
392 void InstructionSelector::VisitWord32And(Node* node) {
393   VisitBinop(this, node, kIA32And);
394 }
395
396
397 void InstructionSelector::VisitWord32Or(Node* node) {
398   VisitBinop(this, node, kIA32Or);
399 }
400
401
402 void InstructionSelector::VisitWord32Xor(Node* node) {
403   IA32OperandGenerator g(this);
404   Int32BinopMatcher m(node);
405   if (m.right().Is(-1)) {
406     Emit(kIA32Not, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()));
407   } else {
408     VisitBinop(this, node, kIA32Xor);
409   }
410 }
411
412
413 // Shared routine for multiple shift operations.
414 static inline void VisitShift(InstructionSelector* selector, Node* node,
415                               ArchOpcode opcode) {
416   IA32OperandGenerator g(selector);
417   Node* left = node->InputAt(0);
418   Node* right = node->InputAt(1);
419
420   if (g.CanBeImmediate(right)) {
421     selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
422                    g.UseImmediate(right));
423   } else {
424     selector->Emit(opcode, g.DefineSameAsFirst(node), g.UseRegister(left),
425                    g.UseFixed(right, ecx));
426   }
427 }
428
429
430 namespace {
431
432 void VisitMulHigh(InstructionSelector* selector, Node* node,
433                   ArchOpcode opcode) {
434   IA32OperandGenerator g(selector);
435   selector->Emit(opcode, g.DefineAsFixed(node, edx),
436                  g.UseFixed(node->InputAt(0), eax),
437                  g.UseUniqueRegister(node->InputAt(1)));
438 }
439
440
441 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
442   IA32OperandGenerator g(selector);
443   InstructionOperand temps[] = {g.TempRegister(edx)};
444   selector->Emit(opcode, g.DefineAsFixed(node, eax),
445                  g.UseFixed(node->InputAt(0), eax),
446                  g.UseUnique(node->InputAt(1)), arraysize(temps), temps);
447 }
448
449
450 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
451   IA32OperandGenerator g(selector);
452   selector->Emit(opcode, g.DefineAsFixed(node, edx),
453                  g.UseFixed(node->InputAt(0), eax),
454                  g.UseUnique(node->InputAt(1)));
455 }
456
457 void EmitLea(InstructionSelector* selector, Node* result, Node* index,
458              int scale, Node* base, Node* displacement) {
459   IA32OperandGenerator g(selector);
460   InstructionOperand inputs[4];
461   size_t input_count = 0;
462   AddressingMode mode = g.GenerateMemoryOperandInputs(
463       index, scale, base, displacement, inputs, &input_count);
464
465   DCHECK_NE(0, static_cast<int>(input_count));
466   DCHECK_GE(arraysize(inputs), input_count);
467
468   InstructionOperand outputs[1];
469   outputs[0] = g.DefineAsRegister(result);
470
471   InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea;
472
473   selector->Emit(opcode, 1, outputs, input_count, inputs);
474 }
475
476 }  // namespace
477
478
479 void InstructionSelector::VisitWord32Shl(Node* node) {
480   Int32ScaleMatcher m(node, true);
481   if (m.matches()) {
482     Node* index = node->InputAt(0);
483     Node* base = m.power_of_two_plus_one() ? index : NULL;
484     EmitLea(this, node, index, m.scale(), base, NULL);
485     return;
486   }
487   VisitShift(this, node, kIA32Shl);
488 }
489
490
491 void InstructionSelector::VisitWord32Shr(Node* node) {
492   VisitShift(this, node, kIA32Shr);
493 }
494
495
496 void InstructionSelector::VisitWord32Sar(Node* node) {
497   VisitShift(this, node, kIA32Sar);
498 }
499
500
501 void InstructionSelector::VisitWord32Ror(Node* node) {
502   VisitShift(this, node, kIA32Ror);
503 }
504
505
506 void InstructionSelector::VisitInt32Add(Node* node) {
507   IA32OperandGenerator g(this);
508
509   // Try to match the Add to a lea pattern
510   BaseWithIndexAndDisplacement32Matcher m(node);
511   if (m.matches() &&
512       (m.displacement() == NULL || g.CanBeImmediate(m.displacement()))) {
513     InstructionOperand inputs[4];
514     size_t input_count = 0;
515     AddressingMode mode = g.GenerateMemoryOperandInputs(
516         m.index(), m.scale(), m.base(), m.displacement(), inputs, &input_count);
517
518     DCHECK_NE(0, static_cast<int>(input_count));
519     DCHECK_GE(arraysize(inputs), input_count);
520
521     InstructionOperand outputs[1];
522     outputs[0] = g.DefineAsRegister(node);
523
524     InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea;
525     Emit(opcode, 1, outputs, input_count, inputs);
526     return;
527   }
528
529   // No lea pattern match, use add
530   VisitBinop(this, node, kIA32Add);
531 }
532
533
534 void InstructionSelector::VisitInt32Sub(Node* node) {
535   IA32OperandGenerator g(this);
536   Int32BinopMatcher m(node);
537   if (m.left().Is(0)) {
538     Emit(kIA32Neg, g.DefineSameAsFirst(node), g.Use(m.right().node()));
539   } else {
540     VisitBinop(this, node, kIA32Sub);
541   }
542 }
543
544
545 void InstructionSelector::VisitInt32Mul(Node* node) {
546   Int32ScaleMatcher m(node, true);
547   if (m.matches()) {
548     Node* index = node->InputAt(0);
549     Node* base = m.power_of_two_plus_one() ? index : NULL;
550     EmitLea(this, node, index, m.scale(), base, NULL);
551     return;
552   }
553   IA32OperandGenerator g(this);
554   Node* left = node->InputAt(0);
555   Node* right = node->InputAt(1);
556   if (g.CanBeImmediate(right)) {
557     Emit(kIA32Imul, g.DefineAsRegister(node), g.Use(left),
558          g.UseImmediate(right));
559   } else {
560     if (g.CanBeBetterLeftOperand(right)) {
561       std::swap(left, right);
562     }
563     Emit(kIA32Imul, g.DefineSameAsFirst(node), g.UseRegister(left),
564          g.Use(right));
565   }
566 }
567
568
569 void InstructionSelector::VisitInt32MulHigh(Node* node) {
570   VisitMulHigh(this, node, kIA32ImulHigh);
571 }
572
573
574 void InstructionSelector::VisitUint32MulHigh(Node* node) {
575   VisitMulHigh(this, node, kIA32UmulHigh);
576 }
577
578
579 void InstructionSelector::VisitInt32Div(Node* node) {
580   VisitDiv(this, node, kIA32Idiv);
581 }
582
583
584 void InstructionSelector::VisitUint32Div(Node* node) {
585   VisitDiv(this, node, kIA32Udiv);
586 }
587
588
589 void InstructionSelector::VisitInt32Mod(Node* node) {
590   VisitMod(this, node, kIA32Idiv);
591 }
592
593
594 void InstructionSelector::VisitUint32Mod(Node* node) {
595   VisitMod(this, node, kIA32Udiv);
596 }
597
598
599 void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) {
600   IA32OperandGenerator g(this);
601   Emit(kSSECvtss2sd, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
602 }
603
604
605 void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
606   IA32OperandGenerator g(this);
607   Emit(kSSEInt32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
608 }
609
610
611 void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
612   IA32OperandGenerator g(this);
613   Emit(kSSEUint32ToFloat64, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
614 }
615
616
617 void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
618   IA32OperandGenerator g(this);
619   Emit(kSSEFloat64ToInt32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
620 }
621
622
623 void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
624   IA32OperandGenerator g(this);
625   Emit(kSSEFloat64ToUint32, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
626 }
627
628
629 void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
630   IA32OperandGenerator g(this);
631   Emit(kSSECvtsd2ss, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
632 }
633
634
635 void InstructionSelector::VisitFloat64Add(Node* node) {
636   IA32OperandGenerator g(this);
637   if (IsSupported(AVX)) {
638     Emit(kAVXFloat64Add, g.DefineAsRegister(node),
639          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
640   } else {
641     Emit(kSSEFloat64Add, g.DefineSameAsFirst(node),
642          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
643   }
644 }
645
646
647 void InstructionSelector::VisitFloat64Sub(Node* node) {
648   IA32OperandGenerator g(this);
649   if (IsSupported(AVX)) {
650     Emit(kAVXFloat64Sub, g.DefineAsRegister(node),
651          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
652   } else {
653     Emit(kSSEFloat64Sub, g.DefineSameAsFirst(node),
654          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
655   }
656 }
657
658
659 void InstructionSelector::VisitFloat64Mul(Node* node) {
660   IA32OperandGenerator g(this);
661   if (IsSupported(AVX)) {
662     Emit(kAVXFloat64Mul, g.DefineAsRegister(node),
663          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
664   } else {
665     Emit(kSSEFloat64Mul, g.DefineSameAsFirst(node),
666          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
667   }
668 }
669
670
671 void InstructionSelector::VisitFloat64Div(Node* node) {
672   IA32OperandGenerator g(this);
673   if (IsSupported(AVX)) {
674     Emit(kAVXFloat64Div, g.DefineAsRegister(node),
675          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
676   } else {
677     Emit(kSSEFloat64Div, g.DefineSameAsFirst(node),
678          g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
679   }
680 }
681
682
683 void InstructionSelector::VisitFloat64Mod(Node* node) {
684   IA32OperandGenerator g(this);
685   InstructionOperand temps[] = {g.TempRegister(eax)};
686   Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
687        g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1,
688        temps);
689 }
690
691
692 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
693   IA32OperandGenerator g(this);
694   Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
695 }
696
697
698 void InstructionSelector::VisitFloat64Floor(Node* node) {
699   DCHECK(CpuFeatures::IsSupported(SSE4_1));
700   VisitRRFloat64(this, kSSEFloat64Floor, node);
701 }
702
703
704 void InstructionSelector::VisitFloat64Ceil(Node* node) {
705   DCHECK(CpuFeatures::IsSupported(SSE4_1));
706   VisitRRFloat64(this, kSSEFloat64Ceil, node);
707 }
708
709
710 void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
711   DCHECK(CpuFeatures::IsSupported(SSE4_1));
712   VisitRRFloat64(this, kSSEFloat64RoundTruncate, node);
713 }
714
715
716 void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
717   UNREACHABLE();
718 }
719
720
721 void InstructionSelector::VisitCall(Node* node) {
722   IA32OperandGenerator g(this);
723   const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node);
724
725   FrameStateDescriptor* frame_state_descriptor = NULL;
726
727   if (descriptor->NeedsFrameState()) {
728     frame_state_descriptor =
729         GetFrameStateDescriptor(node->InputAt(descriptor->InputCount()));
730   }
731
732   CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
733
734   // Compute InstructionOperands for inputs and outputs.
735   InitializeCallBuffer(node, &buffer, true, true);
736
737   // Push any stack arguments.
738   for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
739        ++i) {
740     // TODO(titzer): handle pushing double parameters.
741     InstructionOperand value =
742         g.CanBeImmediate(*i) ? g.UseImmediate(*i) : IsSupported(ATOM)
743                                                         ? g.UseRegister(*i)
744                                                         : g.Use(*i);
745     Emit(kIA32Push, g.NoOutput(), value);
746   }
747
748   // Select the appropriate opcode based on the call type.
749   InstructionCode opcode;
750   switch (descriptor->kind()) {
751     case CallDescriptor::kCallCodeObject: {
752       opcode = kArchCallCodeObject;
753       break;
754     }
755     case CallDescriptor::kCallJSFunction:
756       opcode = kArchCallJSFunction;
757       break;
758     default:
759       UNREACHABLE();
760       return;
761   }
762   opcode |= MiscField::encode(descriptor->flags());
763
764   // Emit the call instruction.
765   InstructionOperand* first_output =
766       buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
767   Instruction* call_instr =
768       Emit(opcode, buffer.outputs.size(), first_output,
769            buffer.instruction_args.size(), &buffer.instruction_args.front());
770   call_instr->MarkAsCall();
771 }
772
773
774 namespace {
775
776 // Shared routine for multiple compare operations.
777 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
778                   InstructionOperand left, InstructionOperand right,
779                   FlagsContinuation* cont) {
780   IA32OperandGenerator g(selector);
781   if (cont->IsBranch()) {
782     selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right,
783                    g.Label(cont->true_block()),
784                    g.Label(cont->false_block()))->MarkAsControl();
785   } else {
786     DCHECK(cont->IsSet());
787     // TODO(titzer): Needs byte register.
788     selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()),
789                    left, right);
790   }
791 }
792
793
794 // Shared routine for multiple compare operations.
795 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
796                   Node* left, Node* right, FlagsContinuation* cont,
797                   bool commutative) {
798   IA32OperandGenerator g(selector);
799   if (commutative && g.CanBeBetterLeftOperand(right)) {
800     std::swap(left, right);
801   }
802   VisitCompare(selector, opcode, g.UseRegister(left), g.Use(right), cont);
803 }
804
805
806 // Shared routine for multiple float64 compare operations (inputs commuted).
807 void VisitFloat64Compare(InstructionSelector* selector, Node* node,
808                          FlagsContinuation* cont) {
809   Node* const left = node->InputAt(0);
810   Node* const right = node->InputAt(1);
811   VisitCompare(selector, kSSEFloat64Cmp, right, left, cont, false);
812 }
813
814
815 // Shared routine for multiple word compare operations.
816 void VisitWordCompare(InstructionSelector* selector, Node* node,
817                       InstructionCode opcode, FlagsContinuation* cont) {
818   IA32OperandGenerator g(selector);
819   Node* const left = node->InputAt(0);
820   Node* const right = node->InputAt(1);
821
822   // Match immediates on left or right side of comparison.
823   if (g.CanBeImmediate(right)) {
824     VisitCompare(selector, opcode, g.Use(left), g.UseImmediate(right), cont);
825   } else if (g.CanBeImmediate(left)) {
826     if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
827     VisitCompare(selector, opcode, g.Use(right), g.UseImmediate(left), cont);
828   } else {
829     VisitCompare(selector, opcode, left, right, cont,
830                  node->op()->HasProperty(Operator::kCommutative));
831   }
832 }
833
834
835 void VisitWordCompare(InstructionSelector* selector, Node* node,
836                       FlagsContinuation* cont) {
837   VisitWordCompare(selector, node, kIA32Cmp, cont);
838 }
839
840
841 // Shared routine for word comparison with zero.
842 void VisitWordCompareZero(InstructionSelector* selector, Node* user,
843                           Node* value, FlagsContinuation* cont) {
844   // Try to combine the branch with a comparison.
845   while (selector->CanCover(user, value)) {
846     switch (value->opcode()) {
847       case IrOpcode::kWord32Equal: {
848         // Try to combine with comparisons against 0 by simply inverting the
849         // continuation.
850         Int32BinopMatcher m(value);
851         if (m.right().Is(0)) {
852           user = value;
853           value = m.left().node();
854           cont->Negate();
855           continue;
856         }
857         cont->OverwriteAndNegateIfEqual(kEqual);
858         return VisitWordCompare(selector, value, cont);
859       }
860       case IrOpcode::kInt32LessThan:
861         cont->OverwriteAndNegateIfEqual(kSignedLessThan);
862         return VisitWordCompare(selector, value, cont);
863       case IrOpcode::kInt32LessThanOrEqual:
864         cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
865         return VisitWordCompare(selector, value, cont);
866       case IrOpcode::kUint32LessThan:
867         cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
868         return VisitWordCompare(selector, value, cont);
869       case IrOpcode::kUint32LessThanOrEqual:
870         cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
871         return VisitWordCompare(selector, value, cont);
872       case IrOpcode::kFloat64Equal:
873         cont->OverwriteAndNegateIfEqual(kUnorderedEqual);
874         return VisitFloat64Compare(selector, value, cont);
875       case IrOpcode::kFloat64LessThan:
876         cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThan);
877         return VisitFloat64Compare(selector, value, cont);
878       case IrOpcode::kFloat64LessThanOrEqual:
879         cont->OverwriteAndNegateIfEqual(kUnsignedGreaterThanOrEqual);
880         return VisitFloat64Compare(selector, value, cont);
881       case IrOpcode::kProjection:
882         // Check if this is the overflow output projection of an
883         // <Operation>WithOverflow node.
884         if (ProjectionIndexOf(value->op()) == 1u) {
885           // We cannot combine the <Operation>WithOverflow with this branch
886           // unless the 0th projection (the use of the actual value of the
887           // <Operation> is either NULL, which means there's no use of the
888           // actual value, or was already defined, which means it is scheduled
889           // *AFTER* this branch).
890           Node* const node = value->InputAt(0);
891           Node* const result = NodeProperties::FindProjection(node, 0);
892           if (result == NULL || selector->IsDefined(result)) {
893             switch (node->opcode()) {
894               case IrOpcode::kInt32AddWithOverflow:
895                 cont->OverwriteAndNegateIfEqual(kOverflow);
896                 return VisitBinop(selector, node, kIA32Add, cont);
897               case IrOpcode::kInt32SubWithOverflow:
898                 cont->OverwriteAndNegateIfEqual(kOverflow);
899                 return VisitBinop(selector, node, kIA32Sub, cont);
900               default:
901                 break;
902             }
903           }
904         }
905         break;
906       case IrOpcode::kInt32Sub:
907         return VisitWordCompare(selector, value, cont);
908       case IrOpcode::kWord32And:
909         return VisitWordCompare(selector, value, kIA32Test, cont);
910       default:
911         break;
912     }
913     break;
914   }
915
916   // Continuation could not be combined with a compare, emit compare against 0.
917   IA32OperandGenerator g(selector);
918   VisitCompare(selector, kIA32Cmp, g.Use(value), g.TempImmediate(0), cont);
919 }
920
921 }  // namespace
922
923
924 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
925                                       BasicBlock* fbranch) {
926   FlagsContinuation cont(kNotEqual, tbranch, fbranch);
927   VisitWordCompareZero(this, branch, branch->InputAt(0), &cont);
928 }
929
930
931 void InstructionSelector::VisitSwitch(Node* node, BasicBlock* default_branch,
932                                       BasicBlock** case_branches,
933                                       int32_t* case_values, size_t case_count,
934                                       int32_t min_value, int32_t max_value) {
935   IA32OperandGenerator g(this);
936   InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
937   InstructionOperand default_operand = g.Label(default_branch);
938
939   // Note that {value_range} can be 0 if {min_value} is -2^31 and {max_value}
940   // is 2^31-1, so don't assume that it's non-zero below.
941   size_t value_range =
942       1u + bit_cast<uint32_t>(max_value) - bit_cast<uint32_t>(min_value);
943
944   // Determine whether to issue an ArchTableSwitch or an ArchLookupSwitch
945   // instruction.
946   size_t table_space_cost = 4 + value_range;
947   size_t table_time_cost = 3;
948   size_t lookup_space_cost = 3 + 2 * case_count;
949   size_t lookup_time_cost = case_count;
950   if (case_count > 4 &&
951       table_space_cost + 3 * table_time_cost <=
952           lookup_space_cost + 3 * lookup_time_cost &&
953       min_value > std::numeric_limits<int32_t>::min()) {
954     InstructionOperand index_operand = value_operand;
955     if (min_value) {
956       index_operand = g.TempRegister();
957       Emit(kIA32Lea | AddressingModeField::encode(kMode_MRI), index_operand,
958            value_operand, g.TempImmediate(-min_value));
959     }
960     size_t input_count = 2 + value_range;
961     auto* inputs = zone()->NewArray<InstructionOperand>(input_count);
962     inputs[0] = index_operand;
963     std::fill(&inputs[1], &inputs[input_count], default_operand);
964     for (size_t index = 0; index < case_count; ++index) {
965       size_t value = case_values[index] - min_value;
966       BasicBlock* branch = case_branches[index];
967       DCHECK_LE(0u, value);
968       DCHECK_LT(value + 2, input_count);
969       inputs[value + 2] = g.Label(branch);
970     }
971     Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr)
972         ->MarkAsControl();
973     return;
974   }
975
976   // Generate a sequence of conditional jumps.
977   size_t input_count = 2 + case_count * 2;
978   auto* inputs = zone()->NewArray<InstructionOperand>(input_count);
979   inputs[0] = value_operand;
980   inputs[1] = default_operand;
981   for (size_t index = 0; index < case_count; ++index) {
982     int32_t value = case_values[index];
983     BasicBlock* branch = case_branches[index];
984     inputs[index * 2 + 2 + 0] = g.TempImmediate(value);
985     inputs[index * 2 + 2 + 1] = g.Label(branch);
986   }
987   Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr)
988       ->MarkAsControl();
989 }
990
991
992 void InstructionSelector::VisitWord32Equal(Node* const node) {
993   FlagsContinuation cont(kEqual, node);
994   Int32BinopMatcher m(node);
995   if (m.right().Is(0)) {
996     return VisitWordCompareZero(this, m.node(), m.left().node(), &cont);
997   }
998   VisitWordCompare(this, node, &cont);
999 }
1000
1001
1002 void InstructionSelector::VisitInt32LessThan(Node* node) {
1003   FlagsContinuation cont(kSignedLessThan, node);
1004   VisitWordCompare(this, node, &cont);
1005 }
1006
1007
1008 void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
1009   FlagsContinuation cont(kSignedLessThanOrEqual, node);
1010   VisitWordCompare(this, node, &cont);
1011 }
1012
1013
1014 void InstructionSelector::VisitUint32LessThan(Node* node) {
1015   FlagsContinuation cont(kUnsignedLessThan, node);
1016   VisitWordCompare(this, node, &cont);
1017 }
1018
1019
1020 void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
1021   FlagsContinuation cont(kUnsignedLessThanOrEqual, node);
1022   VisitWordCompare(this, node, &cont);
1023 }
1024
1025
1026 void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
1027   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1028     FlagsContinuation cont(kOverflow, ovf);
1029     return VisitBinop(this, node, kIA32Add, &cont);
1030   }
1031   FlagsContinuation cont;
1032   VisitBinop(this, node, kIA32Add, &cont);
1033 }
1034
1035
1036 void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
1037   if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
1038     FlagsContinuation cont(kOverflow, ovf);
1039     return VisitBinop(this, node, kIA32Sub, &cont);
1040   }
1041   FlagsContinuation cont;
1042   VisitBinop(this, node, kIA32Sub, &cont);
1043 }
1044
1045
1046 void InstructionSelector::VisitFloat64Equal(Node* node) {
1047   FlagsContinuation cont(kUnorderedEqual, node);
1048   VisitFloat64Compare(this, node, &cont);
1049 }
1050
1051
1052 void InstructionSelector::VisitFloat64LessThan(Node* node) {
1053   FlagsContinuation cont(kUnsignedGreaterThan, node);
1054   VisitFloat64Compare(this, node, &cont);
1055 }
1056
1057
1058 void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
1059   FlagsContinuation cont(kUnsignedGreaterThanOrEqual, node);
1060   VisitFloat64Compare(this, node, &cont);
1061 }
1062
1063
1064 // static
1065 MachineOperatorBuilder::Flags
1066 InstructionSelector::SupportedMachineOperatorFlags() {
1067   if (CpuFeatures::IsSupported(SSE4_1)) {
1068     return MachineOperatorBuilder::kFloat64Floor |
1069            MachineOperatorBuilder::kFloat64Ceil |
1070            MachineOperatorBuilder::kFloat64RoundTruncate |
1071            MachineOperatorBuilder::kWord32ShiftIsSafe;
1072   }
1073   return MachineOperatorBuilder::Flag::kNoFlags;
1074 }
1075
1076 }  // namespace compiler
1077 }  // namespace internal
1078 }  // namespace v8