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