23#if V8_TARGET_ARCH_32_BIT
30 CommonOperatorBuilder* common,
31 SimplifiedOperatorBuilder* simplified,
Zone* zone,
32 Signature<MachineRepresentation>* signature)
36 simplified_(simplified),
38 signature_(signature),
41 replacements_(nullptr),
42 placeholder_(graph->NewNode(common->Dead())) {
45 replacements_ = zone->AllocateArray<Replacement>(graph->NodeCount());
46 memset(replacements_, 0,
sizeof(Replacement) * graph->NodeCount());
49void Int64Lowering::LowerGraph() {
50 stack_.push_back({
graph()->end(), 0});
53 while (!stack_.empty()) {
54 NodeState& top = stack_.back();
55 if (top.input_index == top.node->InputCount()) {
57 Node* node = top.node;
59 state_[node->id()] = State::kVisited;
63 Node* input = top.node->InputAt(top.input_index++);
64 if (
state_[input->id()] == State::kUnvisited) {
65 if (input->opcode() == IrOpcode::kPhi) {
68 PreparePhiReplacement(input);
69 stack_.push_front({input, 0});
70 }
else if (input->opcode() == IrOpcode::kEffectPhi ||
71 input->opcode() == IrOpcode::kLoop) {
72 stack_.push_front({input, 0});
74 stack_.push_back({input, 0});
76 state_[input->id()] = State::kOnStack;
84int GetReturnIndexAfterLowering(
const CallDescriptor* call_descriptor,
87 for (
int i = 0;
i < old_index;
i++) {
88 if (call_descriptor->GetReturnType(
i).representation() ==
89 MachineRepresentation::kWord64) {
96int GetReturnCountAfterLowering(
const CallDescriptor* call_descriptor) {
97 return GetReturnIndexAfterLowering(
98 call_descriptor,
static_cast<int>(call_descriptor->ReturnCount()));
101int GetParameterIndexAfterLowering(
102 Signature<MachineRepresentation>* signature,
int old_index) {
106 std::min(old_index,
static_cast<int>(signature->parameter_count()));
107 for (
int i = 0;
i < max_to_check;
i++) {
108 if (signature->GetParam(
i) == MachineRepresentation::kWord64) {
115int GetReturnCountAfterLowering(Signature<MachineRepresentation>* signature) {
116 int result =
static_cast<int>(signature->return_count());
117 for (
int i = 0; i < static_cast<int>(signature->return_count());
i++) {
118 if (signature->GetReturn(
i) == MachineRepresentation::kWord64) {
127void Int64Lowering::LowerWord64AtomicBinop(Node* node,
const Operator* op) {
129 LowerMemoryBaseAndIndex(node);
130 Node* value = node->InputAt(2);
131 node->ReplaceInput(2, GetReplacementLow(value));
132 node->InsertInput(zone(), 3, GetReplacementHigh(value));
133 NodeProperties::ChangeOp(node, op);
134 ReplaceNodeWithProjections(node);
137void Int64Lowering::LowerWord64AtomicNarrowOp(Node* node,
const Operator* op) {
138 DefaultLowering(node,
true);
139 NodeProperties::ChangeOp(node, op);
140 ReplaceNode(node, node,
graph()->NewNode(common()->Int32Constant(0)));
144int Int64Lowering::GetParameterCountAfterLowering(
145 Signature<MachineRepresentation>* signature) {
148 return GetParameterIndexAfterLowering(
149 signature,
static_cast<int>(signature->parameter_count()));
152void Int64Lowering::GetIndexNodes(Node* index, Node** index_low,
159 ?
graph()->NewNode(common()->Int32Constant(
m.ResolvedValue() + 4))
160 :
graph()->NewNode(machine()->Int32Add(), index,
161 graph()->NewNode(common()->Int32Constant(4)));
162#if defined(V8_TARGET_LITTLE_ENDIAN)
164 *index_high = index_second;
165#elif defined(V8_TARGET_BIG_ENDIAN)
166 *index_low = index_second;
171void Int64Lowering::LowerLoadOperator(Node* node, MachineRepresentation rep,
172 const Operator* load_op) {
173 if (rep == MachineRepresentation::kWord64) {
174 LowerMemoryBaseAndIndex(node);
175 Node*
base = node->InputAt(0);
176 Node* index = node->InputAt(1);
179 GetIndexNodes(index, &index_low, &index_high);
181 if (node->InputCount() > 2) {
182 Node* effect_high = node->InputAt(2);
183 Node* control_high = node->InputAt(3);
184 high_node =
graph()->NewNode(load_op,
base, index_high, effect_high,
188 node->ReplaceInput(2, high_node);
190 high_node =
graph()->NewNode(load_op,
base, index_high);
192 node->ReplaceInput(1, index_low);
193 NodeProperties::ChangeOp(node, load_op);
194 ReplaceNode(node, node, high_node);
196 DefaultLowering(node);
200void Int64Lowering::LowerStoreOperator(Node* node, MachineRepresentation rep,
201 const Operator* store_op) {
202 if (rep == MachineRepresentation::kWord64) {
207 LowerMemoryBaseAndIndex(node);
208 Node*
base = node->InputAt(0);
209 Node* index = node->InputAt(1);
212 GetIndexNodes(index, &index_low, &index_high);
213 Node* value = node->InputAt(2);
214 DCHECK(HasReplacementLow(value));
215 DCHECK(HasReplacementHigh(value));
218 if (node->InputCount() > 3) {
219 Node* effect_high = node->InputAt(3);
220 Node* control_high = node->InputAt(4);
221 high_node =
graph()->NewNode(store_op,
base, index_high,
222 GetReplacementHigh(value), effect_high,
224 node->ReplaceInput(3, high_node);
227 high_node =
graph()->NewNode(store_op,
base, index_high,
228 GetReplacementHigh(value));
231 node->ReplaceInput(1, index_low);
232 node->ReplaceInput(2, GetReplacementLow(value));
233 NodeProperties::ChangeOp(node, store_op);
234 ReplaceNode(node, node, high_node);
236 DefaultLowering(node,
true);
240void Int64Lowering::LowerNode(Node* node) {
241 switch (node->opcode()) {
242 case IrOpcode::kInt64Constant: {
243 int64_t value = OpParameter<int64_t>(node->op());
244 Node* low_node =
graph()->NewNode(
245 common()->Int32Constant(
static_cast<int32_t>(value & 0xFFFFFFFF)));
246 Node* high_node =
graph()->NewNode(
247 common()->Int32Constant(
static_cast<int32_t>(value >> 32)));
248 ReplaceNode(node, low_node, high_node);
251 case IrOpcode::kLoad: {
254 LowerLoadOperator(node, rep, machine()->
Load(MachineType::Int32()));
257 case IrOpcode::kUnalignedLoad: {
260 LowerLoadOperator(node, rep,
261 machine()->UnalignedLoad(MachineType::Int32()));
264 case IrOpcode::kLoadImmutable: {
267 LowerLoadOperator(node, rep,
268 machine()->LoadImmutable(MachineType::Int32()));
271 case IrOpcode::kLoadFromObject: {
273 LowerLoadOperator(node, access.machine_type.representation(),
274 simplified()->LoadFromObject(ObjectAccess(
275 MachineType::Int32(), access.write_barrier_kind)));
278 case IrOpcode::kLoadImmutableFromObject: {
280 LowerLoadOperator(node, access.machine_type.representation(),
281 simplified()->LoadImmutableFromObject(ObjectAccess(
282 MachineType::Int32(), access.write_barrier_kind)));
285 case IrOpcode::kStore: {
288 node, store_rep.representation(),
289 machine()->
Store(StoreRepresentation(
290 MachineRepresentation::kWord32, store_rep.write_barrier_kind())));
293 case IrOpcode::kUnalignedStore: {
298 machine()->UnalignedStore(MachineRepresentation::kWord32));
301 case IrOpcode::kStoreToObject: {
303 LowerStoreOperator(node, access.machine_type.representation(),
304 simplified()->StoreToObject(ObjectAccess(
305 MachineType::Int32(), access.write_barrier_kind)));
308 case IrOpcode::kInitializeImmutableInObject: {
310 LowerStoreOperator(node, access.machine_type.representation(),
311 simplified()->InitializeImmutableInObject(ObjectAccess(
312 MachineType::Int32(), access.write_barrier_kind)));
315 case IrOpcode::kStart: {
321 int new_output_count = node->op()->ValueOutputCount() + delta;
322 NodeProperties::ChangeOp(node, common()->Start(new_output_count));
326 case IrOpcode::kParameter: {
328 int param_count =
static_cast<int>(signature()->parameter_count());
333 if (GetParameterCountAfterLowering(signature()) != param_count) {
337 int new_index = GetParameterIndexAfterLowering(signature(), old_index);
340 NodeProperties::ChangeOp(node, common()->Parameter(new_index));
342 if (old_index < 0 || old_index >= param_count) {
348 if (signature()->GetParam(old_index) ==
349 MachineRepresentation::kWord64) {
350 Node* high_node =
graph()->NewNode(common()->Parameter(new_index + 1),
352 ReplaceNode(node, node, high_node);
357 case IrOpcode::kReturn: {
359 DefaultLowering(node);
360 if (input_count != node->InputCount()) {
361 int new_return_count = GetReturnCountAfterLowering(signature());
362 if (
static_cast<int>(signature()->return_count()) != new_return_count) {
363 NodeProperties::ChangeOp(node, common()->Return(new_return_count));
368 case IrOpcode::kTailCall: {
369 auto call_descriptor =
371 bool returns_require_lowering =
372 GetReturnCountAfterLowering(call_descriptor) !=
373 static_cast<int>(call_descriptor->ReturnCount());
374 if (DefaultLowering(node) || returns_require_lowering) {
377 NodeProperties::ChangeOp(
378 node, common()->TailCall(LowerCallDescriptor(call_descriptor)));
382 case IrOpcode::kCall: {
385 bool returns_require_lowering =
386 GetReturnCountAfterLowering(call_descriptor) !=
387 static_cast<int>(call_descriptor->ReturnCount());
388 if (DefaultLowering(node) || returns_require_lowering) {
390 NodeProperties::ChangeOp(
391 node, common()->Call(LowerCallDescriptor(call_descriptor)));
393 if (returns_require_lowering) {
394 size_t return_arity = call_descriptor->ReturnCount();
395 if (return_arity == 1) {
397 ReplaceNodeWithProjections(node);
399 ZoneVector<Node*> projections(return_arity, zone());
400 NodeProperties::CollectValueProjections(node, projections.data(),
402 for (
size_t old_index = 0, new_index = 0; old_index < return_arity;
403 ++old_index, ++new_index) {
404 Node* use_node = projections[old_index];
406 DCHECK_EQ(GetReturnIndexAfterLowering(call_descriptor,
407 static_cast<int>(old_index)),
408 static_cast<int>(new_index));
409 if (new_index != old_index) {
410 NodeProperties::ChangeOp(
411 use_node, common()->Projection(new_index));
413 if (call_descriptor->GetReturnType(old_index).representation() ==
414 MachineRepresentation::kWord64) {
415 Node* high_node =
graph()->NewNode(
416 common()->Projection(new_index + 1), node,
graph()->
start());
417 ReplaceNode(use_node, use_node, high_node);
425 case IrOpcode::kWord64And: {
427 Node* left = node->InputAt(0);
428 Node* right = node->InputAt(1);
431 graph()->NewNode(machine()->Word32And(), GetReplacementLow(left),
432 GetReplacementLow(right));
434 graph()->NewNode(machine()->Word32And(), GetReplacementHigh(left),
435 GetReplacementHigh(right));
436 ReplaceNode(node, low_node, high_node);
439 case IrOpcode::kTruncateInt64ToInt32: {
441 Node* input = node->InputAt(0);
442 ReplaceNode(node, GetReplacementLow(input),
nullptr);
443 node->NullAllInputs();
446 case IrOpcode::kInt64Add: {
449 Node* right = node->InputAt(1);
450 node->ReplaceInput(1, GetReplacementLow(right));
451 node->AppendInput(zone(), GetReplacementHigh(right));
453 Node* left = node->InputAt(0);
454 node->ReplaceInput(0, GetReplacementLow(left));
455 node->InsertInput(zone(), 1, GetReplacementHigh(left));
457 NodeProperties::ChangeOp(node, machine()->Int32PairAdd());
459 ReplaceNodeWithProjections(node);
462 case IrOpcode::kInt64Sub: {
465 Node* right = node->InputAt(1);
466 node->ReplaceInput(1, GetReplacementLow(right));
467 node->AppendInput(zone(), GetReplacementHigh(right));
469 Node* left = node->InputAt(0);
470 node->ReplaceInput(0, GetReplacementLow(left));
471 node->InsertInput(zone(), 1, GetReplacementHigh(left));
473 NodeProperties::ChangeOp(node, machine()->Int32PairSub());
475 ReplaceNodeWithProjections(node);
478 case IrOpcode::kInt64Mul: {
481 Node* right = node->InputAt(1);
482 node->ReplaceInput(1, GetReplacementLow(right));
483 node->AppendInput(zone(), GetReplacementHigh(right));
485 Node* left = node->InputAt(0);
486 node->ReplaceInput(0, GetReplacementLow(left));
487 node->InsertInput(zone(), 1, GetReplacementHigh(left));
489 NodeProperties::ChangeOp(node, machine()->Int32PairMul());
491 ReplaceNodeWithProjections(node);
494 case IrOpcode::kWord64Or: {
496 Node* left = node->InputAt(0);
497 Node* right = node->InputAt(1);
500 graph()->NewNode(machine()->Word32Or(), GetReplacementLow(left),
501 GetReplacementLow(right));
503 graph()->NewNode(machine()->Word32Or(), GetReplacementHigh(left),
504 GetReplacementHigh(right));
505 ReplaceNode(node, low_node, high_node);
508 case IrOpcode::kWord64Xor: {
510 Node* left = node->InputAt(0);
511 Node* right = node->InputAt(1);
514 graph()->NewNode(machine()->Word32Xor(), GetReplacementLow(left),
515 GetReplacementLow(right));
517 graph()->NewNode(machine()->Word32Xor(), GetReplacementHigh(left),
518 GetReplacementHigh(right));
519 ReplaceNode(node, low_node, high_node);
522 case IrOpcode::kWord64Shl: {
526 Node* shift = node->InputAt(1);
527 if (HasReplacementLow(shift)) {
530 node->ReplaceInput(1, GetReplacementLow(shift));
533 Node* value = node->InputAt(0);
534 node->ReplaceInput(0, GetReplacementLow(value));
535 node->InsertInput(zone(), 1, GetReplacementHigh(value));
537 NodeProperties::ChangeOp(node, machine()->Word32PairShl());
539 ReplaceNodeWithProjections(node);
542 case IrOpcode::kWord64Shr: {
546 Node* shift = node->InputAt(1);
547 if (HasReplacementLow(shift)) {
550 node->ReplaceInput(1, GetReplacementLow(shift));
553 Node* value = node->InputAt(0);
554 node->ReplaceInput(0, GetReplacementLow(value));
555 node->InsertInput(zone(), 1, GetReplacementHigh(value));
557 NodeProperties::ChangeOp(node, machine()->Word32PairShr());
559 ReplaceNodeWithProjections(node);
562 case IrOpcode::kWord64Sar: {
566 Node* shift = node->InputAt(1);
567 if (HasReplacementLow(shift)) {
570 node->ReplaceInput(1, GetReplacementLow(shift));
573 Node* value = node->InputAt(0);
574 node->ReplaceInput(0, GetReplacementLow(value));
575 node->InsertInput(zone(), 1, GetReplacementHigh(value));
577 NodeProperties::ChangeOp(node, machine()->Word32PairSar());
579 ReplaceNodeWithProjections(node);
582 case IrOpcode::kWord64Equal: {
584 Node* left = node->InputAt(0);
585 Node* right = node->InputAt(1);
588 Node* replacement =
graph()->NewNode(
591 machine()->Word32Or(),
592 graph()->NewNode(machine()->Word32Xor(), GetReplacementLow(left),
593 GetReplacementLow(right)),
594 graph()->NewNode(machine()->Word32Xor(), GetReplacementHigh(left),
595 GetReplacementHigh(right))),
596 graph()->NewNode(common()->Int32Constant(0)));
597 ReplaceNode(node, replacement,
nullptr);
600 case IrOpcode::kInt64LessThan: {
601 LowerComparison(node, machine()->Int32LessThan(),
602 machine()->Uint32LessThan());
605 case IrOpcode::kInt64LessThanOrEqual: {
606 LowerComparison(node, machine()->Int32LessThan(),
607 machine()->Uint32LessThanOrEqual());
610 case IrOpcode::kUint64LessThan: {
611 LowerComparison(node, machine()->Uint32LessThan(),
612 machine()->Uint32LessThan());
615 case IrOpcode::kUint64LessThanOrEqual: {
616 LowerComparison(node, machine()->Uint32LessThan(),
617 machine()->Uint32LessThanOrEqual());
620 case IrOpcode::kSignExtendWord32ToInt64:
621 case IrOpcode::kChangeInt32ToInt64: {
623 Node* input = node->InputAt(0);
624 if (HasReplacementLow(input)) {
625 input = GetReplacementLow(input);
629 graph()->NewNode(machine()->Word32Sar(), input,
630 graph()->NewNode(common()->Int32Constant(31)));
631 ReplaceNode(node, input, high_node);
632 node->NullAllInputs();
635 case IrOpcode::kChangeUint32ToUint64: {
637 Node* input = node->InputAt(0);
638 if (HasReplacementLow(input)) {
639 input = GetReplacementLow(input);
641 ReplaceNode(node, input,
graph()->NewNode(common()->Int32Constant(0)));
642 node->NullAllInputs();
645 case IrOpcode::kBitcastInt64ToFloat64: {
647 Node* input = node->InputAt(0);
650 graph()->NewNode(machine()->Float64InsertHighWord32(),
651 graph()->NewNode(common()->Float64Constant(0.0)),
652 GetReplacementHigh(input));
653 Node*
result =
graph()->NewNode(machine()->Float64InsertLowWord32(),
654 high_half, GetReplacementLow(input));
655 ReplaceNode(node,
result,
nullptr);
658 case IrOpcode::kBitcastFloat64ToInt64: {
660 Node* input = node->InputAt(0);
661 if (HasReplacementLow(input)) {
662 input = GetReplacementLow(input);
666 graph()->NewNode(machine()->Float64ExtractLowWord32(), input);
668 graph()->NewNode(machine()->Float64ExtractHighWord32(), input);
669 ReplaceNode(node, low_node, high_node);
672 case IrOpcode::kWord64RolLowerable:
673 DCHECK(machine()->Word32Rol().IsSupported());
675 case IrOpcode::kWord64RorLowerable: {
677 Node* input = node->InputAt(0);
678 Node* shift = HasReplacementLow(node->InputAt(1))
679 ? GetReplacementLow(node->InputAt(1))
682 if (
m.HasResolvedValue()) {
684 int32_t shift_value =
m.ResolvedValue() & 0x3F;
685 if (shift_value == 0) {
686 ReplaceNode(node, GetReplacementLow(input),
687 GetReplacementHigh(input));
688 }
else if (shift_value == 32) {
689 ReplaceNode(node, GetReplacementHigh(input),
690 GetReplacementLow(input));
694 if (shift_value < 32) {
695 low_input = GetReplacementLow(input);
696 high_input = GetReplacementHigh(input);
698 low_input = GetReplacementHigh(input);
699 high_input = GetReplacementLow(input);
701 int32_t masked_shift_value = shift_value & 0x1F;
703 graph()->NewNode(common()->Int32Constant(masked_shift_value));
704 Node* inv_shift =
graph()->NewNode(
705 common()->Int32Constant(32 - masked_shift_value));
707 auto* op1 = machine()->Word32Shr();
708 auto* op2 = machine()->Word32Shl();
709 bool is_ror = node->opcode() == IrOpcode::kWord64RorLowerable;
710 if (!is_ror) std::swap(op1, op2);
713 graph()->NewNode(machine()->Word32Or(),
714 graph()->NewNode(op1, low_input, masked_shift),
715 graph()->NewNode(op2, high_input, inv_shift));
717 graph()->NewNode(machine()->Word32Or(),
718 graph()->NewNode(op1, high_input, masked_shift),
719 graph()->NewNode(op2, low_input, inv_shift));
720 ReplaceNode(node, low_node, high_node);
723 Node* safe_shift = shift;
724 if (!machine()->Word32ShiftIsSafe()) {
726 graph()->NewNode(machine()->Word32And(), shift,
727 graph()->NewNode(common()->Int32Constant(0x1F)));
730 bool is_ror = node->opcode() == IrOpcode::kWord64RorLowerable;
732 is_ror ?
graph()->NewNode(
733 machine()->Word32Xor(),
735 machine()->Word32Shr(),
736 graph()->NewNode(common()->Int32Constant(-1)),
738 graph()->NewNode(common()->Int32Constant(-1)))
740 machine()->Word32Shl(),
741 graph()->NewNode(common()->Int32Constant(-1)),
745 graph()->NewNode(machine()->Word32Xor(), inv_mask,
746 graph()->NewNode(common()->Int32Constant(-1)));
751 Node* masked_shift6 = shift;
752 if (machine()->Word32ShiftIsSafe()) {
754 graph()->NewNode(machine()->Word32And(), shift,
755 graph()->NewNode(common()->Int32Constant(0x3F)));
760 graph()->NewNode(machine()->Int32LessThan(), masked_shift6,
761 graph()->NewNode(common()->Int32Constant(32))));
762 lt32.Chain(NodeProperties::GetControlInput(node));
768 lt32.Phi(MachineRepresentation::kWord32, GetReplacementLow(input),
769 GetReplacementHigh(input));
771 lt32.Phi(MachineRepresentation::kWord32, GetReplacementHigh(input),
772 GetReplacementLow(input));
774 const Operator* oper =
775 is_ror ? machine()->Word32Ror() : machine()->Word32Rol().op();
777 Node* rotate_low =
graph()->NewNode(oper, input_low, safe_shift);
778 Node* rotate_high =
graph()->NewNode(oper, input_high, safe_shift);
780 auto* mask1 = bit_mask;
781 auto* mask2 = inv_mask;
782 if (!is_ror) std::swap(mask1, mask2);
784 Node* low_node =
graph()->NewNode(
785 machine()->Word32Or(),
786 graph()->NewNode(machine()->Word32And(), rotate_low, mask1),
787 graph()->NewNode(machine()->Word32And(), rotate_high, mask2));
788 Node* high_node =
graph()->NewNode(
789 machine()->Word32Or(),
790 graph()->NewNode(machine()->Word32And(), rotate_high, mask1),
791 graph()->NewNode(machine()->Word32And(), rotate_low, mask2));
792 ReplaceNode(node, low_node, high_node);
796 case IrOpcode::kWord64ClzLowerable: {
798 Node* input = node->InputAt(0);
802 graph()->NewNode(common()->Int32Constant(0))));
803 d.Chain(NodeProperties::GetControlInput(node));
805 Node* low_node = d.Phi(
806 MachineRepresentation::kWord32,
807 graph()->NewNode(machine()->Int32Add(),
808 graph()->NewNode(machine()->Word32Clz(),
809 GetReplacementLow(input)),
810 graph()->NewNode(common()->Int32Constant(32))),
811 graph()->NewNode(machine()->Word32Clz(), GetReplacementHigh(input)));
812 ReplaceNode(node, low_node,
graph()->NewNode(common()->Int32Constant(0)));
815 case IrOpcode::kWord64CtzLowerable: {
817 DCHECK(machine()->Word32Ctz().IsSupported());
818 Node* input = node->InputAt(0);
822 graph()->NewNode(common()->Int32Constant(0))));
823 d.Chain(NodeProperties::GetControlInput(node));
826 d.Phi(MachineRepresentation::kWord32,
827 graph()->NewNode(machine()->Int32Add(),
828 graph()->NewNode(machine()->Word32Ctz().op(),
829 GetReplacementHigh(input)),
830 graph()->NewNode(common()->Int32Constant(32))),
831 graph()->NewNode(machine()->Word32Ctz().op(),
832 GetReplacementLow(input)));
833 ReplaceNode(node, low_node,
graph()->NewNode(common()->Int32Constant(0)));
836 case IrOpcode::kWord64Ror:
837 case IrOpcode::kWord64Rol:
838 case IrOpcode::kWord64Ctz:
839 case IrOpcode::kWord64Clz:
840 FATAL(
"%s operator should not be used in 32-bit systems",
841 node->op()->mnemonic());
842 case IrOpcode::kWord64Popcnt: {
844 Node* input = node->InputAt(0);
847 DCHECK(machine()->Word32Popcnt().IsSupported());
849 graph()->NewNode(machine()->Int32Add(),
850 graph()->NewNode(machine()->Word32Popcnt().op(),
851 GetReplacementLow(input)),
852 graph()->NewNode(machine()->Word32Popcnt().op(),
853 GetReplacementHigh(input)));
854 ReplaceNode(node, low_node,
graph()->NewNode(common()->Int32Constant(0)));
857 case IrOpcode::kPhi: {
859 if (rep == MachineRepresentation::kWord64) {
862 Node* low_node = GetReplacementLow(node);
863 Node* high_node = GetReplacementHigh(node);
864 for (
int i = 0;
i < node->op()->ValueInputCount();
i++) {
865 low_node->ReplaceInput(
i, GetReplacementLow(node->InputAt(
i)));
866 high_node->ReplaceInput(
i, GetReplacementHigh(node->InputAt(
i)));
869 DefaultLowering(node);
873 case IrOpcode::kLoopExitValue: {
875 if (rep == MachineRepresentation::kWord64) {
876 Node* low_node =
graph()->NewNode(
877 common()->LoopExitValue(MachineRepresentation::kWord32),
878 GetReplacementLow(node->InputAt(0)), node->InputAt(1));
879 Node* high_node =
graph()->NewNode(
880 common()->LoopExitValue(MachineRepresentation::kWord32),
881 GetReplacementHigh(node->InputAt(0)), node->InputAt(1));
882 ReplaceNode(node, low_node, high_node);
884 DefaultLowering(node);
888 case IrOpcode::kWord64ReverseBytes: {
889 Node* input = node->InputAt(0);
890 Node* low_node =
graph()->NewNode(machine()->Word32ReverseBytes(),
891 GetReplacementHigh(input));
892 Node* high_node =
graph()->NewNode(machine()->Word32ReverseBytes(),
893 GetReplacementLow(input));
894 ReplaceNode(node, low_node, high_node);
897 case IrOpcode::kSignExtendWord8ToInt64: {
899 Node* input = node->InputAt(0);
900 if (HasReplacementLow(input)) {
901 input = GetReplacementLow(input);
905 graph()->NewNode(machine()->SignExtendWord8ToInt32(), input);
908 graph()->NewNode(machine()->Word32Sar(), low_node,
909 graph()->NewNode(common()->Int32Constant(31)));
910 ReplaceNode(node, low_node, high_node);
911 node->NullAllInputs();
914 case IrOpcode::kSignExtendWord16ToInt64: {
916 Node* input = node->InputAt(0);
917 if (HasReplacementLow(input)) {
918 input = GetReplacementLow(input);
922 graph()->NewNode(machine()->SignExtendWord16ToInt32(), input);
925 graph()->NewNode(machine()->Word32Sar(), low_node,
926 graph()->NewNode(common()->Int32Constant(31)));
927 ReplaceNode(node, low_node, high_node);
928 node->NullAllInputs();
931 case IrOpcode::kWord64AtomicLoad: {
934 DefaultLowering(node,
true);
935 if (params.representation() == MachineType::Uint64()) {
936 NodeProperties::ChangeOp(
937 node, machine()->Word32AtomicPairLoad(params.order()));
938 ReplaceNodeWithProjections(node);
940 NodeProperties::ChangeOp(node, machine()->Word32AtomicLoad(params));
941 ReplaceNode(node, node,
graph()->NewNode(common()->Int32Constant(0)));
945 case IrOpcode::kWord64AtomicStore: {
948 if (params.representation() == MachineRepresentation::kWord64) {
949 LowerMemoryBaseAndIndex(node);
950 Node* value = node->InputAt(2);
951 node->ReplaceInput(2, GetReplacementLow(value));
952 node->InsertInput(zone(), 3, GetReplacementHigh(value));
953 NodeProperties::ChangeOp(
954 node, machine()->Word32AtomicPairStore(params.order()));
956 DefaultLowering(node,
true);
957 NodeProperties::ChangeOp(node, machine()->Word32AtomicStore(params));
961#define ATOMIC_CASE(name) \
962 case IrOpcode::kWord64Atomic##name: { \
963 MachineType type = AtomicOpType(node->op()); \
964 if (type == MachineType::Uint64()) { \
965 LowerWord64AtomicBinop(node, machine()->Word32AtomicPair##name()); \
967 LowerWord64AtomicNarrowOp(node, machine()->Word32Atomic##name(type)); \
976 ATOMIC_CASE(Exchange)
978 case IrOpcode::kWord64AtomicCompareExchange: {
980 if (type == MachineType::Uint64()) {
981 LowerMemoryBaseAndIndex(node);
982 Node* old_value = node->InputAt(2);
983 Node* new_value = node->InputAt(3);
984 node->ReplaceInput(2, GetReplacementLow(old_value));
985 node->ReplaceInput(3, GetReplacementHigh(old_value));
986 node->InsertInput(zone(), 4, GetReplacementLow(new_value));
987 node->InsertInput(zone(), 5, GetReplacementHigh(new_value));
988 NodeProperties::ChangeOp(node,
989 machine()->Word32AtomicPairCompareExchange());
990 ReplaceNodeWithProjections(node);
992 DCHECK(type == MachineType::Uint32() || type == MachineType::Uint16() ||
993 type == MachineType::Uint8());
994 DefaultLowering(node,
true);
995 NodeProperties::ChangeOp(node,
996 machine()->Word32AtomicCompareExchange(type));
997 ReplaceNode(node, node,
graph()->NewNode(common()->Int32Constant(0)));
1001 case IrOpcode::kI64x2Splat: {
1003 Node* input = node->InputAt(0);
1004 node->ReplaceInput(0, GetReplacementLow(input));
1005 node->AppendInput(zone(), GetReplacementHigh(input));
1006 NodeProperties::ChangeOp(node, machine()->I64x2SplatI32Pair());
1009 case IrOpcode::kI64x2ExtractLane: {
1011 Node* input = node->InputAt(0);
1012 int32_t lane = OpParameter<int32_t>(node->op());
1014 graph()->NewNode(machine()->I32x4ExtractLane(lane * 2), input);
1016 graph()->NewNode(machine()->I32x4ExtractLane(lane * 2 + 1), input);
1017 ReplaceNode(node, low_node, high_node);
1020 case IrOpcode::kI64x2ReplaceLane: {
1022 int32_t lane = OpParameter<int32_t>(node->op());
1023 Node* input = node->InputAt(1);
1024 node->ReplaceInput(1, GetReplacementLow(input));
1025 node->AppendInput(zone(), GetReplacementHigh(input));
1026 NodeProperties::ChangeOp(node, machine()->I64x2ReplaceLaneI32Pair(lane));
1030 default: { DefaultLowering(node); }
1034void Int64Lowering::LowerComparison(Node* node,
const Operator* high_word_op,
1035 const Operator* low_word_op) {
1037 Node* left = node->InputAt(0);
1038 Node* right = node->InputAt(1);
1039 Node* replacement =
graph()->NewNode(
1040 machine()->Word32Or(),
1041 graph()->NewNode(high_word_op, GetReplacementHigh(left),
1042 GetReplacementHigh(right)),
1044 machine()->Word32And(),
1046 GetReplacementHigh(right)),
1047 graph()->NewNode(low_word_op, GetReplacementLow(left),
1048 GetReplacementLow(right))));
1049 ReplaceNode(node, replacement,
nullptr);
1052bool Int64Lowering::DefaultLowering(Node* node,
bool low_word_only) {
1053 bool something_changed =
false;
1054 for (
int i = NodeProperties::PastValueIndex(node) - 1;
i >= 0;
i--) {
1055 Node* input = node->InputAt(
i);
1056 if (HasReplacementLow(input)) {
1057 something_changed =
true;
1058 node->ReplaceInput(
i, GetReplacementLow(input));
1060 if (!low_word_only && HasReplacementHigh(input)) {
1061 something_changed =
true;
1062 node->InsertInput(zone(),
i + 1, GetReplacementHigh(input));
1065 return something_changed;
1068const CallDescriptor* Int64Lowering::LowerCallDescriptor(
1069 const CallDescriptor* call_descriptor) {
1070 CallDescriptor* maybe_special_replacement =
1071 wasm::GetWasmEngine()->call_descriptors()->GetLoweredCallDescriptor(
1073 if (maybe_special_replacement)
return maybe_special_replacement;
1074 return GetI32WasmCallDescriptor(zone(), call_descriptor);
1077void Int64Lowering::ReplaceNode(Node* old, Node* new_low, Node* new_high) {
1079 DCHECK(new_low !=
nullptr || new_high ==
nullptr);
1080 replacements_[old->id()].low = new_low;
1081 replacements_[old->id()].high = new_high;
1084bool Int64Lowering::HasReplacementLow(Node* node) {
1085 return replacements_[node->id()].low !=
nullptr;
1088Node* Int64Lowering::GetReplacementLow(Node* node) {
1089 Node*
result = replacements_[node->id()].low;
1094bool Int64Lowering::HasReplacementHigh(Node* node) {
1095 return replacements_[node->id()].high !=
nullptr;
1098Node* Int64Lowering::GetReplacementHigh(Node* node) {
1099 Node*
result = replacements_[node->id()].high;
1104void Int64Lowering::PreparePhiReplacement(Node* phi) {
1106 if (rep == MachineRepresentation::kWord64) {
1111 int value_count = phi->op()->ValueInputCount();
1112 Node** inputs_low = zone()->AllocateArray<Node*>(value_count + 1);
1113 Node** inputs_high = zone()->AllocateArray<Node*>(value_count + 1);
1114 for (
int i = 0;
i < value_count;
i++) {
1115 inputs_low[
i] = placeholder_;
1116 inputs_high[
i] = placeholder_;
1118 inputs_low[value_count] = NodeProperties::GetControlInput(phi, 0);
1119 inputs_high[value_count] = NodeProperties::GetControlInput(phi, 0);
1122 common()->Phi(MachineRepresentation::kWord32, value_count),
1123 value_count + 1, inputs_low,
false),
1125 common()->Phi(MachineRepresentation::kWord32, value_count),
1126 value_count + 1, inputs_high,
false));
1130void Int64Lowering::ReplaceNodeWithProjections(Node* node) {
1136 ReplaceNode(node, low_node, high_node);
1139void Int64Lowering::LowerMemoryBaseAndIndex(Node* node) {
1142 Node*
base = node->InputAt(0);
1143 Node* index = node->InputAt(1);
1144 if (HasReplacementLow(
base)) {
1145 node->ReplaceInput(0, GetReplacementLow(
base));
1147 if (HasReplacementLow(index)) {
1148 node->ReplaceInput(1, GetReplacementLow(index));
constexpr MachineRepresentation representation() const
Int64Lowering(TFGraph *graph, MachineOperatorBuilder *machine, CommonOperatorBuilder *common, SimplifiedOperatorBuilder *simplified_, Zone *zone, Signature< MachineRepresentation > *signature)
enum v8::internal::@1270::DeoptimizableCodeIterator::@67 state_
ZoneVector< RpoNumber > & result
bool Word32Equal(uint32_t a, uint32_t b)
constexpr size_t input_count()
size_t ProjectionIndexOf(const Operator *const op)
AtomicStoreParameters const & AtomicStoreParametersOf(Operator const *op)
StoreRepresentation const & StoreRepresentationOf(Operator const *op)
CallDescriptor const * CallDescriptorOf(const Operator *const op)
AtomicLoadParameters AtomicLoadParametersOf(Operator const *op)
int ParameterIndexOf(const Operator *const op)
const ObjectAccess & ObjectAccessOf(const Operator *op)
MachineType AtomicOpType(InstructionSelectorT *selector, OpIndex node)
IntMatcher< int32_t, IrOpcode::kInt32Constant > Int32Matcher
LoadRepresentation LoadRepresentationOf(Operator const *op)
MachineRepresentation UnalignedStoreRepresentation
UnalignedStoreRepresentation const & UnalignedStoreRepresentationOf(Operator const *op)
MachineRepresentation LoopExitValueRepresentationOf(const Operator *const op)
MachineRepresentation PhiRepresentationOf(const Operator *const op)
void Store(LiftoffAssembler *assm, LiftoffRegister src, MemOperand dst, ValueKind kind)
i::Address Load(i::Address address)
#define DCHECK_NOT_NULL(val)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)