5 #include "src/compiler/int64-lowering.h" 7 #include "src/compiler/common-operator.h" 8 #include "src/compiler/diamond.h" 9 #include "src/compiler/graph.h" 10 #include "src/compiler/linkage.h" 11 #include "src/compiler/machine-operator.h" 12 #include "src/compiler/node-matchers.h" 13 #include "src/compiler/node-properties.h" 14 #include "src/compiler/node.h" 15 #include "src/compiler/wasm-compiler.h" 17 #include "src/wasm/wasm-linkage.h" 18 #include "src/zone/zone.h" 24 Int64Lowering::Int64Lowering(Graph* graph, MachineOperatorBuilder* machine,
25 CommonOperatorBuilder* common, Zone* zone,
26 Signature<MachineRepresentation>* signature)
33 replacements_(nullptr),
34 signature_(signature),
35 placeholder_(graph->NewNode(common->Parameter(-2,
"placeholder"),
37 DCHECK_NOT_NULL(graph);
38 DCHECK_NOT_NULL(graph->end());
39 replacements_ = zone->NewArray<Replacement>(graph->NodeCount());
40 memset(replacements_, 0,
sizeof(Replacement) * graph->NodeCount());
43 void Int64Lowering::LowerGraph() {
44 if (!machine()->Is32()) {
47 stack_.push_back({graph()->end(), 0});
48 state_.Set(graph()->end(), State::kOnStack);
50 while (!stack_.empty()) {
51 NodeState& top = stack_.back();
52 if (top.input_index == top.node->InputCount()) {
55 state_.Set(top.node, State::kVisited);
59 Node* input = top.node->InputAt(top.input_index++);
60 if (state_.Get(input) == State::kUnvisited) {
61 if (input->opcode() == IrOpcode::kPhi) {
64 PreparePhiReplacement(input);
65 stack_.push_front({input, 0});
66 }
else if (input->opcode() == IrOpcode::kEffectPhi ||
67 input->opcode() == IrOpcode::kLoop) {
68 stack_.push_front({input, 0});
70 stack_.push_back({input, 0});
72 state_.Set(input, State::kOnStack);
80 int GetReturnIndexAfterLowering(CallDescriptor* call_descriptor,
82 int result = old_index;
83 for (
int i = 0;
i < old_index;
i++) {
84 if (call_descriptor->GetReturnType(
i).representation() ==
85 MachineRepresentation::kWord64) {
92 int GetReturnCountAfterLowering(CallDescriptor* call_descriptor) {
93 return GetReturnIndexAfterLowering(
94 call_descriptor, static_cast<int>(call_descriptor->ReturnCount()));
97 int GetParameterIndexAfterLowering(
98 Signature<MachineRepresentation>* signature,
int old_index) {
99 int result = old_index;
100 for (
int i = 0;
i < old_index;
i++) {
101 if (signature->GetParam(
i) == MachineRepresentation::kWord64) {
108 int GetReturnCountAfterLowering(Signature<MachineRepresentation>* signature) {
109 int result =
static_cast<int>(signature->return_count());
110 for (
int i = 0; i < static_cast<int>(signature->return_count());
i++) {
111 if (signature->GetReturn(
i) == MachineRepresentation::kWord64) {
120 void Int64Lowering::LowerWord64AtomicBinop(Node* node,
const Operator* op) {
121 DCHECK_EQ(5, node->InputCount());
122 Node* value = node->InputAt(2);
123 node->ReplaceInput(2, GetReplacementLow(value));
124 node->InsertInput(zone(), 3, GetReplacementHigh(value));
125 NodeProperties::ChangeOp(node, op);
126 ReplaceNodeWithProjections(node);
129 void Int64Lowering::LowerWord64AtomicNarrowOp(Node* node,
const Operator* op) {
130 Node* value = node->InputAt(2);
131 node->ReplaceInput(2, GetReplacementLow(value));
132 NodeProperties::ChangeOp(node, op);
133 ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
137 int Int64Lowering::GetParameterCountAfterLowering(
138 Signature<MachineRepresentation>* signature) {
141 return GetParameterIndexAfterLowering(
142 signature, static_cast<int>(signature->parameter_count()));
145 void Int64Lowering::GetIndexNodes(Node* index, Node*& index_low,
147 if (HasReplacementLow(index)) {
148 index = GetReplacementLow(index);
150 #if defined(V8_TARGET_LITTLE_ENDIAN) 152 index_high = graph()->NewNode(machine()->Int32Add(), index,
153 graph()->NewNode(common()->Int32Constant(4)));
154 #elif defined(V8_TARGET_BIG_ENDIAN) 155 index_low = graph()->NewNode(machine()->Int32Add(), index,
156 graph()->NewNode(common()->Int32Constant(4)));
161 void Int64Lowering::LowerNode(Node* node) {
162 switch (node->opcode()) {
163 case IrOpcode::kInt64Constant: {
164 int64_t value = OpParameter<int64_t>(node->op());
165 Node* low_node = graph()->NewNode(
166 common()->Int32Constant(static_cast<int32_t>(value & 0xFFFFFFFF)));
167 Node* high_node = graph()->NewNode(
168 common()->Int32Constant(static_cast<int32_t>(value >> 32)));
169 ReplaceNode(node, low_node, high_node);
172 case IrOpcode::kLoad:
173 case IrOpcode::kUnalignedLoad: {
174 MachineRepresentation rep;
175 if (node->opcode() == IrOpcode::kLoad) {
176 rep = LoadRepresentationOf(node->op()).representation();
178 DCHECK_EQ(IrOpcode::kUnalignedLoad, node->opcode());
179 rep = LoadRepresentationOf(node->op()).representation();
182 if (rep == MachineRepresentation::kWord64) {
183 Node* base = node->InputAt(0);
184 Node* index = node->InputAt(1);
187 GetIndexNodes(index, index_low, index_high);
188 const Operator* load_op;
190 if (node->opcode() == IrOpcode::kLoad) {
191 load_op = machine()->Load(MachineType::Int32());
193 DCHECK_EQ(IrOpcode::kUnalignedLoad, node->opcode());
194 load_op = machine()->UnalignedLoad(MachineType::Int32());
198 if (node->InputCount() > 2) {
199 Node* effect_high = node->InputAt(2);
200 Node* control_high = node->InputAt(3);
201 high_node = graph()->NewNode(load_op, base, index_high, effect_high,
205 node->ReplaceInput(2, high_node);
207 high_node = graph()->NewNode(load_op, base, index_high);
209 node->ReplaceInput(1, index_low);
210 NodeProperties::ChangeOp(node, load_op);
211 ReplaceNode(node, node, high_node);
213 DefaultLowering(node);
217 case IrOpcode::kStore:
218 case IrOpcode::kUnalignedStore: {
219 MachineRepresentation rep;
220 if (node->opcode() == IrOpcode::kStore) {
221 rep = StoreRepresentationOf(node->op()).representation();
223 DCHECK_EQ(IrOpcode::kUnalignedStore, node->opcode());
224 rep = UnalignedStoreRepresentationOf(node->op());
227 if (rep == MachineRepresentation::kWord64) {
232 Node* base = node->InputAt(0);
233 Node* index = node->InputAt(1);
236 GetIndexNodes(index, index_low, index_high);
237 Node* value = node->InputAt(2);
238 DCHECK(HasReplacementLow(value));
239 DCHECK(HasReplacementHigh(value));
241 const Operator* store_op;
242 if (node->opcode() == IrOpcode::kStore) {
243 WriteBarrierKind write_barrier_kind =
244 StoreRepresentationOf(node->op()).write_barrier_kind();
245 store_op = machine()->Store(StoreRepresentation(
246 MachineRepresentation::kWord32, write_barrier_kind));
248 DCHECK_EQ(IrOpcode::kUnalignedStore, node->opcode());
249 store_op = machine()->UnalignedStore(MachineRepresentation::kWord32);
253 if (node->InputCount() > 3) {
254 Node* effect_high = node->InputAt(3);
255 Node* control_high = node->InputAt(4);
256 high_node = graph()->NewNode(store_op, base, index_high,
257 GetReplacementHigh(value), effect_high,
259 node->ReplaceInput(3, high_node);
262 high_node = graph()->NewNode(store_op, base, index_high,
263 GetReplacementHigh(value));
266 node->ReplaceInput(1, index_low);
267 node->ReplaceInput(2, GetReplacementLow(value));
268 NodeProperties::ChangeOp(node, store_op);
269 ReplaceNode(node, node, high_node);
271 DefaultLowering(node,
true);
275 case IrOpcode::kStart: {
276 int parameter_count = GetParameterCountAfterLowering(signature());
278 if (parameter_count != static_cast<int>(signature()->parameter_count())) {
280 parameter_count -
static_cast<int>(signature()->parameter_count());
281 int new_output_count = node->op()->ValueOutputCount() + delta;
282 NodeProperties::ChangeOp(node, common()->Start(new_output_count));
286 case IrOpcode::kParameter: {
287 DCHECK_EQ(1, node->InputCount());
292 if (GetParameterCountAfterLowering(signature()) !=
293 static_cast<int>(signature()->parameter_count())) {
294 int old_index = ParameterIndexOf(node->op());
297 if (old_index == wasm::kWasmInstanceParameterIndex) {
298 DefaultLowering(node);
303 int new_index = GetParameterIndexAfterLowering(signature(), old_index);
306 NodeProperties::ChangeOp(node, common()->Parameter(new_index));
308 if (signature()->GetParam(old_index) ==
309 MachineRepresentation::kWord64) {
310 Node* high_node = graph()->NewNode(common()->Parameter(new_index + 1),
312 ReplaceNode(node, node, high_node);
317 case IrOpcode::kReturn: {
318 int input_count = node->InputCount();
319 DefaultLowering(node);
320 if (input_count != node->InputCount()) {
321 int new_return_count = GetReturnCountAfterLowering(signature());
322 if (static_cast<int>(signature()->return_count()) != new_return_count) {
323 NodeProperties::ChangeOp(node, common()->Return(new_return_count));
328 case IrOpcode::kTailCall: {
329 auto call_descriptor =
330 const_cast<CallDescriptor*
>(CallDescriptorOf(node->op()));
331 bool returns_require_lowering =
332 GetReturnCountAfterLowering(call_descriptor) !=
333 static_cast<int>(call_descriptor->ReturnCount());
334 if (DefaultLowering(node) || returns_require_lowering) {
337 auto new_descriptor = GetI32WasmCallDescriptor(zone(), call_descriptor);
338 NodeProperties::ChangeOp(node, common()->TailCall(new_descriptor));
342 case IrOpcode::kCall: {
343 auto call_descriptor =
344 const_cast<CallDescriptor*
>(CallDescriptorOf(node->op()));
345 bool returns_require_lowering =
346 GetReturnCountAfterLowering(call_descriptor) !=
347 static_cast<int>(call_descriptor->ReturnCount());
348 if (DefaultLowering(node) || returns_require_lowering) {
350 NodeProperties::ChangeOp(node, common()->Call(GetI32WasmCallDescriptor(
351 zone(), call_descriptor)));
353 if (returns_require_lowering) {
354 size_t return_arity = call_descriptor->ReturnCount();
355 if (return_arity == 1) {
357 ReplaceNodeWithProjections(node);
359 ZoneVector<Node*> projections(return_arity, zone());
360 NodeProperties::CollectValueProjections(node, projections.data(),
362 for (
size_t old_index = 0, new_index = 0; old_index < return_arity;
363 ++old_index, ++new_index) {
364 Node* use_node = projections[old_index];
365 DCHECK_EQ(ProjectionIndexOf(use_node->op()), old_index);
366 DCHECK_EQ(GetReturnIndexAfterLowering(call_descriptor,
367 static_cast<int>(old_index)),
368 static_cast<int>(new_index));
369 if (new_index != old_index) {
370 NodeProperties::ChangeOp(
371 use_node, common()->Projection(new_index));
373 if (call_descriptor->GetReturnType(old_index).representation() ==
374 MachineRepresentation::kWord64) {
375 Node* high_node = graph()->NewNode(
376 common()->Projection(new_index + 1), node,
378 ReplaceNode(use_node, use_node, high_node);
386 case IrOpcode::kWord64And: {
387 DCHECK_EQ(2, node->InputCount());
388 Node* left = node->InputAt(0);
389 Node* right = node->InputAt(1);
392 graph()->NewNode(machine()->Word32And(), GetReplacementLow(left),
393 GetReplacementLow(right));
395 graph()->NewNode(machine()->Word32And(), GetReplacementHigh(left),
396 GetReplacementHigh(right));
397 ReplaceNode(node, low_node, high_node);
400 case IrOpcode::kTruncateInt64ToInt32: {
401 DCHECK_EQ(1, node->InputCount());
402 Node* input = node->InputAt(0);
403 ReplaceNode(node, GetReplacementLow(input),
nullptr);
404 node->NullAllInputs();
407 case IrOpcode::kInt64Add: {
408 DCHECK_EQ(2, node->InputCount());
410 Node* right = node->InputAt(1);
411 node->ReplaceInput(1, GetReplacementLow(right));
412 node->AppendInput(zone(), GetReplacementHigh(right));
414 Node* left = node->InputAt(0);
415 node->ReplaceInput(0, GetReplacementLow(left));
416 node->InsertInput(zone(), 1, GetReplacementHigh(left));
418 NodeProperties::ChangeOp(node, machine()->Int32PairAdd());
420 ReplaceNodeWithProjections(node);
423 case IrOpcode::kInt64Sub: {
424 DCHECK_EQ(2, node->InputCount());
426 Node* right = node->InputAt(1);
427 node->ReplaceInput(1, GetReplacementLow(right));
428 node->AppendInput(zone(), GetReplacementHigh(right));
430 Node* left = node->InputAt(0);
431 node->ReplaceInput(0, GetReplacementLow(left));
432 node->InsertInput(zone(), 1, GetReplacementHigh(left));
434 NodeProperties::ChangeOp(node, machine()->Int32PairSub());
436 ReplaceNodeWithProjections(node);
439 case IrOpcode::kInt64Mul: {
440 DCHECK_EQ(2, node->InputCount());
442 Node* right = node->InputAt(1);
443 node->ReplaceInput(1, GetReplacementLow(right));
444 node->AppendInput(zone(), GetReplacementHigh(right));
446 Node* left = node->InputAt(0);
447 node->ReplaceInput(0, GetReplacementLow(left));
448 node->InsertInput(zone(), 1, GetReplacementHigh(left));
450 NodeProperties::ChangeOp(node, machine()->Int32PairMul());
452 ReplaceNodeWithProjections(node);
455 case IrOpcode::kWord64Or: {
456 DCHECK_EQ(2, node->InputCount());
457 Node* left = node->InputAt(0);
458 Node* right = node->InputAt(1);
461 graph()->NewNode(machine()->Word32Or(), GetReplacementLow(left),
462 GetReplacementLow(right));
464 graph()->NewNode(machine()->Word32Or(), GetReplacementHigh(left),
465 GetReplacementHigh(right));
466 ReplaceNode(node, low_node, high_node);
469 case IrOpcode::kWord64Xor: {
470 DCHECK_EQ(2, node->InputCount());
471 Node* left = node->InputAt(0);
472 Node* right = node->InputAt(1);
475 graph()->NewNode(machine()->Word32Xor(), GetReplacementLow(left),
476 GetReplacementLow(right));
478 graph()->NewNode(machine()->Word32Xor(), GetReplacementHigh(left),
479 GetReplacementHigh(right));
480 ReplaceNode(node, low_node, high_node);
483 case IrOpcode::kWord64Shl: {
486 DCHECK_EQ(2, node->InputCount());
487 Node* shift = node->InputAt(1);
488 if (HasReplacementLow(shift)) {
491 node->ReplaceInput(1, GetReplacementLow(shift));
494 Node* value = node->InputAt(0);
495 node->ReplaceInput(0, GetReplacementLow(value));
496 node->InsertInput(zone(), 1, GetReplacementHigh(value));
498 NodeProperties::ChangeOp(node, machine()->Word32PairShl());
500 ReplaceNodeWithProjections(node);
503 case IrOpcode::kWord64Shr: {
506 DCHECK_EQ(2, node->InputCount());
507 Node* shift = node->InputAt(1);
508 if (HasReplacementLow(shift)) {
511 node->ReplaceInput(1, GetReplacementLow(shift));
514 Node* value = node->InputAt(0);
515 node->ReplaceInput(0, GetReplacementLow(value));
516 node->InsertInput(zone(), 1, GetReplacementHigh(value));
518 NodeProperties::ChangeOp(node, machine()->Word32PairShr());
520 ReplaceNodeWithProjections(node);
523 case IrOpcode::kWord64Sar: {
526 DCHECK_EQ(2, node->InputCount());
527 Node* shift = node->InputAt(1);
528 if (HasReplacementLow(shift)) {
531 node->ReplaceInput(1, GetReplacementLow(shift));
534 Node* value = node->InputAt(0);
535 node->ReplaceInput(0, GetReplacementLow(value));
536 node->InsertInput(zone(), 1, GetReplacementHigh(value));
538 NodeProperties::ChangeOp(node, machine()->Word32PairSar());
540 ReplaceNodeWithProjections(node);
543 case IrOpcode::kWord64Equal: {
544 DCHECK_EQ(2, node->InputCount());
545 Node* left = node->InputAt(0);
546 Node* right = node->InputAt(1);
549 Node* replacement = graph()->NewNode(
550 machine()->Word32Equal(),
552 machine()->Word32Or(),
553 graph()->NewNode(machine()->Word32Xor(), GetReplacementLow(left),
554 GetReplacementLow(right)),
555 graph()->NewNode(machine()->Word32Xor(), GetReplacementHigh(left),
556 GetReplacementHigh(right))),
557 graph()->NewNode(common()->Int32Constant(0)));
559 ReplaceNode(node, replacement,
nullptr);
562 case IrOpcode::kInt64LessThan: {
563 LowerComparison(node, machine()->Int32LessThan(),
564 machine()->Uint32LessThan());
567 case IrOpcode::kInt64LessThanOrEqual: {
568 LowerComparison(node, machine()->Int32LessThan(),
569 machine()->Uint32LessThanOrEqual());
572 case IrOpcode::kUint64LessThan: {
573 LowerComparison(node, machine()->Uint32LessThan(),
574 machine()->Uint32LessThan());
577 case IrOpcode::kUint64LessThanOrEqual: {
578 LowerComparison(node, machine()->Uint32LessThan(),
579 machine()->Uint32LessThanOrEqual());
582 case IrOpcode::kSignExtendWord32ToInt64:
583 case IrOpcode::kChangeInt32ToInt64: {
584 DCHECK_EQ(1, node->InputCount());
585 Node* input = node->InputAt(0);
586 if (HasReplacementLow(input)) {
587 input = GetReplacementLow(input);
592 graph()->NewNode(machine()->Word32Sar(), input,
593 graph()->NewNode(common()->Int32Constant(31))));
594 node->NullAllInputs();
597 case IrOpcode::kChangeUint32ToUint64: {
598 DCHECK_EQ(1, node->InputCount());
599 Node* input = node->InputAt(0);
600 if (HasReplacementLow(input)) {
601 input = GetReplacementLow(input);
603 ReplaceNode(node, input, graph()->NewNode(common()->Int32Constant(0)));
604 node->NullAllInputs();
607 case IrOpcode::kBitcastInt64ToFloat64: {
608 DCHECK_EQ(1, node->InputCount());
609 Node* input = node->InputAt(0);
610 Node* stack_slot = graph()->NewNode(
611 machine()->StackSlot(MachineRepresentation::kWord64));
613 Node* store_high_word = graph()->NewNode(
615 StoreRepresentation(MachineRepresentation::kWord32,
616 WriteBarrierKind::kNoWriteBarrier)),
619 common()->Int32Constant(kInt64UpperHalfMemoryOffset)),
620 GetReplacementHigh(input), graph()->start(), graph()->start());
622 Node* store_low_word = graph()->NewNode(
624 StoreRepresentation(MachineRepresentation::kWord32,
625 WriteBarrierKind::kNoWriteBarrier)),
628 common()->Int32Constant(kInt64LowerHalfMemoryOffset)),
629 GetReplacementLow(input), store_high_word, graph()->start());
632 graph()->NewNode(machine()->Load(MachineType::Float64()), stack_slot,
633 graph()->NewNode(common()->Int32Constant(0)),
634 store_low_word, graph()->start());
636 ReplaceNode(node, load,
nullptr);
639 case IrOpcode::kBitcastFloat64ToInt64: {
640 DCHECK_EQ(1, node->InputCount());
641 Node* input = node->InputAt(0);
642 if (HasReplacementLow(input)) {
643 input = GetReplacementLow(input);
645 Node* stack_slot = graph()->NewNode(
646 machine()->StackSlot(MachineRepresentation::kWord64));
647 Node* store = graph()->NewNode(
649 StoreRepresentation(MachineRepresentation::kFloat64,
650 WriteBarrierKind::kNoWriteBarrier)),
651 stack_slot, graph()->NewNode(common()->Int32Constant(0)), input,
652 graph()->start(), graph()->start());
654 Node* high_node = graph()->NewNode(
655 machine()->Load(MachineType::Int32()), stack_slot,
657 common()->Int32Constant(kInt64UpperHalfMemoryOffset)),
658 store, graph()->start());
660 Node* low_node = graph()->NewNode(
661 machine()->Load(MachineType::Int32()), stack_slot,
663 common()->Int32Constant(kInt64LowerHalfMemoryOffset)),
664 store, graph()->start());
665 ReplaceNode(node, low_node, high_node);
668 case IrOpcode::kWord64Ror: {
669 DCHECK_EQ(2, node->InputCount());
670 Node* input = node->InputAt(0);
671 Node* shift = HasReplacementLow(node->InputAt(1))
672 ? GetReplacementLow(node->InputAt(1))
674 Int32Matcher m(shift);
677 int32_t shift_value = m.Value() & 0x3F;
678 if (shift_value == 0) {
679 ReplaceNode(node, GetReplacementLow(input),
680 GetReplacementHigh(input));
681 }
else if (shift_value == 32) {
682 ReplaceNode(node, GetReplacementHigh(input),
683 GetReplacementLow(input));
687 if (shift_value < 32) {
688 low_input = GetReplacementLow(input);
689 high_input = GetReplacementHigh(input);
691 low_input = GetReplacementHigh(input);
692 high_input = GetReplacementLow(input);
694 int32_t masked_shift_value = shift_value & 0x1F;
696 graph()->NewNode(common()->Int32Constant(masked_shift_value));
697 Node* inv_shift = graph()->NewNode(
698 common()->Int32Constant(32 - masked_shift_value));
700 Node* low_node = graph()->NewNode(
701 machine()->Word32Or(),
702 graph()->NewNode(machine()->Word32Shr(), low_input, masked_shift),
703 graph()->NewNode(machine()->Word32Shl(), high_input, inv_shift));
704 Node* high_node = graph()->NewNode(
705 machine()->Word32Or(), graph()->NewNode(machine()->Word32Shr(),
706 high_input, masked_shift),
707 graph()->NewNode(machine()->Word32Shl(), low_input, inv_shift));
708 ReplaceNode(node, low_node, high_node);
711 Node* safe_shift = shift;
712 if (!machine()->Word32ShiftIsSafe()) {
714 graph()->NewNode(machine()->Word32And(), shift,
715 graph()->NewNode(common()->Int32Constant(0x1F)));
720 Node* inv_mask = graph()->NewNode(
721 machine()->Word32Shl(),
722 graph()->NewNode(machine()->Word32Sar(),
723 graph()->NewNode(common()->Int32Constant(
724 std::numeric_limits<int32_t>::min())),
726 graph()->NewNode(common()->Int32Constant(1)));
729 graph()->NewNode(machine()->Word32Xor(), inv_mask,
730 graph()->NewNode(common()->Int32Constant(-1)));
735 Node* masked_shift6 = shift;
736 if (machine()->Word32ShiftIsSafe()) {
738 graph()->NewNode(machine()->Word32And(), shift,
739 graph()->NewNode(common()->Int32Constant(0x3F)));
744 graph()->NewNode(machine()->Int32LessThan(), masked_shift6,
745 graph()->NewNode(common()->Int32Constant(32))));
751 lt32.Phi(MachineRepresentation::kWord32, GetReplacementLow(input),
752 GetReplacementHigh(input));
754 lt32.Phi(MachineRepresentation::kWord32, GetReplacementHigh(input),
755 GetReplacementLow(input));
758 graph()->NewNode(machine()->Word32Ror(), input_low, safe_shift);
760 graph()->NewNode(machine()->Word32Ror(), input_high, safe_shift);
762 Node* low_node = graph()->NewNode(
763 machine()->Word32Or(),
764 graph()->NewNode(machine()->Word32And(), rotate_low, bit_mask),
765 graph()->NewNode(machine()->Word32And(), rotate_high, inv_mask));
767 Node* high_node = graph()->NewNode(
768 machine()->Word32Or(),
769 graph()->NewNode(machine()->Word32And(), rotate_high, bit_mask),
770 graph()->NewNode(machine()->Word32And(), rotate_low, inv_mask));
772 ReplaceNode(node, low_node, high_node);
776 case IrOpcode::kWord64Clz: {
777 DCHECK_EQ(1, node->InputCount());
778 Node* input = node->InputAt(0);
781 graph()->NewNode(machine()->Word32Equal(), GetReplacementHigh(input),
782 graph()->NewNode(common()->Int32Constant(0))));
784 Node* low_node = d.Phi(
785 MachineRepresentation::kWord32,
786 graph()->NewNode(machine()->Int32Add(),
787 graph()->NewNode(machine()->Word32Clz(),
788 GetReplacementLow(input)),
789 graph()->NewNode(common()->Int32Constant(32))),
790 graph()->NewNode(machine()->Word32Clz(), GetReplacementHigh(input)));
791 ReplaceNode(node, low_node, graph()->NewNode(common()->Int32Constant(0)));
794 case IrOpcode::kWord64Ctz: {
795 DCHECK_EQ(1, node->InputCount());
796 DCHECK(machine()->Word32Ctz().IsSupported());
797 Node* input = node->InputAt(0);
800 graph()->NewNode(machine()->Word32Equal(), GetReplacementLow(input),
801 graph()->NewNode(common()->Int32Constant(0))));
803 d.Phi(MachineRepresentation::kWord32,
804 graph()->NewNode(machine()->Int32Add(),
805 graph()->NewNode(machine()->Word32Ctz().op(),
806 GetReplacementHigh(input)),
807 graph()->NewNode(common()->Int32Constant(32))),
808 graph()->NewNode(machine()->Word32Ctz().op(),
809 GetReplacementLow(input)));
810 ReplaceNode(node, low_node, graph()->NewNode(common()->Int32Constant(0)));
813 case IrOpcode::kWord64Popcnt: {
814 DCHECK_EQ(1, node->InputCount());
815 Node* input = node->InputAt(0);
818 DCHECK(machine()->Word32Popcnt().IsSupported());
819 ReplaceNode(node, graph()->NewNode(
820 machine()->Int32Add(),
821 graph()->NewNode(machine()->Word32Popcnt().op(),
822 GetReplacementLow(input)),
823 graph()->NewNode(machine()->Word32Popcnt().op(),
824 GetReplacementHigh(input))),
825 graph()->NewNode(common()->Int32Constant(0)));
828 case IrOpcode::kPhi: {
829 MachineRepresentation rep = PhiRepresentationOf(node->op());
830 if (rep == MachineRepresentation::kWord64) {
833 Node* low_node = GetReplacementLow(node);
834 Node* high_node = GetReplacementHigh(node);
835 for (
int i = 0;
i < node->op()->ValueInputCount();
i++) {
836 low_node->ReplaceInput(
i, GetReplacementLow(node->InputAt(
i)));
837 high_node->ReplaceInput(
i, GetReplacementHigh(node->InputAt(
i)));
840 DefaultLowering(node);
844 case IrOpcode::kWord64ReverseBytes: {
845 Node* input = node->InputAt(0);
847 graph()->NewNode(machine()->Word32ReverseBytes(),
848 GetReplacementHigh(input)),
849 graph()->NewNode(machine()->Word32ReverseBytes(),
850 GetReplacementLow(input)));
853 case IrOpcode::kSignExtendWord8ToInt64: {
854 DCHECK_EQ(1, node->InputCount());
855 Node* input = node->InputAt(0);
856 if (HasReplacementLow(input)) {
857 input = GetReplacementLow(input);
860 input = graph()->NewNode(machine()->SignExtendWord8ToInt32(), input);
865 graph()->NewNode(machine()->Word32Sar(), input,
866 graph()->NewNode(common()->Int32Constant(31))));
867 node->NullAllInputs();
870 case IrOpcode::kSignExtendWord16ToInt64: {
871 DCHECK_EQ(1, node->InputCount());
872 Node* input = node->InputAt(0);
873 if (HasReplacementLow(input)) {
874 input = GetReplacementLow(input);
877 input = graph()->NewNode(machine()->SignExtendWord16ToInt32(), input);
882 graph()->NewNode(machine()->Word32Sar(), input,
883 graph()->NewNode(common()->Int32Constant(31))));
884 node->NullAllInputs();
887 case IrOpcode::kWord64AtomicLoad: {
888 DCHECK_EQ(4, node->InputCount());
889 MachineType type = AtomicOpType(node->op());
890 if (type == MachineType::Uint64()) {
891 NodeProperties::ChangeOp(node, machine()->Word32AtomicPairLoad());
892 ReplaceNodeWithProjections(node);
894 NodeProperties::ChangeOp(node, machine()->Word32AtomicLoad(type));
895 ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
899 case IrOpcode::kWord64AtomicStore: {
900 DCHECK_EQ(5, node->InputCount());
901 MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
902 if (rep == MachineRepresentation::kWord64) {
903 Node* value = node->InputAt(2);
904 node->ReplaceInput(2, GetReplacementLow(value));
905 node->InsertInput(zone(), 3, GetReplacementHigh(value));
906 NodeProperties::ChangeOp(node, machine()->Word32AtomicPairStore());
908 DefaultLowering(node,
true);
909 NodeProperties::ChangeOp(node, machine()->Word32AtomicStore(rep));
913 #define ATOMIC_CASE(name) \ 914 case IrOpcode::kWord64Atomic##name: { \ 915 MachineType type = AtomicOpType(node->op()); \ 916 if (type == MachineType::Uint64()) { \ 917 LowerWord64AtomicBinop(node, machine()->Word32AtomicPair##name()); \ 919 LowerWord64AtomicNarrowOp(node, machine()->Word32Atomic##name(type)); \ 928 ATOMIC_CASE(Exchange)
930 case IrOpcode::kWord64AtomicCompareExchange: {
931 MachineType type = AtomicOpType(node->op());
932 if (type == MachineType::Uint64()) {
933 Node* old_value = node->InputAt(2);
934 Node* new_value = node->InputAt(3);
935 node->ReplaceInput(2, GetReplacementLow(old_value));
936 node->ReplaceInput(3, GetReplacementHigh(old_value));
937 node->InsertInput(zone(), 4, GetReplacementLow(new_value));
938 node->InsertInput(zone(), 5, GetReplacementHigh(new_value));
939 NodeProperties::ChangeOp(node,
940 machine()->Word32AtomicPairCompareExchange());
941 ReplaceNodeWithProjections(node);
943 DCHECK(type == MachineType::Uint32() || type == MachineType::Uint16() ||
944 type == MachineType::Uint8());
945 Node* old_value = node->InputAt(2);
946 node->ReplaceInput(2, GetReplacementLow(old_value));
947 Node* new_value = node->InputAt(3);
948 node->ReplaceInput(3, GetReplacementLow(new_value));
949 NodeProperties::ChangeOp(node,
950 machine()->Word32AtomicCompareExchange(type));
951 ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
956 default: { DefaultLowering(node); }
960 void Int64Lowering::LowerComparison(Node* node,
const Operator* high_word_op,
961 const Operator* low_word_op) {
962 DCHECK_EQ(2, node->InputCount());
963 Node* left = node->InputAt(0);
964 Node* right = node->InputAt(1);
965 Node* replacement = graph()->NewNode(
966 machine()->Word32Or(),
967 graph()->NewNode(high_word_op, GetReplacementHigh(left),
968 GetReplacementHigh(right)),
970 machine()->Word32And(),
971 graph()->NewNode(machine()->Word32Equal(), GetReplacementHigh(left),
972 GetReplacementHigh(right)),
973 graph()->NewNode(low_word_op, GetReplacementLow(left),
974 GetReplacementLow(right))));
976 ReplaceNode(node, replacement,
nullptr);
979 bool Int64Lowering::DefaultLowering(Node* node,
bool low_word_only) {
980 bool something_changed =
false;
981 for (
int i = NodeProperties::PastValueIndex(node) - 1;
i >= 0;
i--) {
982 Node* input = node->InputAt(
i);
983 if (HasReplacementLow(input)) {
984 something_changed =
true;
985 node->ReplaceInput(
i, GetReplacementLow(input));
987 if (!low_word_only && HasReplacementHigh(input)) {
988 something_changed =
true;
989 node->InsertInput(zone(),
i + 1, GetReplacementHigh(input));
992 return something_changed;
995 void Int64Lowering::ReplaceNode(Node* old, Node* new_low, Node* new_high) {
997 DCHECK(new_low !=
nullptr || new_high ==
nullptr);
998 replacements_[old->id()].low = new_low;
999 replacements_[old->id()].high = new_high;
1002 bool Int64Lowering::HasReplacementLow(Node* node) {
1003 return replacements_[node->id()].low !=
nullptr;
1006 Node* Int64Lowering::GetReplacementLow(Node* node) {
1007 Node* result = replacements_[node->id()].low;
1012 bool Int64Lowering::HasReplacementHigh(Node* node) {
1013 return replacements_[node->id()].high !=
nullptr;
1016 Node* Int64Lowering::GetReplacementHigh(Node* node) {
1017 Node* result = replacements_[node->id()].high;
1022 void Int64Lowering::PreparePhiReplacement(Node* phi) {
1023 MachineRepresentation rep = PhiRepresentationOf(phi->op());
1024 if (rep == MachineRepresentation::kWord64) {
1029 int value_count = phi->op()->ValueInputCount();
1030 Node** inputs_low = zone()->NewArray<Node*>(value_count + 1);
1031 Node** inputs_high = zone()->NewArray<Node*>(value_count + 1);
1032 for (
int i = 0;
i < value_count;
i++) {
1033 inputs_low[
i] = placeholder_;
1034 inputs_high[
i] = placeholder_;
1036 inputs_low[value_count] = NodeProperties::GetControlInput(phi, 0);
1037 inputs_high[value_count] = NodeProperties::GetControlInput(phi, 0);
1040 common()->Phi(MachineRepresentation::kWord32, value_count),
1041 value_count + 1, inputs_low,
false),
1043 common()->Phi(MachineRepresentation::kWord32, value_count),
1044 value_count + 1, inputs_high,
false));
1048 void Int64Lowering::ReplaceNodeWithProjections(Node* node) {
1049 DCHECK(node !=
nullptr);
1051 graph()->NewNode(common()->Projection(0), node, graph()->start());
1053 graph()->NewNode(common()->Projection(1), node, graph()->start());
1054 ReplaceNode(node, low_node, high_node);