1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/int64-lowering.h"
6
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"
16 // TODO(wasm): Remove this include.
17 #include "src/wasm/wasm-linkage.h"
18 #include "src/zone/zone.h"
19
20 namespace v8 {
21 namespace internal {
22 namespace compiler {
23
Int64Lowering(Graph * graph,MachineOperatorBuilder * machine,CommonOperatorBuilder * common,SimplifiedOperatorBuilder * simplified,Zone * zone,Signature<MachineRepresentation> * signature,std::unique_ptr<Int64LoweringSpecialCase> special_case)24 Int64Lowering::Int64Lowering(
25 Graph* graph, MachineOperatorBuilder* machine,
26 CommonOperatorBuilder* common, SimplifiedOperatorBuilder* simplified,
27 Zone* zone, Signature<MachineRepresentation>* signature,
28 std::unique_ptr<Int64LoweringSpecialCase> special_case)
29 : zone_(zone),
30 graph_(graph),
31 machine_(machine),
32 common_(common),
33 simplified_(simplified),
34 state_(graph->NodeCount(), State::kUnvisited),
35 stack_(zone),
36 replacements_(nullptr),
37 signature_(signature),
38 placeholder_(graph->NewNode(common->Dead())),
39 special_case_(std::move(special_case)) {
40 DCHECK_NOT_NULL(graph);
41 DCHECK_NOT_NULL(graph->end());
42 replacements_ = zone->NewArray<Replacement>(graph->NodeCount());
43 memset(replacements_, 0, sizeof(Replacement) * graph->NodeCount());
44 }
45
LowerGraph()46 void Int64Lowering::LowerGraph() {
47 if (!machine()->Is32()) {
48 return;
49 }
50 stack_.push_back({graph()->end(), 0});
51 state_[graph()->end()->id()] = State::kOnStack;
52
53 while (!stack_.empty()) {
54 NodeState& top = stack_.back();
55 if (top.input_index == top.node->InputCount()) {
56 // All inputs of top have already been lowered, now lower top.
57 stack_.pop_back();
58 state_[top.node->id()] = State::kVisited;
59 LowerNode(top.node);
60 } else {
61 // Push the next input onto the stack.
62 Node* input = top.node->InputAt(top.input_index++);
63 if (state_[input->id()] == State::kUnvisited) {
64 if (input->opcode() == IrOpcode::kPhi) {
65 // To break cycles with phi nodes we push phis on a separate stack so
66 // that they are processed after all other nodes.
67 PreparePhiReplacement(input);
68 stack_.push_front({input, 0});
69 } else if (input->opcode() == IrOpcode::kEffectPhi ||
70 input->opcode() == IrOpcode::kLoop) {
71 stack_.push_front({input, 0});
72 } else {
73 stack_.push_back({input, 0});
74 }
75 state_[input->id()] = State::kOnStack;
76 }
77 }
78 }
79 }
80
81 namespace {
82
GetReturnIndexAfterLowering(const CallDescriptor * call_descriptor,int old_index)83 int GetReturnIndexAfterLowering(const CallDescriptor* call_descriptor,
84 int old_index) {
85 int result = old_index;
86 for (int i = 0; i < old_index; i++) {
87 if (call_descriptor->GetReturnType(i).representation() ==
88 MachineRepresentation::kWord64) {
89 result++;
90 }
91 }
92 return result;
93 }
94
GetReturnCountAfterLowering(const CallDescriptor * call_descriptor)95 int GetReturnCountAfterLowering(const CallDescriptor* call_descriptor) {
96 return GetReturnIndexAfterLowering(
97 call_descriptor, static_cast<int>(call_descriptor->ReturnCount()));
98 }
99
GetParameterIndexAfterLowering(Signature<MachineRepresentation> * signature,int old_index)100 int GetParameterIndexAfterLowering(
101 Signature<MachineRepresentation>* signature, int old_index) {
102 int result = old_index;
103 // Be robust towards special indexes (>= param count).
104 int max_to_check =
105 std::min(old_index, static_cast<int>(signature->parameter_count()));
106 for (int i = 0; i < max_to_check; i++) {
107 if (signature->GetParam(i) == MachineRepresentation::kWord64) {
108 result++;
109 }
110 }
111 return result;
112 }
113
GetReturnCountAfterLowering(Signature<MachineRepresentation> * signature)114 int GetReturnCountAfterLowering(Signature<MachineRepresentation>* signature) {
115 int result = static_cast<int>(signature->return_count());
116 for (int i = 0; i < static_cast<int>(signature->return_count()); i++) {
117 if (signature->GetReturn(i) == MachineRepresentation::kWord64) {
118 result++;
119 }
120 }
121 return result;
122 }
123
124 } // namespace
125
LowerWord64AtomicBinop(Node * node,const Operator * op)126 void Int64Lowering::LowerWord64AtomicBinop(Node* node, const Operator* op) {
127 DCHECK_EQ(5, node->InputCount());
128 LowerMemoryBaseAndIndex(node);
129 Node* value = node->InputAt(2);
130 node->ReplaceInput(2, GetReplacementLow(value));
131 node->InsertInput(zone(), 3, GetReplacementHigh(value));
132 NodeProperties::ChangeOp(node, op);
133 ReplaceNodeWithProjections(node);
134 }
135
LowerWord64AtomicNarrowOp(Node * node,const Operator * op)136 void Int64Lowering::LowerWord64AtomicNarrowOp(Node* node, const Operator* op) {
137 DefaultLowering(node, true);
138 NodeProperties::ChangeOp(node, op);
139 ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
140 }
141
142 // static
GetParameterCountAfterLowering(Signature<MachineRepresentation> * signature)143 int Int64Lowering::GetParameterCountAfterLowering(
144 Signature<MachineRepresentation>* signature) {
145 // GetParameterIndexAfterLowering(parameter_count) returns the parameter count
146 // after lowering.
147 return GetParameterIndexAfterLowering(
148 signature, static_cast<int>(signature->parameter_count()));
149 }
150
GetIndexNodes(Node * index,Node ** index_low,Node ** index_high)151 void Int64Lowering::GetIndexNodes(Node* index, Node** index_low,
152 Node** index_high) {
153 #if defined(V8_TARGET_LITTLE_ENDIAN)
154 *index_low = index;
155 *index_high = graph()->NewNode(machine()->Int32Add(), index,
156 graph()->NewNode(common()->Int32Constant(4)));
157 #elif defined(V8_TARGET_BIG_ENDIAN)
158 *index_low = graph()->NewNode(machine()->Int32Add(), index,
159 graph()->NewNode(common()->Int32Constant(4)));
160 *index_high = index;
161 #endif
162 }
163
LowerLoadOperator(Node * node,MachineRepresentation rep,const Operator * load_op)164 void Int64Lowering::LowerLoadOperator(Node* node, MachineRepresentation rep,
165 const Operator* load_op) {
166 if (rep == MachineRepresentation::kWord64) {
167 LowerMemoryBaseAndIndex(node);
168 Node* base = node->InputAt(0);
169 Node* index = node->InputAt(1);
170 Node* index_low;
171 Node* index_high;
172 GetIndexNodes(index, &index_low, &index_high);
173 Node* high_node;
174 if (node->InputCount() > 2) {
175 Node* effect_high = node->InputAt(2);
176 Node* control_high = node->InputAt(3);
177 high_node = graph()->NewNode(load_op, base, index_high, effect_high,
178 control_high);
179 // change the effect change from old_node --> old_effect to
180 // old_node --> high_node --> old_effect.
181 node->ReplaceInput(2, high_node);
182 } else {
183 high_node = graph()->NewNode(load_op, base, index_high);
184 }
185 node->ReplaceInput(1, index_low);
186 NodeProperties::ChangeOp(node, load_op);
187 ReplaceNode(node, node, high_node);
188 } else {
189 DefaultLowering(node);
190 }
191 }
192
LowerStoreOperator(Node * node,MachineRepresentation rep,const Operator * store_op)193 void Int64Lowering::LowerStoreOperator(Node* node, MachineRepresentation rep,
194 const Operator* store_op) {
195 if (rep == MachineRepresentation::kWord64) {
196 // We change the original store node to store the low word, and create
197 // a new store node to store the high word. The effect and control edges
198 // are copied from the original store to the new store node, the effect
199 // edge of the original store is redirected to the new store.
200 LowerMemoryBaseAndIndex(node);
201 Node* base = node->InputAt(0);
202 Node* index = node->InputAt(1);
203 Node* index_low;
204 Node* index_high;
205 GetIndexNodes(index, &index_low, &index_high);
206 Node* value = node->InputAt(2);
207 DCHECK(HasReplacementLow(value));
208 DCHECK(HasReplacementHigh(value));
209
210 Node* high_node;
211 if (node->InputCount() > 3) {
212 Node* effect_high = node->InputAt(3);
213 Node* control_high = node->InputAt(4);
214 high_node = graph()->NewNode(store_op, base, index_high,
215 GetReplacementHigh(value), effect_high,
216 control_high);
217 node->ReplaceInput(3, high_node);
218
219 } else {
220 high_node = graph()->NewNode(store_op, base, index_high,
221 GetReplacementHigh(value));
222 }
223
224 node->ReplaceInput(1, index_low);
225 node->ReplaceInput(2, GetReplacementLow(value));
226 NodeProperties::ChangeOp(node, store_op);
227 ReplaceNode(node, node, high_node);
228 } else {
229 DefaultLowering(node, true);
230 }
231 }
232
LowerNode(Node * node)233 void Int64Lowering::LowerNode(Node* node) {
234 switch (node->opcode()) {
235 case IrOpcode::kInt64Constant: {
236 int64_t value = OpParameter<int64_t>(node->op());
237 Node* low_node = graph()->NewNode(
238 common()->Int32Constant(static_cast<int32_t>(value & 0xFFFFFFFF)));
239 Node* high_node = graph()->NewNode(
240 common()->Int32Constant(static_cast<int32_t>(value >> 32)));
241 ReplaceNode(node, low_node, high_node);
242 break;
243 }
244 case IrOpcode::kLoad: {
245 MachineRepresentation rep =
246 LoadRepresentationOf(node->op()).representation();
247 LowerLoadOperator(node, rep, machine()->Load(MachineType::Int32()));
248 break;
249 }
250 case IrOpcode::kUnalignedLoad: {
251 MachineRepresentation rep =
252 LoadRepresentationOf(node->op()).representation();
253 LowerLoadOperator(node, rep,
254 machine()->UnalignedLoad(MachineType::Int32()));
255 break;
256 }
257 case IrOpcode::kLoadImmutable: {
258 MachineRepresentation rep =
259 LoadRepresentationOf(node->op()).representation();
260 LowerLoadOperator(node, rep,
261 machine()->LoadImmutable(MachineType::Int32()));
262 break;
263 }
264 case IrOpcode::kLoadFromObject: {
265 ObjectAccess access = ObjectAccessOf(node->op());
266 LowerLoadOperator(node, access.machine_type.representation(),
267 simplified()->LoadFromObject(ObjectAccess(
268 MachineType::Int32(), access.write_barrier_kind)));
269 break;
270 }
271 case IrOpcode::kLoadImmutableFromObject: {
272 ObjectAccess access = ObjectAccessOf(node->op());
273 LowerLoadOperator(node, access.machine_type.representation(),
274 simplified()->LoadImmutableFromObject(ObjectAccess(
275 MachineType::Int32(), access.write_barrier_kind)));
276 break;
277 }
278 case IrOpcode::kStore: {
279 StoreRepresentation store_rep = StoreRepresentationOf(node->op());
280 LowerStoreOperator(
281 node, store_rep.representation(),
282 machine()->Store(StoreRepresentation(
283 MachineRepresentation::kWord32, store_rep.write_barrier_kind())));
284 break;
285 }
286 case IrOpcode::kUnalignedStore: {
287 UnalignedStoreRepresentation store_rep =
288 UnalignedStoreRepresentationOf(node->op());
289 LowerStoreOperator(
290 node, store_rep,
291 machine()->UnalignedStore(MachineRepresentation::kWord32));
292 break;
293 }
294 case IrOpcode::kStoreToObject: {
295 ObjectAccess access = ObjectAccessOf(node->op());
296 LowerStoreOperator(node, access.machine_type.representation(),
297 simplified()->StoreToObject(ObjectAccess(
298 MachineType::Int32(), access.write_barrier_kind)));
299 break;
300 }
301 case IrOpcode::kInitializeImmutableInObject: {
302 ObjectAccess access = ObjectAccessOf(node->op());
303 LowerStoreOperator(node, access.machine_type.representation(),
304 simplified()->InitializeImmutableInObject(ObjectAccess(
305 MachineType::Int32(), access.write_barrier_kind)));
306 break;
307 }
308 case IrOpcode::kStart: {
309 int parameter_count = GetParameterCountAfterLowering(signature());
310 // Only exchange the node if the parameter count actually changed.
311 if (parameter_count != static_cast<int>(signature()->parameter_count())) {
312 int delta =
313 parameter_count - static_cast<int>(signature()->parameter_count());
314 int new_output_count = node->op()->ValueOutputCount() + delta;
315 NodeProperties::ChangeOp(node, common()->Start(new_output_count));
316 }
317 break;
318 }
319 case IrOpcode::kParameter: {
320 DCHECK_EQ(1, node->InputCount());
321 int param_count = static_cast<int>(signature()->parameter_count());
322 // Only exchange the node if the parameter count actually changed. We do
323 // not even have to do the default lowering because the the start node,
324 // the only input of a parameter node, only changes if the parameter count
325 // changes.
326 if (GetParameterCountAfterLowering(signature()) != param_count) {
327 int old_index = ParameterIndexOf(node->op());
328 // Adjust old_index to be compliant with the signature.
329 --old_index;
330 int new_index = GetParameterIndexAfterLowering(signature(), old_index);
331 // Adjust new_index to consider the instance parameter.
332 ++new_index;
333 NodeProperties::ChangeOp(node, common()->Parameter(new_index));
334
335 if (old_index < 0 || old_index >= param_count) {
336 // Special parameters (JS closure/context) don't have kWord64
337 // representation anyway.
338 break;
339 }
340
341 if (signature()->GetParam(old_index) ==
342 MachineRepresentation::kWord64) {
343 Node* high_node = graph()->NewNode(common()->Parameter(new_index + 1),
344 graph()->start());
345 ReplaceNode(node, node, high_node);
346 }
347 }
348 break;
349 }
350 case IrOpcode::kReturn: {
351 int input_count = node->InputCount();
352 DefaultLowering(node);
353 if (input_count != node->InputCount()) {
354 int new_return_count = GetReturnCountAfterLowering(signature());
355 if (static_cast<int>(signature()->return_count()) != new_return_count) {
356 NodeProperties::ChangeOp(node, common()->Return(new_return_count));
357 }
358 }
359 break;
360 }
361 case IrOpcode::kTailCall: {
362 auto call_descriptor =
363 const_cast<CallDescriptor*>(CallDescriptorOf(node->op()));
364 bool returns_require_lowering =
365 GetReturnCountAfterLowering(call_descriptor) !=
366 static_cast<int>(call_descriptor->ReturnCount());
367 if (DefaultLowering(node) || returns_require_lowering) {
368 // Tail calls do not have return values, so adjusting the call
369 // descriptor is enough.
370 NodeProperties::ChangeOp(
371 node, common()->TailCall(LowerCallDescriptor(call_descriptor)));
372 }
373 break;
374 }
375 case IrOpcode::kCall: {
376 auto call_descriptor = CallDescriptorOf(node->op());
377
378 bool returns_require_lowering =
379 GetReturnCountAfterLowering(call_descriptor) !=
380 static_cast<int>(call_descriptor->ReturnCount());
381 if (DefaultLowering(node) || returns_require_lowering) {
382 // We have to adjust the call descriptor.
383 NodeProperties::ChangeOp(
384 node, common()->Call(LowerCallDescriptor(call_descriptor)));
385 }
386 if (returns_require_lowering) {
387 size_t return_arity = call_descriptor->ReturnCount();
388 if (return_arity == 1) {
389 // We access the additional return values through projections.
390 ReplaceNodeWithProjections(node);
391 } else {
392 ZoneVector<Node*> projections(return_arity, zone());
393 NodeProperties::CollectValueProjections(node, projections.data(),
394 return_arity);
395 for (size_t old_index = 0, new_index = 0; old_index < return_arity;
396 ++old_index, ++new_index) {
397 Node* use_node = projections[old_index];
398 DCHECK_EQ(ProjectionIndexOf(use_node->op()), old_index);
399 DCHECK_EQ(GetReturnIndexAfterLowering(call_descriptor,
400 static_cast<int>(old_index)),
401 static_cast<int>(new_index));
402 if (new_index != old_index) {
403 NodeProperties::ChangeOp(
404 use_node, common()->Projection(new_index));
405 }
406 if (call_descriptor->GetReturnType(old_index).representation() ==
407 MachineRepresentation::kWord64) {
408 Node* high_node = graph()->NewNode(
409 common()->Projection(new_index + 1), node, graph()->start());
410 ReplaceNode(use_node, use_node, high_node);
411 ++new_index;
412 }
413 }
414 }
415 }
416 break;
417 }
418 case IrOpcode::kWord64And: {
419 DCHECK_EQ(2, node->InputCount());
420 Node* left = node->InputAt(0);
421 Node* right = node->InputAt(1);
422
423 Node* low_node =
424 graph()->NewNode(machine()->Word32And(), GetReplacementLow(left),
425 GetReplacementLow(right));
426 Node* high_node =
427 graph()->NewNode(machine()->Word32And(), GetReplacementHigh(left),
428 GetReplacementHigh(right));
429 ReplaceNode(node, low_node, high_node);
430 break;
431 }
432 case IrOpcode::kTruncateInt64ToInt32: {
433 DCHECK_EQ(1, node->InputCount());
434 Node* input = node->InputAt(0);
435 ReplaceNode(node, GetReplacementLow(input), nullptr);
436 node->NullAllInputs();
437 break;
438 }
439 case IrOpcode::kInt64Add: {
440 DCHECK_EQ(2, node->InputCount());
441
442 Node* right = node->InputAt(1);
443 node->ReplaceInput(1, GetReplacementLow(right));
444 node->AppendInput(zone(), GetReplacementHigh(right));
445
446 Node* left = node->InputAt(0);
447 node->ReplaceInput(0, GetReplacementLow(left));
448 node->InsertInput(zone(), 1, GetReplacementHigh(left));
449
450 NodeProperties::ChangeOp(node, machine()->Int32PairAdd());
451 // We access the additional return values through projections.
452 ReplaceNodeWithProjections(node);
453 break;
454 }
455 case IrOpcode::kInt64Sub: {
456 DCHECK_EQ(2, node->InputCount());
457
458 Node* right = node->InputAt(1);
459 node->ReplaceInput(1, GetReplacementLow(right));
460 node->AppendInput(zone(), GetReplacementHigh(right));
461
462 Node* left = node->InputAt(0);
463 node->ReplaceInput(0, GetReplacementLow(left));
464 node->InsertInput(zone(), 1, GetReplacementHigh(left));
465
466 NodeProperties::ChangeOp(node, machine()->Int32PairSub());
467 // We access the additional return values through projections.
468 ReplaceNodeWithProjections(node);
469 break;
470 }
471 case IrOpcode::kInt64Mul: {
472 DCHECK_EQ(2, node->InputCount());
473
474 Node* right = node->InputAt(1);
475 node->ReplaceInput(1, GetReplacementLow(right));
476 node->AppendInput(zone(), GetReplacementHigh(right));
477
478 Node* left = node->InputAt(0);
479 node->ReplaceInput(0, GetReplacementLow(left));
480 node->InsertInput(zone(), 1, GetReplacementHigh(left));
481
482 NodeProperties::ChangeOp(node, machine()->Int32PairMul());
483 // We access the additional return values through projections.
484 ReplaceNodeWithProjections(node);
485 break;
486 }
487 case IrOpcode::kWord64Or: {
488 DCHECK_EQ(2, node->InputCount());
489 Node* left = node->InputAt(0);
490 Node* right = node->InputAt(1);
491
492 Node* low_node =
493 graph()->NewNode(machine()->Word32Or(), GetReplacementLow(left),
494 GetReplacementLow(right));
495 Node* high_node =
496 graph()->NewNode(machine()->Word32Or(), GetReplacementHigh(left),
497 GetReplacementHigh(right));
498 ReplaceNode(node, low_node, high_node);
499 break;
500 }
501 case IrOpcode::kWord64Xor: {
502 DCHECK_EQ(2, node->InputCount());
503 Node* left = node->InputAt(0);
504 Node* right = node->InputAt(1);
505
506 Node* low_node =
507 graph()->NewNode(machine()->Word32Xor(), GetReplacementLow(left),
508 GetReplacementLow(right));
509 Node* high_node =
510 graph()->NewNode(machine()->Word32Xor(), GetReplacementHigh(left),
511 GetReplacementHigh(right));
512 ReplaceNode(node, low_node, high_node);
513 break;
514 }
515 case IrOpcode::kWord64Shl: {
516 // TODO(turbofan): if the shift count >= 32, then we can set the low word
517 // of the output to 0 and just calculate the high word.
518 DCHECK_EQ(2, node->InputCount());
519 Node* shift = node->InputAt(1);
520 if (HasReplacementLow(shift)) {
521 // We do not have to care about the high word replacement, because
522 // the shift can only be between 0 and 63 anyways.
523 node->ReplaceInput(1, GetReplacementLow(shift));
524 }
525
526 Node* value = node->InputAt(0);
527 node->ReplaceInput(0, GetReplacementLow(value));
528 node->InsertInput(zone(), 1, GetReplacementHigh(value));
529
530 NodeProperties::ChangeOp(node, machine()->Word32PairShl());
531 // We access the additional return values through projections.
532 ReplaceNodeWithProjections(node);
533 break;
534 }
535 case IrOpcode::kWord64Shr: {
536 // TODO(turbofan): if the shift count >= 32, then we can set the low word
537 // of the output to 0 and just calculate the high word.
538 DCHECK_EQ(2, node->InputCount());
539 Node* shift = node->InputAt(1);
540 if (HasReplacementLow(shift)) {
541 // We do not have to care about the high word replacement, because
542 // the shift can only be between 0 and 63 anyways.
543 node->ReplaceInput(1, GetReplacementLow(shift));
544 }
545
546 Node* value = node->InputAt(0);
547 node->ReplaceInput(0, GetReplacementLow(value));
548 node->InsertInput(zone(), 1, GetReplacementHigh(value));
549
550 NodeProperties::ChangeOp(node, machine()->Word32PairShr());
551 // We access the additional return values through projections.
552 ReplaceNodeWithProjections(node);
553 break;
554 }
555 case IrOpcode::kWord64Sar: {
556 // TODO(turbofan): if the shift count >= 32, then we can set the low word
557 // of the output to 0 and just calculate the high word.
558 DCHECK_EQ(2, node->InputCount());
559 Node* shift = node->InputAt(1);
560 if (HasReplacementLow(shift)) {
561 // We do not have to care about the high word replacement, because
562 // the shift can only be between 0 and 63 anyways.
563 node->ReplaceInput(1, GetReplacementLow(shift));
564 }
565
566 Node* value = node->InputAt(0);
567 node->ReplaceInput(0, GetReplacementLow(value));
568 node->InsertInput(zone(), 1, GetReplacementHigh(value));
569
570 NodeProperties::ChangeOp(node, machine()->Word32PairSar());
571 // We access the additional return values through projections.
572 ReplaceNodeWithProjections(node);
573 break;
574 }
575 case IrOpcode::kWord64Equal: {
576 DCHECK_EQ(2, node->InputCount());
577 Node* left = node->InputAt(0);
578 Node* right = node->InputAt(1);
579
580 // TODO(wasm): Use explicit comparisons and && here?
581 Node* replacement = graph()->NewNode(
582 machine()->Word32Equal(),
583 graph()->NewNode(
584 machine()->Word32Or(),
585 graph()->NewNode(machine()->Word32Xor(), GetReplacementLow(left),
586 GetReplacementLow(right)),
587 graph()->NewNode(machine()->Word32Xor(), GetReplacementHigh(left),
588 GetReplacementHigh(right))),
589 graph()->NewNode(common()->Int32Constant(0)));
590
591 ReplaceNode(node, replacement, nullptr);
592 break;
593 }
594 case IrOpcode::kInt64LessThan: {
595 LowerComparison(node, machine()->Int32LessThan(),
596 machine()->Uint32LessThan());
597 break;
598 }
599 case IrOpcode::kInt64LessThanOrEqual: {
600 LowerComparison(node, machine()->Int32LessThan(),
601 machine()->Uint32LessThanOrEqual());
602 break;
603 }
604 case IrOpcode::kUint64LessThan: {
605 LowerComparison(node, machine()->Uint32LessThan(),
606 machine()->Uint32LessThan());
607 break;
608 }
609 case IrOpcode::kUint64LessThanOrEqual: {
610 LowerComparison(node, machine()->Uint32LessThan(),
611 machine()->Uint32LessThanOrEqual());
612 break;
613 }
614 case IrOpcode::kSignExtendWord32ToInt64:
615 case IrOpcode::kChangeInt32ToInt64: {
616 DCHECK_EQ(1, node->InputCount());
617 Node* input = node->InputAt(0);
618 if (HasReplacementLow(input)) {
619 input = GetReplacementLow(input);
620 }
621 // We use SAR to preserve the sign in the high word.
622 ReplaceNode(
623 node, input,
624 graph()->NewNode(machine()->Word32Sar(), input,
625 graph()->NewNode(common()->Int32Constant(31))));
626 node->NullAllInputs();
627 break;
628 }
629 case IrOpcode::kChangeUint32ToUint64: {
630 DCHECK_EQ(1, node->InputCount());
631 Node* input = node->InputAt(0);
632 if (HasReplacementLow(input)) {
633 input = GetReplacementLow(input);
634 }
635 ReplaceNode(node, input, graph()->NewNode(common()->Int32Constant(0)));
636 node->NullAllInputs();
637 break;
638 }
639 case IrOpcode::kBitcastInt64ToFloat64: {
640 DCHECK_EQ(1, node->InputCount());
641 Node* input = node->InputAt(0);
642 Node* stack_slot = graph()->NewNode(
643 machine()->StackSlot(MachineRepresentation::kWord64));
644
645 Node* store_high_word = graph()->NewNode(
646 machine()->Store(
647 StoreRepresentation(MachineRepresentation::kWord32,
648 WriteBarrierKind::kNoWriteBarrier)),
649 stack_slot,
650 graph()->NewNode(
651 common()->Int32Constant(kInt64UpperHalfMemoryOffset)),
652 GetReplacementHigh(input), graph()->start(), graph()->start());
653
654 Node* store_low_word = graph()->NewNode(
655 machine()->Store(
656 StoreRepresentation(MachineRepresentation::kWord32,
657 WriteBarrierKind::kNoWriteBarrier)),
658 stack_slot,
659 graph()->NewNode(
660 common()->Int32Constant(kInt64LowerHalfMemoryOffset)),
661 GetReplacementLow(input), store_high_word, graph()->start());
662
663 Node* load =
664 graph()->NewNode(machine()->Load(MachineType::Float64()), stack_slot,
665 graph()->NewNode(common()->Int32Constant(0)),
666 store_low_word, graph()->start());
667
668 ReplaceNode(node, load, nullptr);
669 break;
670 }
671 case IrOpcode::kBitcastFloat64ToInt64: {
672 DCHECK_EQ(1, node->InputCount());
673 Node* input = node->InputAt(0);
674 if (HasReplacementLow(input)) {
675 input = GetReplacementLow(input);
676 }
677 Node* stack_slot = graph()->NewNode(
678 machine()->StackSlot(MachineRepresentation::kWord64));
679 Node* store = graph()->NewNode(
680 machine()->Store(
681 StoreRepresentation(MachineRepresentation::kFloat64,
682 WriteBarrierKind::kNoWriteBarrier)),
683 stack_slot, graph()->NewNode(common()->Int32Constant(0)), input,
684 graph()->start(), graph()->start());
685
686 Node* high_node = graph()->NewNode(
687 machine()->Load(MachineType::Int32()), stack_slot,
688 graph()->NewNode(
689 common()->Int32Constant(kInt64UpperHalfMemoryOffset)),
690 store, graph()->start());
691
692 Node* low_node = graph()->NewNode(
693 machine()->Load(MachineType::Int32()), stack_slot,
694 graph()->NewNode(
695 common()->Int32Constant(kInt64LowerHalfMemoryOffset)),
696 store, graph()->start());
697 ReplaceNode(node, low_node, high_node);
698 break;
699 }
700 case IrOpcode::kWord64RolLowerable:
701 DCHECK(machine()->Word32Rol().IsSupported());
702 V8_FALLTHROUGH;
703 case IrOpcode::kWord64RorLowerable: {
704 DCHECK_EQ(3, node->InputCount());
705 Node* input = node->InputAt(0);
706 Node* shift = HasReplacementLow(node->InputAt(1))
707 ? GetReplacementLow(node->InputAt(1))
708 : node->InputAt(1);
709 Int32Matcher m(shift);
710 if (m.HasResolvedValue()) {
711 // Precondition: 0 <= shift < 64.
712 int32_t shift_value = m.ResolvedValue() & 0x3F;
713 if (shift_value == 0) {
714 ReplaceNode(node, GetReplacementLow(input),
715 GetReplacementHigh(input));
716 } else if (shift_value == 32) {
717 ReplaceNode(node, GetReplacementHigh(input),
718 GetReplacementLow(input));
719 } else {
720 Node* low_input;
721 Node* high_input;
722 if (shift_value < 32) {
723 low_input = GetReplacementLow(input);
724 high_input = GetReplacementHigh(input);
725 } else {
726 low_input = GetReplacementHigh(input);
727 high_input = GetReplacementLow(input);
728 }
729 int32_t masked_shift_value = shift_value & 0x1F;
730 Node* masked_shift =
731 graph()->NewNode(common()->Int32Constant(masked_shift_value));
732 Node* inv_shift = graph()->NewNode(
733 common()->Int32Constant(32 - masked_shift_value));
734
735 auto* op1 = machine()->Word32Shr();
736 auto* op2 = machine()->Word32Shl();
737 bool is_ror = node->opcode() == IrOpcode::kWord64RorLowerable;
738 if (!is_ror) std::swap(op1, op2);
739
740 Node* low_node =
741 graph()->NewNode(machine()->Word32Or(),
742 graph()->NewNode(op1, low_input, masked_shift),
743 graph()->NewNode(op2, high_input, inv_shift));
744 Node* high_node =
745 graph()->NewNode(machine()->Word32Or(),
746 graph()->NewNode(op1, high_input, masked_shift),
747 graph()->NewNode(op2, low_input, inv_shift));
748 ReplaceNode(node, low_node, high_node);
749 }
750 } else {
751 Node* safe_shift = shift;
752 if (!machine()->Word32ShiftIsSafe()) {
753 safe_shift =
754 graph()->NewNode(machine()->Word32And(), shift,
755 graph()->NewNode(common()->Int32Constant(0x1F)));
756 }
757
758 bool is_ror = node->opcode() == IrOpcode::kWord64RorLowerable;
759 Node* inv_mask =
760 is_ror ? graph()->NewNode(
761 machine()->Word32Xor(),
762 graph()->NewNode(
763 machine()->Word32Shr(),
764 graph()->NewNode(common()->Int32Constant(-1)),
765 safe_shift),
766 graph()->NewNode(common()->Int32Constant(-1)))
767 : graph()->NewNode(
768 machine()->Word32Shl(),
769 graph()->NewNode(common()->Int32Constant(-1)),
770 safe_shift);
771
772 Node* bit_mask =
773 graph()->NewNode(machine()->Word32Xor(), inv_mask,
774 graph()->NewNode(common()->Int32Constant(-1)));
775
776 // We have to mask the shift value for this comparison. If
777 // !machine()->Word32ShiftIsSafe() then the masking should already be
778 // part of the graph.
779 Node* masked_shift6 = shift;
780 if (machine()->Word32ShiftIsSafe()) {
781 masked_shift6 =
782 graph()->NewNode(machine()->Word32And(), shift,
783 graph()->NewNode(common()->Int32Constant(0x3F)));
784 }
785
786 Diamond lt32(
787 graph(), common(),
788 graph()->NewNode(machine()->Int32LessThan(), masked_shift6,
789 graph()->NewNode(common()->Int32Constant(32))));
790 lt32.Chain(NodeProperties::GetControlInput(node));
791
792 // The low word and the high word can be swapped either at the input or
793 // at the output. We swap the inputs so that shift does not have to be
794 // kept for so long in a register.
795 Node* input_low =
796 lt32.Phi(MachineRepresentation::kWord32, GetReplacementLow(input),
797 GetReplacementHigh(input));
798 Node* input_high =
799 lt32.Phi(MachineRepresentation::kWord32, GetReplacementHigh(input),
800 GetReplacementLow(input));
801
802 const Operator* oper =
803 is_ror ? machine()->Word32Ror() : machine()->Word32Rol().op();
804
805 Node* rotate_low = graph()->NewNode(oper, input_low, safe_shift);
806 Node* rotate_high = graph()->NewNode(oper, input_high, safe_shift);
807
808 auto* mask1 = bit_mask;
809 auto* mask2 = inv_mask;
810 if (!is_ror) std::swap(mask1, mask2);
811
812 Node* low_node = graph()->NewNode(
813 machine()->Word32Or(),
814 graph()->NewNode(machine()->Word32And(), rotate_low, mask1),
815 graph()->NewNode(machine()->Word32And(), rotate_high, mask2));
816 Node* high_node = graph()->NewNode(
817 machine()->Word32Or(),
818 graph()->NewNode(machine()->Word32And(), rotate_high, mask1),
819 graph()->NewNode(machine()->Word32And(), rotate_low, mask2));
820 ReplaceNode(node, low_node, high_node);
821 }
822 break;
823 }
824 case IrOpcode::kWord64ClzLowerable: {
825 DCHECK_EQ(2, node->InputCount());
826 Node* input = node->InputAt(0);
827 Diamond d(
828 graph(), common(),
829 graph()->NewNode(machine()->Word32Equal(), GetReplacementHigh(input),
830 graph()->NewNode(common()->Int32Constant(0))));
831 d.Chain(NodeProperties::GetControlInput(node));
832
833 Node* low_node = d.Phi(
834 MachineRepresentation::kWord32,
835 graph()->NewNode(machine()->Int32Add(),
836 graph()->NewNode(machine()->Word32Clz(),
837 GetReplacementLow(input)),
838 graph()->NewNode(common()->Int32Constant(32))),
839 graph()->NewNode(machine()->Word32Clz(), GetReplacementHigh(input)));
840 ReplaceNode(node, low_node, graph()->NewNode(common()->Int32Constant(0)));
841 break;
842 }
843 case IrOpcode::kWord64CtzLowerable: {
844 DCHECK_EQ(2, node->InputCount());
845 DCHECK(machine()->Word32Ctz().IsSupported());
846 Node* input = node->InputAt(0);
847 Diamond d(
848 graph(), common(),
849 graph()->NewNode(machine()->Word32Equal(), GetReplacementLow(input),
850 graph()->NewNode(common()->Int32Constant(0))));
851 d.Chain(NodeProperties::GetControlInput(node));
852
853 Node* low_node =
854 d.Phi(MachineRepresentation::kWord32,
855 graph()->NewNode(machine()->Int32Add(),
856 graph()->NewNode(machine()->Word32Ctz().op(),
857 GetReplacementHigh(input)),
858 graph()->NewNode(common()->Int32Constant(32))),
859 graph()->NewNode(machine()->Word32Ctz().op(),
860 GetReplacementLow(input)));
861 ReplaceNode(node, low_node, graph()->NewNode(common()->Int32Constant(0)));
862 break;
863 }
864 case IrOpcode::kWord64Ror:
865 case IrOpcode::kWord64Rol:
866 case IrOpcode::kWord64Ctz:
867 case IrOpcode::kWord64Clz:
868 FATAL("%s operator should not be used in 32-bit systems",
869 node->op()->mnemonic());
870 case IrOpcode::kWord64Popcnt: {
871 DCHECK_EQ(1, node->InputCount());
872 Node* input = node->InputAt(0);
873 // We assume that a Word64Popcnt node only has been created if
874 // Word32Popcnt is actually supported.
875 DCHECK(machine()->Word32Popcnt().IsSupported());
876 ReplaceNode(node, graph()->NewNode(
877 machine()->Int32Add(),
878 graph()->NewNode(machine()->Word32Popcnt().op(),
879 GetReplacementLow(input)),
880 graph()->NewNode(machine()->Word32Popcnt().op(),
881 GetReplacementHigh(input))),
882 graph()->NewNode(common()->Int32Constant(0)));
883 break;
884 }
885 case IrOpcode::kPhi: {
886 MachineRepresentation rep = PhiRepresentationOf(node->op());
887 if (rep == MachineRepresentation::kWord64) {
888 // The replacement nodes have already been created, we only have to
889 // replace placeholder nodes.
890 Node* low_node = GetReplacementLow(node);
891 Node* high_node = GetReplacementHigh(node);
892 for (int i = 0; i < node->op()->ValueInputCount(); i++) {
893 low_node->ReplaceInput(i, GetReplacementLow(node->InputAt(i)));
894 high_node->ReplaceInput(i, GetReplacementHigh(node->InputAt(i)));
895 }
896 } else {
897 DefaultLowering(node);
898 }
899 break;
900 }
901 case IrOpcode::kLoopExitValue: {
902 MachineRepresentation rep = LoopExitValueRepresentationOf(node->op());
903 if (rep == MachineRepresentation::kWord64) {
904 Node* low_node = graph()->NewNode(
905 common()->LoopExitValue(MachineRepresentation::kWord32),
906 GetReplacementLow(node->InputAt(0)), node->InputAt(1));
907 Node* high_node = graph()->NewNode(
908 common()->LoopExitValue(MachineRepresentation::kWord32),
909 GetReplacementHigh(node->InputAt(0)), node->InputAt(1));
910 ReplaceNode(node, low_node, high_node);
911 } else {
912 DefaultLowering(node);
913 }
914 break;
915 }
916 case IrOpcode::kWord64ReverseBytes: {
917 Node* input = node->InputAt(0);
918 ReplaceNode(node,
919 graph()->NewNode(machine()->Word32ReverseBytes(),
920 GetReplacementHigh(input)),
921 graph()->NewNode(machine()->Word32ReverseBytes(),
922 GetReplacementLow(input)));
923 break;
924 }
925 case IrOpcode::kSignExtendWord8ToInt64: {
926 DCHECK_EQ(1, node->InputCount());
927 Node* input = node->InputAt(0);
928 if (HasReplacementLow(input)) {
929 input = GetReplacementLow(input);
930 }
931 // Sign extend low node to Int32
932 input = graph()->NewNode(machine()->SignExtendWord8ToInt32(), input);
933
934 // We use SAR to preserve the sign in the high word.
935 ReplaceNode(
936 node, input,
937 graph()->NewNode(machine()->Word32Sar(), input,
938 graph()->NewNode(common()->Int32Constant(31))));
939 node->NullAllInputs();
940 break;
941 }
942 case IrOpcode::kSignExtendWord16ToInt64: {
943 DCHECK_EQ(1, node->InputCount());
944 Node* input = node->InputAt(0);
945 if (HasReplacementLow(input)) {
946 input = GetReplacementLow(input);
947 }
948 // Sign extend low node to Int32
949 input = graph()->NewNode(machine()->SignExtendWord16ToInt32(), input);
950
951 // We use SAR to preserve the sign in the high word.
952 ReplaceNode(
953 node, input,
954 graph()->NewNode(machine()->Word32Sar(), input,
955 graph()->NewNode(common()->Int32Constant(31))));
956 node->NullAllInputs();
957 break;
958 }
959 case IrOpcode::kWord64AtomicLoad: {
960 DCHECK_EQ(4, node->InputCount());
961 AtomicLoadParameters params = AtomicLoadParametersOf(node->op());
962 DefaultLowering(node, true);
963 if (params.representation() == MachineType::Uint64()) {
964 NodeProperties::ChangeOp(
965 node, machine()->Word32AtomicPairLoad(params.order()));
966 ReplaceNodeWithProjections(node);
967 } else {
968 NodeProperties::ChangeOp(node, machine()->Word32AtomicLoad(params));
969 ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
970 }
971 break;
972 }
973 case IrOpcode::kWord64AtomicStore: {
974 DCHECK_EQ(5, node->InputCount());
975 AtomicStoreParameters params = AtomicStoreParametersOf(node->op());
976 if (params.representation() == MachineRepresentation::kWord64) {
977 LowerMemoryBaseAndIndex(node);
978 Node* value = node->InputAt(2);
979 node->ReplaceInput(2, GetReplacementLow(value));
980 node->InsertInput(zone(), 3, GetReplacementHigh(value));
981 NodeProperties::ChangeOp(
982 node, machine()->Word32AtomicPairStore(params.order()));
983 } else {
984 DefaultLowering(node, true);
985 NodeProperties::ChangeOp(node, machine()->Word32AtomicStore(params));
986 }
987 break;
988 }
989 #define ATOMIC_CASE(name) \
990 case IrOpcode::kWord64Atomic##name: { \
991 MachineType type = AtomicOpType(node->op()); \
992 if (type == MachineType::Uint64()) { \
993 LowerWord64AtomicBinop(node, machine()->Word32AtomicPair##name()); \
994 } else { \
995 LowerWord64AtomicNarrowOp(node, machine()->Word32Atomic##name(type)); \
996 } \
997 break; \
998 }
999 ATOMIC_CASE(Add)
1000 ATOMIC_CASE(Sub)
1001 ATOMIC_CASE(And)
1002 ATOMIC_CASE(Or)
1003 ATOMIC_CASE(Xor)
1004 ATOMIC_CASE(Exchange)
1005 #undef ATOMIC_CASE
1006 case IrOpcode::kWord64AtomicCompareExchange: {
1007 MachineType type = AtomicOpType(node->op());
1008 if (type == MachineType::Uint64()) {
1009 LowerMemoryBaseAndIndex(node);
1010 Node* old_value = node->InputAt(2);
1011 Node* new_value = node->InputAt(3);
1012 node->ReplaceInput(2, GetReplacementLow(old_value));
1013 node->ReplaceInput(3, GetReplacementHigh(old_value));
1014 node->InsertInput(zone(), 4, GetReplacementLow(new_value));
1015 node->InsertInput(zone(), 5, GetReplacementHigh(new_value));
1016 NodeProperties::ChangeOp(node,
1017 machine()->Word32AtomicPairCompareExchange());
1018 ReplaceNodeWithProjections(node);
1019 } else {
1020 DCHECK(type == MachineType::Uint32() || type == MachineType::Uint16() ||
1021 type == MachineType::Uint8());
1022 DefaultLowering(node, true);
1023 NodeProperties::ChangeOp(node,
1024 machine()->Word32AtomicCompareExchange(type));
1025 ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
1026 }
1027 break;
1028 }
1029 case IrOpcode::kI64x2Splat: {
1030 DCHECK_EQ(1, node->InputCount());
1031 Node* input = node->InputAt(0);
1032 node->ReplaceInput(0, GetReplacementLow(input));
1033 node->AppendInput(zone(), GetReplacementHigh(input));
1034 NodeProperties::ChangeOp(node, machine()->I64x2SplatI32Pair());
1035 break;
1036 }
1037 case IrOpcode::kI64x2ExtractLane: {
1038 DCHECK_EQ(1, node->InputCount());
1039 Node* input = node->InputAt(0);
1040 int32_t lane = OpParameter<int32_t>(node->op());
1041 ReplaceNode(
1042 node, graph()->NewNode(machine()->I32x4ExtractLane(lane * 2), input),
1043 graph()->NewNode(machine()->I32x4ExtractLane(lane * 2 + 1), input));
1044 break;
1045 }
1046 case IrOpcode::kI64x2ReplaceLane: {
1047 DCHECK_EQ(2, node->InputCount());
1048 int32_t lane = OpParameter<int32_t>(node->op());
1049 Node* input = node->InputAt(1);
1050 node->ReplaceInput(1, GetReplacementLow(input));
1051 node->AppendInput(zone(), GetReplacementHigh(input));
1052 NodeProperties::ChangeOp(node, machine()->I64x2ReplaceLaneI32Pair(lane));
1053 break;
1054 }
1055
1056 default: { DefaultLowering(node); }
1057 }
1058 }
1059
LowerComparison(Node * node,const Operator * high_word_op,const Operator * low_word_op)1060 void Int64Lowering::LowerComparison(Node* node, const Operator* high_word_op,
1061 const Operator* low_word_op) {
1062 DCHECK_EQ(2, node->InputCount());
1063 Node* left = node->InputAt(0);
1064 Node* right = node->InputAt(1);
1065 Node* replacement = graph()->NewNode(
1066 machine()->Word32Or(),
1067 graph()->NewNode(high_word_op, GetReplacementHigh(left),
1068 GetReplacementHigh(right)),
1069 graph()->NewNode(
1070 machine()->Word32And(),
1071 graph()->NewNode(machine()->Word32Equal(), GetReplacementHigh(left),
1072 GetReplacementHigh(right)),
1073 graph()->NewNode(low_word_op, GetReplacementLow(left),
1074 GetReplacementLow(right))));
1075
1076 ReplaceNode(node, replacement, nullptr);
1077 }
1078
DefaultLowering(Node * node,bool low_word_only)1079 bool Int64Lowering::DefaultLowering(Node* node, bool low_word_only) {
1080 bool something_changed = false;
1081 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
1082 Node* input = node->InputAt(i);
1083 if (HasReplacementLow(input)) {
1084 something_changed = true;
1085 node->ReplaceInput(i, GetReplacementLow(input));
1086 }
1087 if (!low_word_only && HasReplacementHigh(input)) {
1088 something_changed = true;
1089 node->InsertInput(zone(), i + 1, GetReplacementHigh(input));
1090 }
1091 }
1092 return something_changed;
1093 }
1094
LowerCallDescriptor(const CallDescriptor * call_descriptor)1095 const CallDescriptor* Int64Lowering::LowerCallDescriptor(
1096 const CallDescriptor* call_descriptor) {
1097 if (special_case_) {
1098 auto replacement = special_case_->replacements.find(call_descriptor);
1099 if (replacement != special_case_->replacements.end()) {
1100 return replacement->second;
1101 }
1102 }
1103 return GetI32WasmCallDescriptor(zone(), call_descriptor);
1104 }
1105
ReplaceNode(Node * old,Node * new_low,Node * new_high)1106 void Int64Lowering::ReplaceNode(Node* old, Node* new_low, Node* new_high) {
1107 // if new_low == nullptr, then also new_high == nullptr.
1108 DCHECK(new_low != nullptr || new_high == nullptr);
1109 replacements_[old->id()].low = new_low;
1110 replacements_[old->id()].high = new_high;
1111 }
1112
HasReplacementLow(Node * node)1113 bool Int64Lowering::HasReplacementLow(Node* node) {
1114 return replacements_[node->id()].low != nullptr;
1115 }
1116
GetReplacementLow(Node * node)1117 Node* Int64Lowering::GetReplacementLow(Node* node) {
1118 Node* result = replacements_[node->id()].low;
1119 DCHECK(result);
1120 return result;
1121 }
1122
HasReplacementHigh(Node * node)1123 bool Int64Lowering::HasReplacementHigh(Node* node) {
1124 return replacements_[node->id()].high != nullptr;
1125 }
1126
GetReplacementHigh(Node * node)1127 Node* Int64Lowering::GetReplacementHigh(Node* node) {
1128 Node* result = replacements_[node->id()].high;
1129 DCHECK(result);
1130 return result;
1131 }
1132
PreparePhiReplacement(Node * phi)1133 void Int64Lowering::PreparePhiReplacement(Node* phi) {
1134 MachineRepresentation rep = PhiRepresentationOf(phi->op());
1135 if (rep == MachineRepresentation::kWord64) {
1136 // We have to create the replacements for a phi node before we actually
1137 // lower the phi to break potential cycles in the graph. The replacements of
1138 // input nodes do not exist yet, so we use a placeholder node to pass the
1139 // graph verifier.
1140 int value_count = phi->op()->ValueInputCount();
1141 Node** inputs_low = zone()->NewArray<Node*>(value_count + 1);
1142 Node** inputs_high = zone()->NewArray<Node*>(value_count + 1);
1143 for (int i = 0; i < value_count; i++) {
1144 inputs_low[i] = placeholder_;
1145 inputs_high[i] = placeholder_;
1146 }
1147 inputs_low[value_count] = NodeProperties::GetControlInput(phi, 0);
1148 inputs_high[value_count] = NodeProperties::GetControlInput(phi, 0);
1149 ReplaceNode(phi,
1150 graph()->NewNode(
1151 common()->Phi(MachineRepresentation::kWord32, value_count),
1152 value_count + 1, inputs_low, false),
1153 graph()->NewNode(
1154 common()->Phi(MachineRepresentation::kWord32, value_count),
1155 value_count + 1, inputs_high, false));
1156 }
1157 }
1158
ReplaceNodeWithProjections(Node * node)1159 void Int64Lowering::ReplaceNodeWithProjections(Node* node) {
1160 DCHECK(node != nullptr);
1161 Node* low_node =
1162 graph()->NewNode(common()->Projection(0), node, graph()->start());
1163 Node* high_node =
1164 graph()->NewNode(common()->Projection(1), node, graph()->start());
1165 ReplaceNode(node, low_node, high_node);
1166 }
1167
LowerMemoryBaseAndIndex(Node * node)1168 void Int64Lowering::LowerMemoryBaseAndIndex(Node* node) {
1169 DCHECK(node != nullptr);
1170 // Low word only replacements for memory operands for 32-bit address space.
1171 Node* base = node->InputAt(0);
1172 Node* index = node->InputAt(1);
1173 if (HasReplacementLow(base)) {
1174 node->ReplaceInput(0, GetReplacementLow(base));
1175 }
1176 if (HasReplacementLow(index)) {
1177 node->ReplaceInput(1, GetReplacementLow(index));
1178 }
1179 }
1180
1181 } // namespace compiler
1182 } // namespace internal
1183 } // namespace v8
1184