blob: b8ca3ba692ac1f537e249984a191075eaf405389 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/base/adapters.h"
6#include "src/compiler/instruction-selector-impl.h"
7#include "src/compiler/node-matchers.h"
8#include "src/compiler/node-properties.h"
9#include "src/ppc/frames-ppc.h"
10
11namespace v8 {
12namespace internal {
13namespace compiler {
14
15enum ImmediateMode {
16 kInt16Imm,
17 kInt16Imm_Unsigned,
18 kInt16Imm_Negate,
19 kInt16Imm_4ByteAligned,
20 kShift32Imm,
21 kShift64Imm,
22 kNoImmediate
23};
24
25
26// Adds PPC-specific methods for generating operands.
27class PPCOperandGenerator final : public OperandGenerator {
28 public:
29 explicit PPCOperandGenerator(InstructionSelector* selector)
30 : OperandGenerator(selector) {}
31
32 InstructionOperand UseOperand(Node* node, ImmediateMode mode) {
33 if (CanBeImmediate(node, mode)) {
34 return UseImmediate(node);
35 }
36 return UseRegister(node);
37 }
38
39 bool CanBeImmediate(Node* node, ImmediateMode mode) {
40 int64_t value;
41 if (node->opcode() == IrOpcode::kInt32Constant)
42 value = OpParameter<int32_t>(node);
43 else if (node->opcode() == IrOpcode::kInt64Constant)
44 value = OpParameter<int64_t>(node);
45 else
46 return false;
47 return CanBeImmediate(value, mode);
48 }
49
50 bool CanBeImmediate(int64_t value, ImmediateMode mode) {
51 switch (mode) {
52 case kInt16Imm:
53 return is_int16(value);
54 case kInt16Imm_Unsigned:
55 return is_uint16(value);
56 case kInt16Imm_Negate:
57 return is_int16(-value);
58 case kInt16Imm_4ByteAligned:
59 return is_int16(value) && !(value & 3);
60 case kShift32Imm:
61 return 0 <= value && value < 32;
62 case kShift64Imm:
63 return 0 <= value && value < 64;
64 case kNoImmediate:
65 return false;
66 }
67 return false;
68 }
69};
70
71
72namespace {
73
Ben Murdochda12d292016-06-02 14:46:10 +010074void VisitRR(InstructionSelector* selector, InstructionCode opcode,
75 Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076 PPCOperandGenerator g(selector);
77 selector->Emit(opcode, g.DefineAsRegister(node),
78 g.UseRegister(node->InputAt(0)));
79}
80
Ben Murdochda12d292016-06-02 14:46:10 +010081void VisitRRR(InstructionSelector* selector, InstructionCode opcode,
82 Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 PPCOperandGenerator g(selector);
84 selector->Emit(opcode, g.DefineAsRegister(node),
85 g.UseRegister(node->InputAt(0)),
86 g.UseRegister(node->InputAt(1)));
87}
88
Ben Murdochda12d292016-06-02 14:46:10 +010089void VisitRRO(InstructionSelector* selector, InstructionCode opcode, Node* node,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 ImmediateMode operand_mode) {
91 PPCOperandGenerator g(selector);
92 selector->Emit(opcode, g.DefineAsRegister(node),
93 g.UseRegister(node->InputAt(0)),
94 g.UseOperand(node->InputAt(1), operand_mode));
95}
96
97
98#if V8_TARGET_ARCH_PPC64
Ben Murdochda12d292016-06-02 14:46:10 +010099void VisitTryTruncateDouble(InstructionSelector* selector,
100 InstructionCode opcode, Node* node) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000101 PPCOperandGenerator g(selector);
102 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0))};
103 InstructionOperand outputs[2];
104 size_t output_count = 0;
105 outputs[output_count++] = g.DefineAsRegister(node);
106
107 Node* success_output = NodeProperties::FindProjection(node, 1);
108 if (success_output) {
109 outputs[output_count++] = g.DefineAsRegister(success_output);
110 }
111
112 selector->Emit(opcode, output_count, outputs, 1, inputs);
113}
114#endif
115
116
117// Shared routine for multiple binary operations.
118template <typename Matcher>
119void VisitBinop(InstructionSelector* selector, Node* node,
120 InstructionCode opcode, ImmediateMode operand_mode,
121 FlagsContinuation* cont) {
122 PPCOperandGenerator g(selector);
123 Matcher m(node);
124 InstructionOperand inputs[4];
125 size_t input_count = 0;
126 InstructionOperand outputs[2];
127 size_t output_count = 0;
128
129 inputs[input_count++] = g.UseRegister(m.left().node());
130 inputs[input_count++] = g.UseOperand(m.right().node(), operand_mode);
131
132 if (cont->IsBranch()) {
133 inputs[input_count++] = g.Label(cont->true_block());
134 inputs[input_count++] = g.Label(cont->false_block());
135 }
136
137 outputs[output_count++] = g.DefineAsRegister(node);
138 if (cont->IsSet()) {
139 outputs[output_count++] = g.DefineAsRegister(cont->result());
140 }
141
142 DCHECK_NE(0u, input_count);
143 DCHECK_NE(0u, output_count);
144 DCHECK_GE(arraysize(inputs), input_count);
145 DCHECK_GE(arraysize(outputs), output_count);
146
Ben Murdochda12d292016-06-02 14:46:10 +0100147 opcode = cont->Encode(opcode);
148 if (cont->IsDeoptimize()) {
149 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs,
150 cont->frame_state());
151 } else {
152 selector->Emit(opcode, output_count, outputs, input_count, inputs);
153 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154}
155
156
157// Shared routine for multiple binary operations.
158template <typename Matcher>
Ben Murdochda12d292016-06-02 14:46:10 +0100159void VisitBinop(InstructionSelector* selector, Node* node,
160 InstructionCode opcode, ImmediateMode operand_mode) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000161 FlagsContinuation cont;
162 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont);
163}
164
165} // namespace
166
167
168void InstructionSelector::VisitLoad(Node* node) {
169 LoadRepresentation load_rep = LoadRepresentationOf(node->op());
170 PPCOperandGenerator g(this);
171 Node* base = node->InputAt(0);
172 Node* offset = node->InputAt(1);
173 ArchOpcode opcode = kArchNop;
174 ImmediateMode mode = kInt16Imm;
175 switch (load_rep.representation()) {
176 case MachineRepresentation::kFloat32:
177 opcode = kPPC_LoadFloat32;
178 break;
179 case MachineRepresentation::kFloat64:
180 opcode = kPPC_LoadDouble;
181 break;
182 case MachineRepresentation::kBit: // Fall through.
183 case MachineRepresentation::kWord8:
184 opcode = load_rep.IsSigned() ? kPPC_LoadWordS8 : kPPC_LoadWordU8;
185 break;
186 case MachineRepresentation::kWord16:
187 opcode = load_rep.IsSigned() ? kPPC_LoadWordS16 : kPPC_LoadWordU16;
188 break;
189#if !V8_TARGET_ARCH_PPC64
190 case MachineRepresentation::kTagged: // Fall through.
191#endif
192 case MachineRepresentation::kWord32:
Ben Murdochc5610432016-08-08 18:44:38 +0100193 opcode = kPPC_LoadWordU32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 break;
195#if V8_TARGET_ARCH_PPC64
196 case MachineRepresentation::kTagged: // Fall through.
197 case MachineRepresentation::kWord64:
198 opcode = kPPC_LoadWord64;
199 mode = kInt16Imm_4ByteAligned;
200 break;
201#else
202 case MachineRepresentation::kWord64: // Fall through.
203#endif
Ben Murdoch097c5b22016-05-18 11:27:45 +0100204 case MachineRepresentation::kSimd128: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205 case MachineRepresentation::kNone:
206 UNREACHABLE();
207 return;
208 }
209 if (g.CanBeImmediate(offset, mode)) {
210 Emit(opcode | AddressingModeField::encode(kMode_MRI),
211 g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(offset));
212 } else if (g.CanBeImmediate(base, mode)) {
213 Emit(opcode | AddressingModeField::encode(kMode_MRI),
214 g.DefineAsRegister(node), g.UseRegister(offset), g.UseImmediate(base));
215 } else {
216 Emit(opcode | AddressingModeField::encode(kMode_MRR),
217 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(offset));
218 }
219}
220
221
222void InstructionSelector::VisitStore(Node* node) {
223 PPCOperandGenerator g(this);
224 Node* base = node->InputAt(0);
225 Node* offset = node->InputAt(1);
226 Node* value = node->InputAt(2);
227
228 StoreRepresentation store_rep = StoreRepresentationOf(node->op());
229 WriteBarrierKind write_barrier_kind = store_rep.write_barrier_kind();
230 MachineRepresentation rep = store_rep.representation();
231
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232 if (write_barrier_kind != kNoWriteBarrier) {
233 DCHECK_EQ(MachineRepresentation::kTagged, rep);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100234 AddressingMode addressing_mode;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000235 InstructionOperand inputs[3];
236 size_t input_count = 0;
237 inputs[input_count++] = g.UseUniqueRegister(base);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100238 // OutOfLineRecordWrite uses the offset in an 'add' instruction as well as
239 // for the store itself, so we must check compatibility with both.
240 if (g.CanBeImmediate(offset, kInt16Imm)
241#if V8_TARGET_ARCH_PPC64
242 && g.CanBeImmediate(offset, kInt16Imm_4ByteAligned)
243#endif
244 ) {
245 inputs[input_count++] = g.UseImmediate(offset);
246 addressing_mode = kMode_MRI;
247 } else {
248 inputs[input_count++] = g.UseUniqueRegister(offset);
249 addressing_mode = kMode_MRR;
250 }
Ben Murdochda12d292016-06-02 14:46:10 +0100251 inputs[input_count++] = g.UseUniqueRegister(value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 RecordWriteMode record_write_mode = RecordWriteMode::kValueIsAny;
253 switch (write_barrier_kind) {
254 case kNoWriteBarrier:
255 UNREACHABLE();
256 break;
257 case kMapWriteBarrier:
258 record_write_mode = RecordWriteMode::kValueIsMap;
259 break;
260 case kPointerWriteBarrier:
261 record_write_mode = RecordWriteMode::kValueIsPointer;
262 break;
263 case kFullWriteBarrier:
264 record_write_mode = RecordWriteMode::kValueIsAny;
265 break;
266 }
267 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
268 size_t const temp_count = arraysize(temps);
269 InstructionCode code = kArchStoreWithWriteBarrier;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100270 code |= AddressingModeField::encode(addressing_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 code |= MiscField::encode(static_cast<int>(record_write_mode));
272 Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
273 } else {
274 ArchOpcode opcode = kArchNop;
275 ImmediateMode mode = kInt16Imm;
276 switch (rep) {
277 case MachineRepresentation::kFloat32:
278 opcode = kPPC_StoreFloat32;
279 break;
280 case MachineRepresentation::kFloat64:
281 opcode = kPPC_StoreDouble;
282 break;
283 case MachineRepresentation::kBit: // Fall through.
284 case MachineRepresentation::kWord8:
285 opcode = kPPC_StoreWord8;
286 break;
287 case MachineRepresentation::kWord16:
288 opcode = kPPC_StoreWord16;
289 break;
290#if !V8_TARGET_ARCH_PPC64
291 case MachineRepresentation::kTagged: // Fall through.
292#endif
293 case MachineRepresentation::kWord32:
294 opcode = kPPC_StoreWord32;
295 break;
296#if V8_TARGET_ARCH_PPC64
297 case MachineRepresentation::kTagged: // Fall through.
298 case MachineRepresentation::kWord64:
299 opcode = kPPC_StoreWord64;
300 mode = kInt16Imm_4ByteAligned;
301 break;
302#else
303 case MachineRepresentation::kWord64: // Fall through.
304#endif
Ben Murdoch097c5b22016-05-18 11:27:45 +0100305 case MachineRepresentation::kSimd128: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 case MachineRepresentation::kNone:
307 UNREACHABLE();
308 return;
309 }
310 if (g.CanBeImmediate(offset, mode)) {
311 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
312 g.UseRegister(base), g.UseImmediate(offset), g.UseRegister(value));
313 } else if (g.CanBeImmediate(base, mode)) {
314 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
315 g.UseRegister(offset), g.UseImmediate(base), g.UseRegister(value));
316 } else {
317 Emit(opcode | AddressingModeField::encode(kMode_MRR), g.NoOutput(),
318 g.UseRegister(base), g.UseRegister(offset), g.UseRegister(value));
319 }
320 }
321}
322
323
324void InstructionSelector::VisitCheckedLoad(Node* node) {
325 CheckedLoadRepresentation load_rep = CheckedLoadRepresentationOf(node->op());
326 PPCOperandGenerator g(this);
327 Node* const base = node->InputAt(0);
328 Node* const offset = node->InputAt(1);
329 Node* const length = node->InputAt(2);
330 ArchOpcode opcode = kArchNop;
331 switch (load_rep.representation()) {
332 case MachineRepresentation::kWord8:
333 opcode = load_rep.IsSigned() ? kCheckedLoadInt8 : kCheckedLoadUint8;
334 break;
335 case MachineRepresentation::kWord16:
336 opcode = load_rep.IsSigned() ? kCheckedLoadInt16 : kCheckedLoadUint16;
337 break;
338 case MachineRepresentation::kWord32:
339 opcode = kCheckedLoadWord32;
340 break;
341#if V8_TARGET_ARCH_PPC64
342 case MachineRepresentation::kWord64:
343 opcode = kCheckedLoadWord64;
344 break;
345#endif
346 case MachineRepresentation::kFloat32:
347 opcode = kCheckedLoadFloat32;
348 break;
349 case MachineRepresentation::kFloat64:
350 opcode = kCheckedLoadFloat64;
351 break;
352 case MachineRepresentation::kBit: // Fall through.
353 case MachineRepresentation::kTagged: // Fall through.
354#if !V8_TARGET_ARCH_PPC64
355 case MachineRepresentation::kWord64: // Fall through.
356#endif
Ben Murdoch097c5b22016-05-18 11:27:45 +0100357 case MachineRepresentation::kSimd128: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358 case MachineRepresentation::kNone:
359 UNREACHABLE();
360 return;
361 }
362 AddressingMode addressingMode = kMode_MRR;
363 Emit(opcode | AddressingModeField::encode(addressingMode),
364 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(offset),
365 g.UseOperand(length, kInt16Imm_Unsigned));
366}
367
368
369void InstructionSelector::VisitCheckedStore(Node* node) {
370 MachineRepresentation rep = CheckedStoreRepresentationOf(node->op());
371 PPCOperandGenerator g(this);
372 Node* const base = node->InputAt(0);
373 Node* const offset = node->InputAt(1);
374 Node* const length = node->InputAt(2);
375 Node* const value = node->InputAt(3);
376 ArchOpcode opcode = kArchNop;
377 switch (rep) {
378 case MachineRepresentation::kWord8:
379 opcode = kCheckedStoreWord8;
380 break;
381 case MachineRepresentation::kWord16:
382 opcode = kCheckedStoreWord16;
383 break;
384 case MachineRepresentation::kWord32:
385 opcode = kCheckedStoreWord32;
386 break;
387#if V8_TARGET_ARCH_PPC64
388 case MachineRepresentation::kWord64:
389 opcode = kCheckedStoreWord64;
390 break;
391#endif
392 case MachineRepresentation::kFloat32:
393 opcode = kCheckedStoreFloat32;
394 break;
395 case MachineRepresentation::kFloat64:
396 opcode = kCheckedStoreFloat64;
397 break;
398 case MachineRepresentation::kBit: // Fall through.
399 case MachineRepresentation::kTagged: // Fall through.
400#if !V8_TARGET_ARCH_PPC64
401 case MachineRepresentation::kWord64: // Fall through.
402#endif
Ben Murdoch097c5b22016-05-18 11:27:45 +0100403 case MachineRepresentation::kSimd128: // Fall through.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404 case MachineRepresentation::kNone:
405 UNREACHABLE();
406 return;
407 }
408 AddressingMode addressingMode = kMode_MRR;
409 Emit(opcode | AddressingModeField::encode(addressingMode), g.NoOutput(),
410 g.UseRegister(base), g.UseRegister(offset),
411 g.UseOperand(length, kInt16Imm_Unsigned), g.UseRegister(value));
412}
413
414
415template <typename Matcher>
416static void VisitLogical(InstructionSelector* selector, Node* node, Matcher* m,
417 ArchOpcode opcode, bool left_can_cover,
418 bool right_can_cover, ImmediateMode imm_mode) {
419 PPCOperandGenerator g(selector);
420
421 // Map instruction to equivalent operation with inverted right input.
422 ArchOpcode inv_opcode = opcode;
423 switch (opcode) {
424 case kPPC_And:
425 inv_opcode = kPPC_AndComplement;
426 break;
427 case kPPC_Or:
428 inv_opcode = kPPC_OrComplement;
429 break;
430 default:
431 UNREACHABLE();
432 }
433
434 // Select Logical(y, ~x) for Logical(Xor(x, -1), y).
435 if ((m->left().IsWord32Xor() || m->left().IsWord64Xor()) && left_can_cover) {
436 Matcher mleft(m->left().node());
437 if (mleft.right().Is(-1)) {
438 selector->Emit(inv_opcode, g.DefineAsRegister(node),
439 g.UseRegister(m->right().node()),
440 g.UseRegister(mleft.left().node()));
441 return;
442 }
443 }
444
445 // Select Logical(x, ~y) for Logical(x, Xor(y, -1)).
446 if ((m->right().IsWord32Xor() || m->right().IsWord64Xor()) &&
447 right_can_cover) {
448 Matcher mright(m->right().node());
449 if (mright.right().Is(-1)) {
450 // TODO(all): support shifted operand on right.
451 selector->Emit(inv_opcode, g.DefineAsRegister(node),
452 g.UseRegister(m->left().node()),
453 g.UseRegister(mright.left().node()));
454 return;
455 }
456 }
457
458 VisitBinop<Matcher>(selector, node, opcode, imm_mode);
459}
460
461
462static inline bool IsContiguousMask32(uint32_t value, int* mb, int* me) {
463 int mask_width = base::bits::CountPopulation32(value);
464 int mask_msb = base::bits::CountLeadingZeros32(value);
465 int mask_lsb = base::bits::CountTrailingZeros32(value);
466 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 32))
467 return false;
468 *mb = mask_lsb + mask_width - 1;
469 *me = mask_lsb;
470 return true;
471}
472
473
474#if V8_TARGET_ARCH_PPC64
475static inline bool IsContiguousMask64(uint64_t value, int* mb, int* me) {
476 int mask_width = base::bits::CountPopulation64(value);
477 int mask_msb = base::bits::CountLeadingZeros64(value);
478 int mask_lsb = base::bits::CountTrailingZeros64(value);
479 if ((mask_width == 0) || (mask_msb + mask_width + mask_lsb != 64))
480 return false;
481 *mb = mask_lsb + mask_width - 1;
482 *me = mask_lsb;
483 return true;
484}
485#endif
486
487
488// TODO(mbrandy): Absorb rotate-right into rlwinm?
489void InstructionSelector::VisitWord32And(Node* node) {
490 PPCOperandGenerator g(this);
491 Int32BinopMatcher m(node);
492 int mb = 0;
493 int me = 0;
494 if (m.right().HasValue() && IsContiguousMask32(m.right().Value(), &mb, &me)) {
495 int sh = 0;
496 Node* left = m.left().node();
497 if ((m.left().IsWord32Shr() || m.left().IsWord32Shl()) &&
498 CanCover(node, left)) {
499 // Try to absorb left/right shift into rlwinm
500 Int32BinopMatcher mleft(m.left().node());
501 if (mleft.right().IsInRange(0, 31)) {
502 left = mleft.left().node();
503 sh = mleft.right().Value();
504 if (m.left().IsWord32Shr()) {
505 // Adjust the mask such that it doesn't include any rotated bits.
506 if (mb > 31 - sh) mb = 31 - sh;
507 sh = (32 - sh) & 0x1f;
508 } else {
509 // Adjust the mask such that it doesn't include any rotated bits.
510 if (me < sh) me = sh;
511 }
512 }
513 }
514 if (mb >= me) {
515 Emit(kPPC_RotLeftAndMask32, g.DefineAsRegister(node), g.UseRegister(left),
516 g.TempImmediate(sh), g.TempImmediate(mb), g.TempImmediate(me));
517 return;
518 }
519 }
520 VisitLogical<Int32BinopMatcher>(
521 this, node, &m, kPPC_And, CanCover(node, m.left().node()),
522 CanCover(node, m.right().node()), kInt16Imm_Unsigned);
523}
524
525
526#if V8_TARGET_ARCH_PPC64
527// TODO(mbrandy): Absorb rotate-right into rldic?
528void InstructionSelector::VisitWord64And(Node* node) {
529 PPCOperandGenerator g(this);
530 Int64BinopMatcher m(node);
531 int mb = 0;
532 int me = 0;
533 if (m.right().HasValue() && IsContiguousMask64(m.right().Value(), &mb, &me)) {
534 int sh = 0;
535 Node* left = m.left().node();
536 if ((m.left().IsWord64Shr() || m.left().IsWord64Shl()) &&
537 CanCover(node, left)) {
538 // Try to absorb left/right shift into rldic
539 Int64BinopMatcher mleft(m.left().node());
540 if (mleft.right().IsInRange(0, 63)) {
541 left = mleft.left().node();
542 sh = mleft.right().Value();
543 if (m.left().IsWord64Shr()) {
544 // Adjust the mask such that it doesn't include any rotated bits.
545 if (mb > 63 - sh) mb = 63 - sh;
546 sh = (64 - sh) & 0x3f;
547 } else {
548 // Adjust the mask such that it doesn't include any rotated bits.
549 if (me < sh) me = sh;
550 }
551 }
552 }
553 if (mb >= me) {
554 bool match = false;
555 ArchOpcode opcode;
556 int mask;
557 if (me == 0) {
558 match = true;
559 opcode = kPPC_RotLeftAndClearLeft64;
560 mask = mb;
561 } else if (mb == 63) {
562 match = true;
563 opcode = kPPC_RotLeftAndClearRight64;
564 mask = me;
565 } else if (sh && me <= sh && m.left().IsWord64Shl()) {
566 match = true;
567 opcode = kPPC_RotLeftAndClear64;
568 mask = mb;
569 }
570 if (match) {
571 Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
572 g.TempImmediate(sh), g.TempImmediate(mask));
573 return;
574 }
575 }
576 }
577 VisitLogical<Int64BinopMatcher>(
578 this, node, &m, kPPC_And, CanCover(node, m.left().node()),
579 CanCover(node, m.right().node()), kInt16Imm_Unsigned);
580}
581#endif
582
583
584void InstructionSelector::VisitWord32Or(Node* node) {
585 Int32BinopMatcher m(node);
586 VisitLogical<Int32BinopMatcher>(
587 this, node, &m, kPPC_Or, CanCover(node, m.left().node()),
588 CanCover(node, m.right().node()), kInt16Imm_Unsigned);
589}
590
591
592#if V8_TARGET_ARCH_PPC64
593void InstructionSelector::VisitWord64Or(Node* node) {
594 Int64BinopMatcher m(node);
595 VisitLogical<Int64BinopMatcher>(
596 this, node, &m, kPPC_Or, CanCover(node, m.left().node()),
597 CanCover(node, m.right().node()), kInt16Imm_Unsigned);
598}
599#endif
600
601
602void InstructionSelector::VisitWord32Xor(Node* node) {
603 PPCOperandGenerator g(this);
604 Int32BinopMatcher m(node);
605 if (m.right().Is(-1)) {
606 Emit(kPPC_Not, g.DefineAsRegister(node), g.UseRegister(m.left().node()));
607 } else {
608 VisitBinop<Int32BinopMatcher>(this, node, kPPC_Xor, kInt16Imm_Unsigned);
609 }
610}
611
612
613#if V8_TARGET_ARCH_PPC64
614void InstructionSelector::VisitWord64Xor(Node* node) {
615 PPCOperandGenerator g(this);
616 Int64BinopMatcher m(node);
617 if (m.right().Is(-1)) {
618 Emit(kPPC_Not, g.DefineAsRegister(node), g.UseRegister(m.left().node()));
619 } else {
620 VisitBinop<Int64BinopMatcher>(this, node, kPPC_Xor, kInt16Imm_Unsigned);
621 }
622}
623#endif
624
625
626void InstructionSelector::VisitWord32Shl(Node* node) {
627 PPCOperandGenerator g(this);
628 Int32BinopMatcher m(node);
629 if (m.left().IsWord32And() && m.right().IsInRange(0, 31)) {
630 // Try to absorb logical-and into rlwinm
631 Int32BinopMatcher mleft(m.left().node());
632 int sh = m.right().Value();
633 int mb;
634 int me;
635 if (mleft.right().HasValue() &&
636 IsContiguousMask32(mleft.right().Value() << sh, &mb, &me)) {
637 // Adjust the mask such that it doesn't include any rotated bits.
638 if (me < sh) me = sh;
639 if (mb >= me) {
640 Emit(kPPC_RotLeftAndMask32, g.DefineAsRegister(node),
641 g.UseRegister(mleft.left().node()), g.TempImmediate(sh),
642 g.TempImmediate(mb), g.TempImmediate(me));
643 return;
644 }
645 }
646 }
647 VisitRRO(this, kPPC_ShiftLeft32, node, kShift32Imm);
648}
649
650
651#if V8_TARGET_ARCH_PPC64
652void InstructionSelector::VisitWord64Shl(Node* node) {
653 PPCOperandGenerator g(this);
654 Int64BinopMatcher m(node);
655 // TODO(mbrandy): eliminate left sign extension if right >= 32
656 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) {
657 // Try to absorb logical-and into rldic
658 Int64BinopMatcher mleft(m.left().node());
659 int sh = m.right().Value();
660 int mb;
661 int me;
662 if (mleft.right().HasValue() &&
663 IsContiguousMask64(mleft.right().Value() << sh, &mb, &me)) {
664 // Adjust the mask such that it doesn't include any rotated bits.
665 if (me < sh) me = sh;
666 if (mb >= me) {
667 bool match = false;
668 ArchOpcode opcode;
669 int mask;
670 if (me == 0) {
671 match = true;
672 opcode = kPPC_RotLeftAndClearLeft64;
673 mask = mb;
674 } else if (mb == 63) {
675 match = true;
676 opcode = kPPC_RotLeftAndClearRight64;
677 mask = me;
678 } else if (sh && me <= sh) {
679 match = true;
680 opcode = kPPC_RotLeftAndClear64;
681 mask = mb;
682 }
683 if (match) {
684 Emit(opcode, g.DefineAsRegister(node),
685 g.UseRegister(mleft.left().node()), g.TempImmediate(sh),
686 g.TempImmediate(mask));
687 return;
688 }
689 }
690 }
691 }
692 VisitRRO(this, kPPC_ShiftLeft64, node, kShift64Imm);
693}
694#endif
695
696
697void InstructionSelector::VisitWord32Shr(Node* node) {
698 PPCOperandGenerator g(this);
699 Int32BinopMatcher m(node);
700 if (m.left().IsWord32And() && m.right().IsInRange(0, 31)) {
701 // Try to absorb logical-and into rlwinm
702 Int32BinopMatcher mleft(m.left().node());
703 int sh = m.right().Value();
704 int mb;
705 int me;
706 if (mleft.right().HasValue() &&
707 IsContiguousMask32((uint32_t)(mleft.right().Value()) >> sh, &mb, &me)) {
708 // Adjust the mask such that it doesn't include any rotated bits.
709 if (mb > 31 - sh) mb = 31 - sh;
710 sh = (32 - sh) & 0x1f;
711 if (mb >= me) {
712 Emit(kPPC_RotLeftAndMask32, g.DefineAsRegister(node),
713 g.UseRegister(mleft.left().node()), g.TempImmediate(sh),
714 g.TempImmediate(mb), g.TempImmediate(me));
715 return;
716 }
717 }
718 }
719 VisitRRO(this, kPPC_ShiftRight32, node, kShift32Imm);
720}
721
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722#if V8_TARGET_ARCH_PPC64
723void InstructionSelector::VisitWord64Shr(Node* node) {
724 PPCOperandGenerator g(this);
725 Int64BinopMatcher m(node);
726 if (m.left().IsWord64And() && m.right().IsInRange(0, 63)) {
727 // Try to absorb logical-and into rldic
728 Int64BinopMatcher mleft(m.left().node());
729 int sh = m.right().Value();
730 int mb;
731 int me;
732 if (mleft.right().HasValue() &&
733 IsContiguousMask64((uint64_t)(mleft.right().Value()) >> sh, &mb, &me)) {
734 // Adjust the mask such that it doesn't include any rotated bits.
735 if (mb > 63 - sh) mb = 63 - sh;
736 sh = (64 - sh) & 0x3f;
737 if (mb >= me) {
738 bool match = false;
739 ArchOpcode opcode;
740 int mask;
741 if (me == 0) {
742 match = true;
743 opcode = kPPC_RotLeftAndClearLeft64;
744 mask = mb;
745 } else if (mb == 63) {
746 match = true;
747 opcode = kPPC_RotLeftAndClearRight64;
748 mask = me;
749 }
750 if (match) {
751 Emit(opcode, g.DefineAsRegister(node),
752 g.UseRegister(mleft.left().node()), g.TempImmediate(sh),
753 g.TempImmediate(mask));
754 return;
755 }
756 }
757 }
758 }
759 VisitRRO(this, kPPC_ShiftRight64, node, kShift64Imm);
760}
761#endif
762
763
764void InstructionSelector::VisitWord32Sar(Node* node) {
765 PPCOperandGenerator g(this);
766 Int32BinopMatcher m(node);
767 // Replace with sign extension for (x << K) >> K where K is 16 or 24.
768 if (CanCover(node, m.left().node()) && m.left().IsWord32Shl()) {
769 Int32BinopMatcher mleft(m.left().node());
770 if (mleft.right().Is(16) && m.right().Is(16)) {
771 Emit(kPPC_ExtendSignWord16, g.DefineAsRegister(node),
772 g.UseRegister(mleft.left().node()));
773 return;
774 } else if (mleft.right().Is(24) && m.right().Is(24)) {
775 Emit(kPPC_ExtendSignWord8, g.DefineAsRegister(node),
776 g.UseRegister(mleft.left().node()));
777 return;
778 }
779 }
780 VisitRRO(this, kPPC_ShiftRightAlg32, node, kShift32Imm);
781}
782
Ben Murdochda12d292016-06-02 14:46:10 +0100783#if !V8_TARGET_ARCH_PPC64
784void VisitPairBinop(InstructionSelector* selector, InstructionCode opcode,
785 Node* node) {
786 PPCOperandGenerator g(selector);
787
788 // We use UseUniqueRegister here to avoid register sharing with the output
789 // registers.
790 InstructionOperand inputs[] = {
791 g.UseRegister(node->InputAt(0)), g.UseUniqueRegister(node->InputAt(1)),
792 g.UseRegister(node->InputAt(2)), g.UseUniqueRegister(node->InputAt(3))};
793
794 InstructionOperand outputs[] = {
795 g.DefineAsRegister(node),
796 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
797
798 selector->Emit(opcode, 2, outputs, 4, inputs);
799}
800
801void InstructionSelector::VisitInt32PairAdd(Node* node) {
802 VisitPairBinop(this, kPPC_AddPair, node);
803}
804
805void InstructionSelector::VisitInt32PairSub(Node* node) {
806 VisitPairBinop(this, kPPC_SubPair, node);
807}
808
809void InstructionSelector::VisitInt32PairMul(Node* node) {
810 PPCOperandGenerator g(this);
811 InstructionOperand inputs[] = {g.UseUniqueRegister(node->InputAt(0)),
812 g.UseUniqueRegister(node->InputAt(1)),
813 g.UseUniqueRegister(node->InputAt(2)),
814 g.UseRegister(node->InputAt(3))};
815
816 InstructionOperand outputs[] = {
817 g.DefineAsRegister(node),
818 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
819
820 InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
821
822 Emit(kPPC_MulPair, 2, outputs, 4, inputs, 2, temps);
823}
824
825void VisitPairShift(InstructionSelector* selector, InstructionCode opcode,
826 Node* node) {
827 PPCOperandGenerator g(selector);
828 Int32Matcher m(node->InputAt(2));
829 InstructionOperand shift_operand;
830 if (m.HasValue()) {
831 shift_operand = g.UseImmediate(m.node());
832 } else {
833 shift_operand = g.UseUniqueRegister(m.node());
834 }
835
836 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0)),
837 g.UseRegister(node->InputAt(1)),
838 shift_operand};
839
840 InstructionOperand outputs[] = {
841 g.DefineSameAsFirst(node),
842 g.DefineAsRegister(NodeProperties::FindProjection(node, 1))};
843
844 selector->Emit(opcode, 2, outputs, 3, inputs);
845}
846
847void InstructionSelector::VisitWord32PairShl(Node* node) {
848 VisitPairShift(this, kPPC_ShiftLeftPair, node);
849}
850
851void InstructionSelector::VisitWord32PairShr(Node* node) {
852 VisitPairShift(this, kPPC_ShiftRightPair, node);
853}
854
855void InstructionSelector::VisitWord32PairSar(Node* node) {
856 VisitPairShift(this, kPPC_ShiftRightAlgPair, node);
857}
858#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859
860#if V8_TARGET_ARCH_PPC64
861void InstructionSelector::VisitWord64Sar(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +0100862 PPCOperandGenerator g(this);
863 Int64BinopMatcher m(node);
864 if (CanCover(m.node(), m.left().node()) && m.left().IsLoad() &&
865 m.right().Is(32)) {
866 // Just load and sign-extend the interesting 4 bytes instead. This happens,
867 // for example, when we're loading and untagging SMIs.
868 BaseWithIndexAndDisplacement64Matcher mleft(m.left().node(), true);
869 if (mleft.matches() && mleft.index() == nullptr) {
870 int64_t offset = 0;
871 Node* displacement = mleft.displacement();
872 if (displacement != nullptr) {
873 Int64Matcher mdisplacement(displacement);
874 DCHECK(mdisplacement.HasValue());
875 offset = mdisplacement.Value();
876 }
877 offset = SmiWordOffset(offset);
878 if (g.CanBeImmediate(offset, kInt16Imm_4ByteAligned)) {
879 Emit(kPPC_LoadWordS32 | AddressingModeField::encode(kMode_MRI),
880 g.DefineAsRegister(node), g.UseRegister(mleft.base()),
881 g.TempImmediate(offset));
882 return;
883 }
884 }
885 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000886 VisitRRO(this, kPPC_ShiftRightAlg64, node, kShift64Imm);
887}
888#endif
889
890
891// TODO(mbrandy): Absorb logical-and into rlwinm?
892void InstructionSelector::VisitWord32Ror(Node* node) {
893 VisitRRO(this, kPPC_RotRight32, node, kShift32Imm);
894}
895
896
897#if V8_TARGET_ARCH_PPC64
898// TODO(mbrandy): Absorb logical-and into rldic?
899void InstructionSelector::VisitWord64Ror(Node* node) {
900 VisitRRO(this, kPPC_RotRight64, node, kShift64Imm);
901}
902#endif
903
904
905void InstructionSelector::VisitWord32Clz(Node* node) {
906 PPCOperandGenerator g(this);
907 Emit(kPPC_Cntlz32, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
908}
909
910
911#if V8_TARGET_ARCH_PPC64
912void InstructionSelector::VisitWord64Clz(Node* node) {
913 PPCOperandGenerator g(this);
914 Emit(kPPC_Cntlz64, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)));
915}
916#endif
917
918
919void InstructionSelector::VisitWord32Popcnt(Node* node) {
920 PPCOperandGenerator g(this);
921 Emit(kPPC_Popcnt32, g.DefineAsRegister(node),
922 g.UseRegister(node->InputAt(0)));
923}
924
925
926#if V8_TARGET_ARCH_PPC64
927void InstructionSelector::VisitWord64Popcnt(Node* node) {
928 PPCOperandGenerator g(this);
929 Emit(kPPC_Popcnt64, g.DefineAsRegister(node),
930 g.UseRegister(node->InputAt(0)));
931}
932#endif
933
934
935void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
936
937
938#if V8_TARGET_ARCH_PPC64
939void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); }
940#endif
941
942
Ben Murdoch097c5b22016-05-18 11:27:45 +0100943void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); }
944
945
946#if V8_TARGET_ARCH_PPC64
947void InstructionSelector::VisitWord64ReverseBits(Node* node) { UNREACHABLE(); }
948#endif
949
950
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000951void InstructionSelector::VisitInt32Add(Node* node) {
952 VisitBinop<Int32BinopMatcher>(this, node, kPPC_Add, kInt16Imm);
953}
954
955
956#if V8_TARGET_ARCH_PPC64
957void InstructionSelector::VisitInt64Add(Node* node) {
958 VisitBinop<Int64BinopMatcher>(this, node, kPPC_Add, kInt16Imm);
959}
960#endif
961
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000962void InstructionSelector::VisitInt32Sub(Node* node) {
963 PPCOperandGenerator g(this);
964 Int32BinopMatcher m(node);
965 if (m.left().Is(0)) {
966 Emit(kPPC_Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node()));
967 } else {
968 VisitBinop<Int32BinopMatcher>(this, node, kPPC_Sub, kInt16Imm_Negate);
969 }
970}
971
972
973#if V8_TARGET_ARCH_PPC64
974void InstructionSelector::VisitInt64Sub(Node* node) {
975 PPCOperandGenerator g(this);
976 Int64BinopMatcher m(node);
977 if (m.left().Is(0)) {
978 Emit(kPPC_Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node()));
979 } else {
980 VisitBinop<Int64BinopMatcher>(this, node, kPPC_Sub, kInt16Imm_Negate);
981 }
982}
983#endif
984
985
986void InstructionSelector::VisitInt32Mul(Node* node) {
987 VisitRRR(this, kPPC_Mul32, node);
988}
989
990
991#if V8_TARGET_ARCH_PPC64
992void InstructionSelector::VisitInt64Mul(Node* node) {
993 VisitRRR(this, kPPC_Mul64, node);
994}
995#endif
996
997
998void InstructionSelector::VisitInt32MulHigh(Node* node) {
999 PPCOperandGenerator g(this);
1000 Emit(kPPC_MulHigh32, g.DefineAsRegister(node),
1001 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
1002}
1003
1004
1005void InstructionSelector::VisitUint32MulHigh(Node* node) {
1006 PPCOperandGenerator g(this);
1007 Emit(kPPC_MulHighU32, g.DefineAsRegister(node),
1008 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)));
1009}
1010
1011
1012void InstructionSelector::VisitInt32Div(Node* node) {
1013 VisitRRR(this, kPPC_Div32, node);
1014}
1015
1016
1017#if V8_TARGET_ARCH_PPC64
1018void InstructionSelector::VisitInt64Div(Node* node) {
1019 VisitRRR(this, kPPC_Div64, node);
1020}
1021#endif
1022
1023
1024void InstructionSelector::VisitUint32Div(Node* node) {
1025 VisitRRR(this, kPPC_DivU32, node);
1026}
1027
1028
1029#if V8_TARGET_ARCH_PPC64
1030void InstructionSelector::VisitUint64Div(Node* node) {
1031 VisitRRR(this, kPPC_DivU64, node);
1032}
1033#endif
1034
1035
1036void InstructionSelector::VisitInt32Mod(Node* node) {
1037 VisitRRR(this, kPPC_Mod32, node);
1038}
1039
1040
1041#if V8_TARGET_ARCH_PPC64
1042void InstructionSelector::VisitInt64Mod(Node* node) {
1043 VisitRRR(this, kPPC_Mod64, node);
1044}
1045#endif
1046
1047
1048void InstructionSelector::VisitUint32Mod(Node* node) {
1049 VisitRRR(this, kPPC_ModU32, node);
1050}
1051
1052
1053#if V8_TARGET_ARCH_PPC64
1054void InstructionSelector::VisitUint64Mod(Node* node) {
1055 VisitRRR(this, kPPC_ModU64, node);
1056}
1057#endif
1058
1059
1060void InstructionSelector::VisitChangeFloat32ToFloat64(Node* node) {
1061 VisitRR(this, kPPC_Float32ToDouble, node);
1062}
1063
1064
Ben Murdoch097c5b22016-05-18 11:27:45 +01001065void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
1066 VisitRR(this, kPPC_Int32ToFloat32, node);
1067}
1068
1069
1070void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
1071 VisitRR(this, kPPC_Uint32ToFloat32, node);
1072}
1073
1074
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001075void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
1076 VisitRR(this, kPPC_Int32ToDouble, node);
1077}
1078
1079
1080void InstructionSelector::VisitChangeUint32ToFloat64(Node* node) {
1081 VisitRR(this, kPPC_Uint32ToDouble, node);
1082}
1083
1084
1085void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
1086 VisitRR(this, kPPC_DoubleToInt32, node);
1087}
1088
1089
1090void InstructionSelector::VisitChangeFloat64ToUint32(Node* node) {
1091 VisitRR(this, kPPC_DoubleToUint32, node);
1092}
1093
Ben Murdochda12d292016-06-02 14:46:10 +01001094void InstructionSelector::VisitTruncateFloat64ToUint32(Node* node) {
1095 VisitRR(this, kPPC_DoubleToUint32, node);
1096}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001097
1098#if V8_TARGET_ARCH_PPC64
1099void InstructionSelector::VisitTryTruncateFloat32ToInt64(Node* node) {
1100 VisitTryTruncateDouble(this, kPPC_DoubleToInt64, node);
1101}
1102
1103
1104void InstructionSelector::VisitTryTruncateFloat64ToInt64(Node* node) {
1105 VisitTryTruncateDouble(this, kPPC_DoubleToInt64, node);
1106}
1107
1108
1109void InstructionSelector::VisitTryTruncateFloat32ToUint64(Node* node) {
1110 VisitTryTruncateDouble(this, kPPC_DoubleToUint64, node);
1111}
1112
1113
1114void InstructionSelector::VisitTryTruncateFloat64ToUint64(Node* node) {
1115 VisitTryTruncateDouble(this, kPPC_DoubleToUint64, node);
1116}
1117
1118
1119void InstructionSelector::VisitChangeInt32ToInt64(Node* node) {
1120 // TODO(mbrandy): inspect input to see if nop is appropriate.
1121 VisitRR(this, kPPC_ExtendSignWord32, node);
1122}
1123
1124
1125void InstructionSelector::VisitChangeUint32ToUint64(Node* node) {
1126 // TODO(mbrandy): inspect input to see if nop is appropriate.
1127 VisitRR(this, kPPC_Uint32ToUint64, node);
1128}
1129#endif
1130
1131
1132void InstructionSelector::VisitTruncateFloat64ToFloat32(Node* node) {
1133 VisitRR(this, kPPC_DoubleToFloat32, node);
1134}
1135
Ben Murdochc5610432016-08-08 18:44:38 +01001136void InstructionSelector::VisitTruncateFloat64ToWord32(Node* node) {
1137 VisitRR(this, kArchTruncateDoubleToI, node);
1138}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001139
Ben Murdochc5610432016-08-08 18:44:38 +01001140void InstructionSelector::VisitRoundFloat64ToInt32(Node* node) {
1141 VisitRR(this, kPPC_DoubleToInt32, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001142}
1143
1144
Ben Murdoch097c5b22016-05-18 11:27:45 +01001145void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
1146 VisitRR(this, kPPC_DoubleToInt32, node);
1147}
1148
1149
1150void InstructionSelector::VisitTruncateFloat32ToUint32(Node* node) {
1151 VisitRR(this, kPPC_DoubleToUint32, node);
1152}
1153
1154
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001155#if V8_TARGET_ARCH_PPC64
1156void InstructionSelector::VisitTruncateInt64ToInt32(Node* node) {
1157 // TODO(mbrandy): inspect input to see if nop is appropriate.
1158 VisitRR(this, kPPC_Int64ToInt32, node);
1159}
1160
1161
1162void InstructionSelector::VisitRoundInt64ToFloat32(Node* node) {
1163 VisitRR(this, kPPC_Int64ToFloat32, node);
1164}
1165
1166
1167void InstructionSelector::VisitRoundInt64ToFloat64(Node* node) {
1168 VisitRR(this, kPPC_Int64ToDouble, node);
1169}
1170
1171
1172void InstructionSelector::VisitRoundUint64ToFloat32(Node* node) {
1173 VisitRR(this, kPPC_Uint64ToFloat32, node);
1174}
1175
1176
1177void InstructionSelector::VisitRoundUint64ToFloat64(Node* node) {
1178 VisitRR(this, kPPC_Uint64ToDouble, node);
1179}
1180#endif
1181
1182
1183void InstructionSelector::VisitBitcastFloat32ToInt32(Node* node) {
1184 VisitRR(this, kPPC_BitcastFloat32ToInt32, node);
1185}
1186
1187
1188#if V8_TARGET_ARCH_PPC64
1189void InstructionSelector::VisitBitcastFloat64ToInt64(Node* node) {
1190 VisitRR(this, kPPC_BitcastDoubleToInt64, node);
1191}
1192#endif
1193
1194
1195void InstructionSelector::VisitBitcastInt32ToFloat32(Node* node) {
1196 VisitRR(this, kPPC_BitcastInt32ToFloat32, node);
1197}
1198
1199
1200#if V8_TARGET_ARCH_PPC64
1201void InstructionSelector::VisitBitcastInt64ToFloat64(Node* node) {
1202 VisitRR(this, kPPC_BitcastInt64ToDouble, node);
1203}
1204#endif
1205
1206
1207void InstructionSelector::VisitFloat32Add(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001208 VisitRRR(this, kPPC_AddDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001209}
1210
1211
1212void InstructionSelector::VisitFloat64Add(Node* node) {
1213 // TODO(mbrandy): detect multiply-add
1214 VisitRRR(this, kPPC_AddDouble, node);
1215}
1216
1217
1218void InstructionSelector::VisitFloat32Sub(Node* node) {
1219 PPCOperandGenerator g(this);
1220 Float32BinopMatcher m(node);
1221 if (m.left().IsMinusZero()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001222 Emit(kPPC_NegDouble | MiscField::encode(1), g.DefineAsRegister(node),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001223 g.UseRegister(m.right().node()));
1224 return;
1225 }
Ben Murdochda12d292016-06-02 14:46:10 +01001226 VisitRRR(this, kPPC_SubDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001227}
1228
Ben Murdochc5610432016-08-08 18:44:38 +01001229void InstructionSelector::VisitFloat32SubPreserveNan(Node* node) {
1230 PPCOperandGenerator g(this);
1231 VisitRRR(this, kPPC_SubDouble | MiscField::encode(1), node);
1232}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001233
1234void InstructionSelector::VisitFloat64Sub(Node* node) {
1235 // TODO(mbrandy): detect multiply-subtract
1236 PPCOperandGenerator g(this);
1237 Float64BinopMatcher m(node);
1238 if (m.left().IsMinusZero()) {
1239 if (m.right().IsFloat64RoundDown() &&
1240 CanCover(m.node(), m.right().node())) {
1241 if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub &&
1242 CanCover(m.right().node(), m.right().InputAt(0))) {
1243 Float64BinopMatcher mright0(m.right().InputAt(0));
1244 if (mright0.left().IsMinusZero()) {
1245 // -floor(-x) = ceil(x)
1246 Emit(kPPC_CeilDouble, g.DefineAsRegister(node),
1247 g.UseRegister(mright0.right().node()));
1248 return;
1249 }
1250 }
1251 }
1252 Emit(kPPC_NegDouble, g.DefineAsRegister(node),
1253 g.UseRegister(m.right().node()));
1254 return;
1255 }
1256 VisitRRR(this, kPPC_SubDouble, node);
1257}
1258
Ben Murdochc5610432016-08-08 18:44:38 +01001259void InstructionSelector::VisitFloat64SubPreserveNan(Node* node) {
1260 VisitRRR(this, kPPC_SubDouble, node);
1261}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001262
1263void InstructionSelector::VisitFloat32Mul(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001264 VisitRRR(this, kPPC_MulDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001265}
1266
1267
1268void InstructionSelector::VisitFloat64Mul(Node* node) {
1269 // TODO(mbrandy): detect negate
1270 VisitRRR(this, kPPC_MulDouble, node);
1271}
1272
1273
1274void InstructionSelector::VisitFloat32Div(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001275 VisitRRR(this, kPPC_DivDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001276}
1277
1278
1279void InstructionSelector::VisitFloat64Div(Node* node) {
1280 VisitRRR(this, kPPC_DivDouble, node);
1281}
1282
1283
1284void InstructionSelector::VisitFloat64Mod(Node* node) {
1285 PPCOperandGenerator g(this);
1286 Emit(kPPC_ModDouble, g.DefineAsFixed(node, d1),
1287 g.UseFixed(node->InputAt(0), d1),
1288 g.UseFixed(node->InputAt(1), d2))->MarkAsCall();
1289}
1290
1291
1292void InstructionSelector::VisitFloat32Max(Node* node) { UNREACHABLE(); }
1293
1294
1295void InstructionSelector::VisitFloat64Max(Node* node) { UNREACHABLE(); }
1296
1297
1298void InstructionSelector::VisitFloat32Min(Node* node) { UNREACHABLE(); }
1299
1300
1301void InstructionSelector::VisitFloat64Min(Node* node) { UNREACHABLE(); }
1302
1303
1304void InstructionSelector::VisitFloat32Abs(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001305 VisitRR(this, kPPC_AbsDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001306}
1307
1308
1309void InstructionSelector::VisitFloat64Abs(Node* node) {
1310 VisitRR(this, kPPC_AbsDouble, node);
1311}
1312
1313
1314void InstructionSelector::VisitFloat32Sqrt(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001315 VisitRR(this, kPPC_SqrtDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316}
1317
1318
1319void InstructionSelector::VisitFloat64Sqrt(Node* node) {
1320 VisitRR(this, kPPC_SqrtDouble, node);
1321}
1322
1323
1324void InstructionSelector::VisitFloat32RoundDown(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001325 VisitRR(this, kPPC_FloorDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001326}
1327
1328
1329void InstructionSelector::VisitFloat64RoundDown(Node* node) {
1330 VisitRR(this, kPPC_FloorDouble, node);
1331}
1332
1333
1334void InstructionSelector::VisitFloat32RoundUp(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001335 VisitRR(this, kPPC_CeilDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336}
1337
1338
1339void InstructionSelector::VisitFloat64RoundUp(Node* node) {
1340 VisitRR(this, kPPC_CeilDouble, node);
1341}
1342
1343
1344void InstructionSelector::VisitFloat32RoundTruncate(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001345 VisitRR(this, kPPC_TruncateDouble | MiscField::encode(1), node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001346}
1347
1348
1349void InstructionSelector::VisitFloat64RoundTruncate(Node* node) {
1350 VisitRR(this, kPPC_TruncateDouble, node);
1351}
1352
1353
1354void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) {
1355 VisitRR(this, kPPC_RoundDouble, node);
1356}
1357
1358
1359void InstructionSelector::VisitFloat32RoundTiesEven(Node* node) {
1360 UNREACHABLE();
1361}
1362
1363
1364void InstructionSelector::VisitFloat64RoundTiesEven(Node* node) {
1365 UNREACHABLE();
1366}
1367
1368
1369void InstructionSelector::VisitInt32AddWithOverflow(Node* node) {
1370 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001371 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001372 return VisitBinop<Int32BinopMatcher>(this, node, kPPC_AddWithOverflow32,
1373 kInt16Imm, &cont);
1374 }
1375 FlagsContinuation cont;
1376 VisitBinop<Int32BinopMatcher>(this, node, kPPC_AddWithOverflow32, kInt16Imm,
1377 &cont);
1378}
1379
1380
1381void InstructionSelector::VisitInt32SubWithOverflow(Node* node) {
1382 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001383 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001384 return VisitBinop<Int32BinopMatcher>(this, node, kPPC_SubWithOverflow32,
1385 kInt16Imm_Negate, &cont);
1386 }
1387 FlagsContinuation cont;
1388 VisitBinop<Int32BinopMatcher>(this, node, kPPC_SubWithOverflow32,
1389 kInt16Imm_Negate, &cont);
1390}
1391
1392
1393#if V8_TARGET_ARCH_PPC64
1394void InstructionSelector::VisitInt64AddWithOverflow(Node* node) {
1395 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001396 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001397 return VisitBinop<Int64BinopMatcher>(this, node, kPPC_Add, kInt16Imm,
1398 &cont);
1399 }
1400 FlagsContinuation cont;
1401 VisitBinop<Int64BinopMatcher>(this, node, kPPC_Add, kInt16Imm, &cont);
1402}
1403
1404
1405void InstructionSelector::VisitInt64SubWithOverflow(Node* node) {
1406 if (Node* ovf = NodeProperties::FindProjection(node, 1)) {
Ben Murdochda12d292016-06-02 14:46:10 +01001407 FlagsContinuation cont = FlagsContinuation::ForSet(kOverflow, ovf);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001408 return VisitBinop<Int64BinopMatcher>(this, node, kPPC_Sub, kInt16Imm_Negate,
1409 &cont);
1410 }
1411 FlagsContinuation cont;
1412 VisitBinop<Int64BinopMatcher>(this, node, kPPC_Sub, kInt16Imm_Negate, &cont);
1413}
1414#endif
1415
1416
1417static bool CompareLogical(FlagsContinuation* cont) {
1418 switch (cont->condition()) {
1419 case kUnsignedLessThan:
1420 case kUnsignedGreaterThanOrEqual:
1421 case kUnsignedLessThanOrEqual:
1422 case kUnsignedGreaterThan:
1423 return true;
1424 default:
1425 return false;
1426 }
1427 UNREACHABLE();
1428 return false;
1429}
1430
1431
1432namespace {
1433
1434// Shared routine for multiple compare operations.
1435void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
1436 InstructionOperand left, InstructionOperand right,
1437 FlagsContinuation* cont) {
1438 PPCOperandGenerator g(selector);
1439 opcode = cont->Encode(opcode);
1440 if (cont->IsBranch()) {
1441 selector->Emit(opcode, g.NoOutput(), left, right,
1442 g.Label(cont->true_block()), g.Label(cont->false_block()));
Ben Murdochda12d292016-06-02 14:46:10 +01001443 } else if (cont->IsDeoptimize()) {
1444 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right,
1445 cont->frame_state());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001446 } else {
1447 DCHECK(cont->IsSet());
1448 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right);
1449 }
1450}
1451
1452
1453// Shared routine for multiple word compare operations.
1454void VisitWordCompare(InstructionSelector* selector, Node* node,
1455 InstructionCode opcode, FlagsContinuation* cont,
1456 bool commutative, ImmediateMode immediate_mode) {
1457 PPCOperandGenerator g(selector);
1458 Node* left = node->InputAt(0);
1459 Node* right = node->InputAt(1);
1460
1461 // Match immediates on left or right side of comparison.
1462 if (g.CanBeImmediate(right, immediate_mode)) {
1463 VisitCompare(selector, opcode, g.UseRegister(left), g.UseImmediate(right),
1464 cont);
1465 } else if (g.CanBeImmediate(left, immediate_mode)) {
1466 if (!commutative) cont->Commute();
1467 VisitCompare(selector, opcode, g.UseRegister(right), g.UseImmediate(left),
1468 cont);
1469 } else {
1470 VisitCompare(selector, opcode, g.UseRegister(left), g.UseRegister(right),
1471 cont);
1472 }
1473}
1474
1475
1476void VisitWord32Compare(InstructionSelector* selector, Node* node,
1477 FlagsContinuation* cont) {
1478 ImmediateMode mode = (CompareLogical(cont) ? kInt16Imm_Unsigned : kInt16Imm);
1479 VisitWordCompare(selector, node, kPPC_Cmp32, cont, false, mode);
1480}
1481
1482
1483#if V8_TARGET_ARCH_PPC64
1484void VisitWord64Compare(InstructionSelector* selector, Node* node,
1485 FlagsContinuation* cont) {
1486 ImmediateMode mode = (CompareLogical(cont) ? kInt16Imm_Unsigned : kInt16Imm);
1487 VisitWordCompare(selector, node, kPPC_Cmp64, cont, false, mode);
1488}
1489#endif
1490
1491
1492// Shared routine for multiple float32 compare operations.
1493void VisitFloat32Compare(InstructionSelector* selector, Node* node,
1494 FlagsContinuation* cont) {
1495 PPCOperandGenerator g(selector);
1496 Node* left = node->InputAt(0);
1497 Node* right = node->InputAt(1);
1498 VisitCompare(selector, kPPC_CmpDouble, g.UseRegister(left),
1499 g.UseRegister(right), cont);
1500}
1501
1502
1503// Shared routine for multiple float64 compare operations.
1504void VisitFloat64Compare(InstructionSelector* selector, Node* node,
1505 FlagsContinuation* cont) {
1506 PPCOperandGenerator g(selector);
1507 Node* left = node->InputAt(0);
1508 Node* right = node->InputAt(1);
1509 VisitCompare(selector, kPPC_CmpDouble, g.UseRegister(left),
1510 g.UseRegister(right), cont);
1511}
1512
1513
1514// Shared routine for word comparisons against zero.
1515void VisitWordCompareZero(InstructionSelector* selector, Node* user,
1516 Node* value, InstructionCode opcode,
1517 FlagsContinuation* cont) {
1518 while (selector->CanCover(user, value)) {
1519 switch (value->opcode()) {
1520 case IrOpcode::kWord32Equal: {
1521 // Combine with comparisons against 0 by simply inverting the
1522 // continuation.
1523 Int32BinopMatcher m(value);
1524 if (m.right().Is(0)) {
1525 user = value;
1526 value = m.left().node();
1527 cont->Negate();
1528 continue;
1529 }
1530 cont->OverwriteAndNegateIfEqual(kEqual);
1531 return VisitWord32Compare(selector, value, cont);
1532 }
1533 case IrOpcode::kInt32LessThan:
1534 cont->OverwriteAndNegateIfEqual(kSignedLessThan);
1535 return VisitWord32Compare(selector, value, cont);
1536 case IrOpcode::kInt32LessThanOrEqual:
1537 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1538 return VisitWord32Compare(selector, value, cont);
1539 case IrOpcode::kUint32LessThan:
1540 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
1541 return VisitWord32Compare(selector, value, cont);
1542 case IrOpcode::kUint32LessThanOrEqual:
1543 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1544 return VisitWord32Compare(selector, value, cont);
1545#if V8_TARGET_ARCH_PPC64
1546 case IrOpcode::kWord64Equal:
1547 cont->OverwriteAndNegateIfEqual(kEqual);
1548 return VisitWord64Compare(selector, value, cont);
1549 case IrOpcode::kInt64LessThan:
1550 cont->OverwriteAndNegateIfEqual(kSignedLessThan);
1551 return VisitWord64Compare(selector, value, cont);
1552 case IrOpcode::kInt64LessThanOrEqual:
1553 cont->OverwriteAndNegateIfEqual(kSignedLessThanOrEqual);
1554 return VisitWord64Compare(selector, value, cont);
1555 case IrOpcode::kUint64LessThan:
1556 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
1557 return VisitWord64Compare(selector, value, cont);
1558 case IrOpcode::kUint64LessThanOrEqual:
1559 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1560 return VisitWord64Compare(selector, value, cont);
1561#endif
1562 case IrOpcode::kFloat32Equal:
1563 cont->OverwriteAndNegateIfEqual(kEqual);
1564 return VisitFloat32Compare(selector, value, cont);
1565 case IrOpcode::kFloat32LessThan:
1566 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
1567 return VisitFloat32Compare(selector, value, cont);
1568 case IrOpcode::kFloat32LessThanOrEqual:
1569 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1570 return VisitFloat32Compare(selector, value, cont);
1571 case IrOpcode::kFloat64Equal:
1572 cont->OverwriteAndNegateIfEqual(kEqual);
1573 return VisitFloat64Compare(selector, value, cont);
1574 case IrOpcode::kFloat64LessThan:
1575 cont->OverwriteAndNegateIfEqual(kUnsignedLessThan);
1576 return VisitFloat64Compare(selector, value, cont);
1577 case IrOpcode::kFloat64LessThanOrEqual:
1578 cont->OverwriteAndNegateIfEqual(kUnsignedLessThanOrEqual);
1579 return VisitFloat64Compare(selector, value, cont);
1580 case IrOpcode::kProjection:
1581 // Check if this is the overflow output projection of an
1582 // <Operation>WithOverflow node.
1583 if (ProjectionIndexOf(value->op()) == 1u) {
1584 // We cannot combine the <Operation>WithOverflow with this branch
1585 // unless the 0th projection (the use of the actual value of the
1586 // <Operation> is either nullptr, which means there's no use of the
1587 // actual value, or was already defined, which means it is scheduled
1588 // *AFTER* this branch).
1589 Node* const node = value->InputAt(0);
1590 Node* const result = NodeProperties::FindProjection(node, 0);
1591 if (result == nullptr || selector->IsDefined(result)) {
1592 switch (node->opcode()) {
1593 case IrOpcode::kInt32AddWithOverflow:
1594 cont->OverwriteAndNegateIfEqual(kOverflow);
1595 return VisitBinop<Int32BinopMatcher>(
1596 selector, node, kPPC_AddWithOverflow32, kInt16Imm, cont);
1597 case IrOpcode::kInt32SubWithOverflow:
1598 cont->OverwriteAndNegateIfEqual(kOverflow);
1599 return VisitBinop<Int32BinopMatcher>(selector, node,
1600 kPPC_SubWithOverflow32,
1601 kInt16Imm_Negate, cont);
1602#if V8_TARGET_ARCH_PPC64
1603 case IrOpcode::kInt64AddWithOverflow:
1604 cont->OverwriteAndNegateIfEqual(kOverflow);
1605 return VisitBinop<Int64BinopMatcher>(selector, node, kPPC_Add,
1606 kInt16Imm, cont);
1607 case IrOpcode::kInt64SubWithOverflow:
1608 cont->OverwriteAndNegateIfEqual(kOverflow);
1609 return VisitBinop<Int64BinopMatcher>(selector, node, kPPC_Sub,
1610 kInt16Imm_Negate, cont);
1611#endif
1612 default:
1613 break;
1614 }
1615 }
1616 }
1617 break;
1618 case IrOpcode::kInt32Sub:
1619 return VisitWord32Compare(selector, value, cont);
1620 case IrOpcode::kWord32And:
1621 // TODO(mbandy): opportunity for rlwinm?
1622 return VisitWordCompare(selector, value, kPPC_Tst32, cont, true,
1623 kInt16Imm_Unsigned);
1624// TODO(mbrandy): Handle?
1625// case IrOpcode::kInt32Add:
1626// case IrOpcode::kWord32Or:
1627// case IrOpcode::kWord32Xor:
1628// case IrOpcode::kWord32Sar:
1629// case IrOpcode::kWord32Shl:
1630// case IrOpcode::kWord32Shr:
1631// case IrOpcode::kWord32Ror:
1632#if V8_TARGET_ARCH_PPC64
1633 case IrOpcode::kInt64Sub:
1634 return VisitWord64Compare(selector, value, cont);
1635 case IrOpcode::kWord64And:
1636 // TODO(mbandy): opportunity for rldic?
1637 return VisitWordCompare(selector, value, kPPC_Tst64, cont, true,
1638 kInt16Imm_Unsigned);
1639// TODO(mbrandy): Handle?
1640// case IrOpcode::kInt64Add:
1641// case IrOpcode::kWord64Or:
1642// case IrOpcode::kWord64Xor:
1643// case IrOpcode::kWord64Sar:
1644// case IrOpcode::kWord64Shl:
1645// case IrOpcode::kWord64Shr:
1646// case IrOpcode::kWord64Ror:
1647#endif
1648 default:
1649 break;
1650 }
1651 break;
1652 }
1653
1654 // Branch could not be combined with a compare, emit compare against 0.
1655 PPCOperandGenerator g(selector);
1656 VisitCompare(selector, opcode, g.UseRegister(value), g.TempImmediate(0),
1657 cont);
1658}
1659
1660
1661void VisitWord32CompareZero(InstructionSelector* selector, Node* user,
1662 Node* value, FlagsContinuation* cont) {
1663 VisitWordCompareZero(selector, user, value, kPPC_Cmp32, cont);
1664}
1665
1666
1667#if V8_TARGET_ARCH_PPC64
1668void VisitWord64CompareZero(InstructionSelector* selector, Node* user,
1669 Node* value, FlagsContinuation* cont) {
1670 VisitWordCompareZero(selector, user, value, kPPC_Cmp64, cont);
1671}
1672#endif
1673
1674} // namespace
1675
1676
1677void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch,
1678 BasicBlock* fbranch) {
1679 FlagsContinuation cont(kNotEqual, tbranch, fbranch);
1680 VisitWord32CompareZero(this, branch, branch->InputAt(0), &cont);
1681}
1682
Ben Murdochda12d292016-06-02 14:46:10 +01001683void InstructionSelector::VisitDeoptimizeIf(Node* node) {
1684 FlagsContinuation cont =
1685 FlagsContinuation::ForDeoptimize(kNotEqual, node->InputAt(1));
1686 VisitWord32CompareZero(this, node, node->InputAt(0), &cont);
1687}
1688
1689void InstructionSelector::VisitDeoptimizeUnless(Node* node) {
1690 FlagsContinuation cont =
1691 FlagsContinuation::ForDeoptimize(kEqual, node->InputAt(1));
1692 VisitWord32CompareZero(this, node, node->InputAt(0), &cont);
1693}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001694
1695void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) {
1696 PPCOperandGenerator g(this);
1697 InstructionOperand value_operand = g.UseRegister(node->InputAt(0));
1698
1699 // Emit either ArchTableSwitch or ArchLookupSwitch.
1700 size_t table_space_cost = 4 + sw.value_range;
1701 size_t table_time_cost = 3;
1702 size_t lookup_space_cost = 3 + 2 * sw.case_count;
1703 size_t lookup_time_cost = sw.case_count;
1704 if (sw.case_count > 0 &&
1705 table_space_cost + 3 * table_time_cost <=
1706 lookup_space_cost + 3 * lookup_time_cost &&
1707 sw.min_value > std::numeric_limits<int32_t>::min()) {
1708 InstructionOperand index_operand = value_operand;
1709 if (sw.min_value) {
1710 index_operand = g.TempRegister();
1711 Emit(kPPC_Sub, index_operand, value_operand,
1712 g.TempImmediate(sw.min_value));
1713 }
1714 // Generate a table lookup.
1715 return EmitTableSwitch(sw, index_operand);
1716 }
1717
1718 // Generate a sequence of conditional jumps.
1719 return EmitLookupSwitch(sw, value_operand);
1720}
1721
1722
1723void InstructionSelector::VisitWord32Equal(Node* const node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001724 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001725 Int32BinopMatcher m(node);
1726 if (m.right().Is(0)) {
1727 return VisitWord32CompareZero(this, m.node(), m.left().node(), &cont);
1728 }
1729 VisitWord32Compare(this, node, &cont);
1730}
1731
1732
1733void InstructionSelector::VisitInt32LessThan(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001734 FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001735 VisitWord32Compare(this, node, &cont);
1736}
1737
1738
1739void InstructionSelector::VisitInt32LessThanOrEqual(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001740 FlagsContinuation cont =
1741 FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001742 VisitWord32Compare(this, node, &cont);
1743}
1744
1745
1746void InstructionSelector::VisitUint32LessThan(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001747 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001748 VisitWord32Compare(this, node, &cont);
1749}
1750
1751
1752void InstructionSelector::VisitUint32LessThanOrEqual(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001753 FlagsContinuation cont =
1754 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001755 VisitWord32Compare(this, node, &cont);
1756}
1757
1758
1759#if V8_TARGET_ARCH_PPC64
1760void InstructionSelector::VisitWord64Equal(Node* const node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001761 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001762 Int64BinopMatcher m(node);
1763 if (m.right().Is(0)) {
1764 return VisitWord64CompareZero(this, m.node(), m.left().node(), &cont);
1765 }
1766 VisitWord64Compare(this, node, &cont);
1767}
1768
1769
1770void InstructionSelector::VisitInt64LessThan(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001771 FlagsContinuation cont = FlagsContinuation::ForSet(kSignedLessThan, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001772 VisitWord64Compare(this, node, &cont);
1773}
1774
1775
1776void InstructionSelector::VisitInt64LessThanOrEqual(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001777 FlagsContinuation cont =
1778 FlagsContinuation::ForSet(kSignedLessThanOrEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001779 VisitWord64Compare(this, node, &cont);
1780}
1781
1782
1783void InstructionSelector::VisitUint64LessThan(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001784 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001785 VisitWord64Compare(this, node, &cont);
1786}
1787
1788
1789void InstructionSelector::VisitUint64LessThanOrEqual(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001790 FlagsContinuation cont =
1791 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001792 VisitWord64Compare(this, node, &cont);
1793}
1794#endif
1795
1796
1797void InstructionSelector::VisitFloat32Equal(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001798 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001799 VisitFloat32Compare(this, node, &cont);
1800}
1801
1802
1803void InstructionSelector::VisitFloat32LessThan(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001804 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001805 VisitFloat32Compare(this, node, &cont);
1806}
1807
1808
1809void InstructionSelector::VisitFloat32LessThanOrEqual(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001810 FlagsContinuation cont =
1811 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001812 VisitFloat32Compare(this, node, &cont);
1813}
1814
1815
1816void InstructionSelector::VisitFloat64Equal(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001817 FlagsContinuation cont = FlagsContinuation::ForSet(kEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001818 VisitFloat64Compare(this, node, &cont);
1819}
1820
1821
1822void InstructionSelector::VisitFloat64LessThan(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001823 FlagsContinuation cont = FlagsContinuation::ForSet(kUnsignedLessThan, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001824 VisitFloat64Compare(this, node, &cont);
1825}
1826
1827
1828void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) {
Ben Murdochda12d292016-06-02 14:46:10 +01001829 FlagsContinuation cont =
1830 FlagsContinuation::ForSet(kUnsignedLessThanOrEqual, node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001831 VisitFloat64Compare(this, node, &cont);
1832}
1833
1834
1835void InstructionSelector::EmitPrepareArguments(
1836 ZoneVector<PushParameter>* arguments, const CallDescriptor* descriptor,
1837 Node* node) {
1838 PPCOperandGenerator g(this);
1839
1840 // Prepare for C function call.
1841 if (descriptor->IsCFunctionCall()) {
1842 Emit(kArchPrepareCallCFunction |
1843 MiscField::encode(static_cast<int>(descriptor->CParameterCount())),
1844 0, nullptr, 0, nullptr);
1845
1846 // Poke any stack arguments.
1847 int slot = kStackFrameExtraParamSlot;
1848 for (PushParameter input : (*arguments)) {
1849 Emit(kPPC_StoreToStackSlot, g.NoOutput(), g.UseRegister(input.node()),
1850 g.TempImmediate(slot));
1851 ++slot;
1852 }
1853 } else {
1854 // Push any stack arguments.
1855 int num_slots = static_cast<int>(descriptor->StackParameterCount());
1856 int slot = 0;
1857 for (PushParameter input : (*arguments)) {
1858 if (slot == 0) {
1859 DCHECK(input.node());
1860 Emit(kPPC_PushFrame, g.NoOutput(), g.UseRegister(input.node()),
1861 g.TempImmediate(num_slots));
1862 } else {
1863 // Skip any alignment holes in pushed nodes.
1864 if (input.node()) {
1865 Emit(kPPC_StoreToStackSlot, g.NoOutput(), g.UseRegister(input.node()),
1866 g.TempImmediate(slot));
1867 }
1868 }
1869 ++slot;
1870 }
1871 }
1872}
1873
1874
1875bool InstructionSelector::IsTailCallAddressImmediate() { return false; }
1876
Ben Murdochda12d292016-06-02 14:46:10 +01001877int InstructionSelector::GetTempsCountForTailCallFromJSFunction() { return 3; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001878
1879void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) {
1880 PPCOperandGenerator g(this);
1881 Emit(kPPC_DoubleExtractLowWord32, g.DefineAsRegister(node),
1882 g.UseRegister(node->InputAt(0)));
1883}
1884
1885
1886void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) {
1887 PPCOperandGenerator g(this);
1888 Emit(kPPC_DoubleExtractHighWord32, g.DefineAsRegister(node),
1889 g.UseRegister(node->InputAt(0)));
1890}
1891
1892
1893void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) {
1894 PPCOperandGenerator g(this);
1895 Node* left = node->InputAt(0);
1896 Node* right = node->InputAt(1);
1897 if (left->opcode() == IrOpcode::kFloat64InsertHighWord32 &&
1898 CanCover(node, left)) {
1899 left = left->InputAt(1);
1900 Emit(kPPC_DoubleConstruct, g.DefineAsRegister(node), g.UseRegister(left),
1901 g.UseRegister(right));
1902 return;
1903 }
1904 Emit(kPPC_DoubleInsertLowWord32, g.DefineSameAsFirst(node),
1905 g.UseRegister(left), g.UseRegister(right));
1906}
1907
1908
1909void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) {
1910 PPCOperandGenerator g(this);
1911 Node* left = node->InputAt(0);
1912 Node* right = node->InputAt(1);
1913 if (left->opcode() == IrOpcode::kFloat64InsertLowWord32 &&
1914 CanCover(node, left)) {
1915 left = left->InputAt(1);
1916 Emit(kPPC_DoubleConstruct, g.DefineAsRegister(node), g.UseRegister(right),
1917 g.UseRegister(left));
1918 return;
1919 }
1920 Emit(kPPC_DoubleInsertHighWord32, g.DefineSameAsFirst(node),
1921 g.UseRegister(left), g.UseRegister(right));
1922}
1923
Ben Murdochc5610432016-08-08 18:44:38 +01001924void InstructionSelector::VisitAtomicLoad(Node* node) {
1925 LoadRepresentation load_rep = LoadRepresentationOf(node->op());
1926 PPCOperandGenerator g(this);
1927 Node* base = node->InputAt(0);
1928 Node* index = node->InputAt(1);
1929 ArchOpcode opcode = kArchNop;
1930 switch (load_rep.representation()) {
1931 case MachineRepresentation::kWord8:
1932 opcode = load_rep.IsSigned() ? kAtomicLoadInt8 : kAtomicLoadUint8;
1933 break;
1934 case MachineRepresentation::kWord16:
1935 opcode = load_rep.IsSigned() ? kAtomicLoadInt16 : kAtomicLoadUint16;
1936 break;
1937 case MachineRepresentation::kWord32:
1938 opcode = kAtomicLoadWord32;
1939 break;
1940 default:
1941 UNREACHABLE();
1942 return;
1943 }
1944 Emit(opcode | AddressingModeField::encode(kMode_MRR),
1945 g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
1946}
1947
1948void InstructionSelector::VisitAtomicStore(Node* node) {
1949 MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
1950 PPCOperandGenerator g(this);
1951 Node* base = node->InputAt(0);
1952 Node* index = node->InputAt(1);
1953 Node* value = node->InputAt(2);
1954 ArchOpcode opcode = kArchNop;
1955 switch (rep) {
1956 case MachineRepresentation::kWord8:
1957 opcode = kAtomicStoreWord8;
1958 break;
1959 case MachineRepresentation::kWord16:
1960 opcode = kAtomicStoreWord16;
1961 break;
1962 case MachineRepresentation::kWord32:
1963 opcode = kAtomicStoreWord32;
1964 break;
1965 default:
1966 UNREACHABLE();
1967 return;
1968 }
1969
1970 InstructionOperand inputs[4];
1971 size_t input_count = 0;
1972 inputs[input_count++] = g.UseUniqueRegister(base);
1973 inputs[input_count++] = g.UseUniqueRegister(index);
1974 inputs[input_count++] = g.UseUniqueRegister(value);
1975 Emit(opcode | AddressingModeField::encode(kMode_MRR),
1976 0, nullptr, input_count, inputs);
1977}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001978
1979// static
1980MachineOperatorBuilder::Flags
1981InstructionSelector::SupportedMachineOperatorFlags() {
1982 return MachineOperatorBuilder::kFloat32RoundDown |
1983 MachineOperatorBuilder::kFloat64RoundDown |
1984 MachineOperatorBuilder::kFloat32RoundUp |
1985 MachineOperatorBuilder::kFloat64RoundUp |
1986 MachineOperatorBuilder::kFloat32RoundTruncate |
1987 MachineOperatorBuilder::kFloat64RoundTruncate |
1988 MachineOperatorBuilder::kFloat64RoundTiesAway |
1989 MachineOperatorBuilder::kWord32Popcnt |
1990 MachineOperatorBuilder::kWord64Popcnt;
1991 // We omit kWord32ShiftIsSafe as s[rl]w use 0x3f as a mask rather than 0x1f.
1992}
1993
1994} // namespace compiler
1995} // namespace internal
1996} // namespace v8