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, 3),
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_.Set(graph()->end(), 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_.Set(top.node, 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_.Get(input) == 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_.Set(input, 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::kStore: {
272 StoreRepresentation store_rep = StoreRepresentationOf(node->op());
273 LowerStoreOperator(
274 node, store_rep.representation(),
275 machine()->Store(StoreRepresentation(
276 MachineRepresentation::kWord32, store_rep.write_barrier_kind())));
277 break;
278 }
279 case IrOpcode::kUnalignedStore: {
280 UnalignedStoreRepresentation store_rep =
281 UnalignedStoreRepresentationOf(node->op());
282 LowerStoreOperator(
283 node, store_rep,
284 machine()->UnalignedStore(MachineRepresentation::kWord32));
285 break;
286 }
287 case IrOpcode::kStoreToObject: {
288 ObjectAccess access = ObjectAccessOf(node->op());
289 LowerStoreOperator(node, access.machine_type.representation(),
290 simplified()->StoreToObject(ObjectAccess(
291 MachineType::Int32(), access.write_barrier_kind)));
292 break;
293 }
294 case IrOpcode::kStart: {
295 int parameter_count = GetParameterCountAfterLowering(signature());
296 // Only exchange the node if the parameter count actually changed.
297 if (parameter_count != static_cast<int>(signature()->parameter_count())) {
298 int delta =
299 parameter_count - static_cast<int>(signature()->parameter_count());
300 int new_output_count = node->op()->ValueOutputCount() + delta;
301 NodeProperties::ChangeOp(node, common()->Start(new_output_count));
302 }
303 break;
304 }
305 case IrOpcode::kParameter: {
306 DCHECK_EQ(1, node->InputCount());
307 int param_count = static_cast<int>(signature()->parameter_count());
308 // Only exchange the node if the parameter count actually changed. We do
309 // not even have to do the default lowering because the the start node,
310 // the only input of a parameter node, only changes if the parameter count
311 // changes.
312 if (GetParameterCountAfterLowering(signature()) != param_count) {
313 int old_index = ParameterIndexOf(node->op());
314 // Adjust old_index to be compliant with the signature.
315 --old_index;
316 int new_index = GetParameterIndexAfterLowering(signature(), old_index);
317 // Adjust new_index to consider the instance parameter.
318 ++new_index;
319 NodeProperties::ChangeOp(node, common()->Parameter(new_index));
320
321 if (old_index < 0 || old_index >= param_count) {
322 // Special parameters (JS closure/context) don't have kWord64
323 // representation anyway.
324 break;
325 }
326
327 if (signature()->GetParam(old_index) ==
328 MachineRepresentation::kWord64) {
329 Node* high_node = graph()->NewNode(common()->Parameter(new_index + 1),
330 graph()->start());
331 ReplaceNode(node, node, high_node);
332 }
333 }
334 break;
335 }
336 case IrOpcode::kReturn: {
337 int input_count = node->InputCount();
338 DefaultLowering(node);
339 if (input_count != node->InputCount()) {
340 int new_return_count = GetReturnCountAfterLowering(signature());
341 if (static_cast<int>(signature()->return_count()) != new_return_count) {
342 NodeProperties::ChangeOp(node, common()->Return(new_return_count));
343 }
344 }
345 break;
346 }
347 case IrOpcode::kTailCall: {
348 auto call_descriptor =
349 const_cast<CallDescriptor*>(CallDescriptorOf(node->op()));
350 bool returns_require_lowering =
351 GetReturnCountAfterLowering(call_descriptor) !=
352 static_cast<int>(call_descriptor->ReturnCount());
353 if (DefaultLowering(node) || returns_require_lowering) {
354 // Tail calls do not have return values, so adjusting the call
355 // descriptor is enough.
356 NodeProperties::ChangeOp(
357 node, common()->TailCall(LowerCallDescriptor(call_descriptor)));
358 }
359 break;
360 }
361 case IrOpcode::kCall: {
362 auto call_descriptor = CallDescriptorOf(node->op());
363
364 bool returns_require_lowering =
365 GetReturnCountAfterLowering(call_descriptor) !=
366 static_cast<int>(call_descriptor->ReturnCount());
367 if (DefaultLowering(node) || returns_require_lowering) {
368 // We have to adjust the call descriptor.
369 NodeProperties::ChangeOp(
370 node, common()->Call(LowerCallDescriptor(call_descriptor)));
371 }
372 if (returns_require_lowering) {
373 size_t return_arity = call_descriptor->ReturnCount();
374 if (return_arity == 1) {
375 // We access the additional return values through projections.
376 ReplaceNodeWithProjections(node);
377 } else {
378 ZoneVector<Node*> projections(return_arity, zone());
379 NodeProperties::CollectValueProjections(node, projections.data(),
380 return_arity);
381 for (size_t old_index = 0, new_index = 0; old_index < return_arity;
382 ++old_index, ++new_index) {
383 Node* use_node = projections[old_index];
384 DCHECK_EQ(ProjectionIndexOf(use_node->op()), old_index);
385 DCHECK_EQ(GetReturnIndexAfterLowering(call_descriptor,
386 static_cast<int>(old_index)),
387 static_cast<int>(new_index));
388 if (new_index != old_index) {
389 NodeProperties::ChangeOp(
390 use_node, common()->Projection(new_index));
391 }
392 if (call_descriptor->GetReturnType(old_index).representation() ==
393 MachineRepresentation::kWord64) {
394 Node* high_node = graph()->NewNode(
395 common()->Projection(new_index + 1), node, graph()->start());
396 ReplaceNode(use_node, use_node, high_node);
397 ++new_index;
398 }
399 }
400 }
401 }
402 break;
403 }
404 case IrOpcode::kWord64And: {
405 DCHECK_EQ(2, node->InputCount());
406 Node* left = node->InputAt(0);
407 Node* right = node->InputAt(1);
408
409 Node* low_node =
410 graph()->NewNode(machine()->Word32And(), GetReplacementLow(left),
411 GetReplacementLow(right));
412 Node* high_node =
413 graph()->NewNode(machine()->Word32And(), GetReplacementHigh(left),
414 GetReplacementHigh(right));
415 ReplaceNode(node, low_node, high_node);
416 break;
417 }
418 case IrOpcode::kTruncateInt64ToInt32: {
419 DCHECK_EQ(1, node->InputCount());
420 Node* input = node->InputAt(0);
421 ReplaceNode(node, GetReplacementLow(input), nullptr);
422 node->NullAllInputs();
423 break;
424 }
425 case IrOpcode::kInt64Add: {
426 DCHECK_EQ(2, node->InputCount());
427
428 Node* right = node->InputAt(1);
429 node->ReplaceInput(1, GetReplacementLow(right));
430 node->AppendInput(zone(), GetReplacementHigh(right));
431
432 Node* left = node->InputAt(0);
433 node->ReplaceInput(0, GetReplacementLow(left));
434 node->InsertInput(zone(), 1, GetReplacementHigh(left));
435
436 NodeProperties::ChangeOp(node, machine()->Int32PairAdd());
437 // We access the additional return values through projections.
438 ReplaceNodeWithProjections(node);
439 break;
440 }
441 case IrOpcode::kInt64Sub: {
442 DCHECK_EQ(2, node->InputCount());
443
444 Node* right = node->InputAt(1);
445 node->ReplaceInput(1, GetReplacementLow(right));
446 node->AppendInput(zone(), GetReplacementHigh(right));
447
448 Node* left = node->InputAt(0);
449 node->ReplaceInput(0, GetReplacementLow(left));
450 node->InsertInput(zone(), 1, GetReplacementHigh(left));
451
452 NodeProperties::ChangeOp(node, machine()->Int32PairSub());
453 // We access the additional return values through projections.
454 ReplaceNodeWithProjections(node);
455 break;
456 }
457 case IrOpcode::kInt64Mul: {
458 DCHECK_EQ(2, node->InputCount());
459
460 Node* right = node->InputAt(1);
461 node->ReplaceInput(1, GetReplacementLow(right));
462 node->AppendInput(zone(), GetReplacementHigh(right));
463
464 Node* left = node->InputAt(0);
465 node->ReplaceInput(0, GetReplacementLow(left));
466 node->InsertInput(zone(), 1, GetReplacementHigh(left));
467
468 NodeProperties::ChangeOp(node, machine()->Int32PairMul());
469 // We access the additional return values through projections.
470 ReplaceNodeWithProjections(node);
471 break;
472 }
473 case IrOpcode::kWord64Or: {
474 DCHECK_EQ(2, node->InputCount());
475 Node* left = node->InputAt(0);
476 Node* right = node->InputAt(1);
477
478 Node* low_node =
479 graph()->NewNode(machine()->Word32Or(), GetReplacementLow(left),
480 GetReplacementLow(right));
481 Node* high_node =
482 graph()->NewNode(machine()->Word32Or(), GetReplacementHigh(left),
483 GetReplacementHigh(right));
484 ReplaceNode(node, low_node, high_node);
485 break;
486 }
487 case IrOpcode::kWord64Xor: {
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()->Word32Xor(), GetReplacementLow(left),
494 GetReplacementLow(right));
495 Node* high_node =
496 graph()->NewNode(machine()->Word32Xor(), GetReplacementHigh(left),
497 GetReplacementHigh(right));
498 ReplaceNode(node, low_node, high_node);
499 break;
500 }
501 case IrOpcode::kWord64Shl: {
502 // TODO(turbofan): if the shift count >= 32, then we can set the low word
503 // of the output to 0 and just calculate the high word.
504 DCHECK_EQ(2, node->InputCount());
505 Node* shift = node->InputAt(1);
506 if (HasReplacementLow(shift)) {
507 // We do not have to care about the high word replacement, because
508 // the shift can only be between 0 and 63 anyways.
509 node->ReplaceInput(1, GetReplacementLow(shift));
510 }
511
512 Node* value = node->InputAt(0);
513 node->ReplaceInput(0, GetReplacementLow(value));
514 node->InsertInput(zone(), 1, GetReplacementHigh(value));
515
516 NodeProperties::ChangeOp(node, machine()->Word32PairShl());
517 // We access the additional return values through projections.
518 ReplaceNodeWithProjections(node);
519 break;
520 }
521 case IrOpcode::kWord64Shr: {
522 // TODO(turbofan): if the shift count >= 32, then we can set the low word
523 // of the output to 0 and just calculate the high word.
524 DCHECK_EQ(2, node->InputCount());
525 Node* shift = node->InputAt(1);
526 if (HasReplacementLow(shift)) {
527 // We do not have to care about the high word replacement, because
528 // the shift can only be between 0 and 63 anyways.
529 node->ReplaceInput(1, GetReplacementLow(shift));
530 }
531
532 Node* value = node->InputAt(0);
533 node->ReplaceInput(0, GetReplacementLow(value));
534 node->InsertInput(zone(), 1, GetReplacementHigh(value));
535
536 NodeProperties::ChangeOp(node, machine()->Word32PairShr());
537 // We access the additional return values through projections.
538 ReplaceNodeWithProjections(node);
539 break;
540 }
541 case IrOpcode::kWord64Sar: {
542 // TODO(turbofan): if the shift count >= 32, then we can set the low word
543 // of the output to 0 and just calculate the high word.
544 DCHECK_EQ(2, node->InputCount());
545 Node* shift = node->InputAt(1);
546 if (HasReplacementLow(shift)) {
547 // We do not have to care about the high word replacement, because
548 // the shift can only be between 0 and 63 anyways.
549 node->ReplaceInput(1, GetReplacementLow(shift));
550 }
551
552 Node* value = node->InputAt(0);
553 node->ReplaceInput(0, GetReplacementLow(value));
554 node->InsertInput(zone(), 1, GetReplacementHigh(value));
555
556 NodeProperties::ChangeOp(node, machine()->Word32PairSar());
557 // We access the additional return values through projections.
558 ReplaceNodeWithProjections(node);
559 break;
560 }
561 case IrOpcode::kWord64Equal: {
562 DCHECK_EQ(2, node->InputCount());
563 Node* left = node->InputAt(0);
564 Node* right = node->InputAt(1);
565
566 // TODO(wasm): Use explicit comparisons and && here?
567 Node* replacement = graph()->NewNode(
568 machine()->Word32Equal(),
569 graph()->NewNode(
570 machine()->Word32Or(),
571 graph()->NewNode(machine()->Word32Xor(), GetReplacementLow(left),
572 GetReplacementLow(right)),
573 graph()->NewNode(machine()->Word32Xor(), GetReplacementHigh(left),
574 GetReplacementHigh(right))),
575 graph()->NewNode(common()->Int32Constant(0)));
576
577 ReplaceNode(node, replacement, nullptr);
578 break;
579 }
580 case IrOpcode::kInt64LessThan: {
581 LowerComparison(node, machine()->Int32LessThan(),
582 machine()->Uint32LessThan());
583 break;
584 }
585 case IrOpcode::kInt64LessThanOrEqual: {
586 LowerComparison(node, machine()->Int32LessThan(),
587 machine()->Uint32LessThanOrEqual());
588 break;
589 }
590 case IrOpcode::kUint64LessThan: {
591 LowerComparison(node, machine()->Uint32LessThan(),
592 machine()->Uint32LessThan());
593 break;
594 }
595 case IrOpcode::kUint64LessThanOrEqual: {
596 LowerComparison(node, machine()->Uint32LessThan(),
597 machine()->Uint32LessThanOrEqual());
598 break;
599 }
600 case IrOpcode::kSignExtendWord32ToInt64:
601 case IrOpcode::kChangeInt32ToInt64: {
602 DCHECK_EQ(1, node->InputCount());
603 Node* input = node->InputAt(0);
604 if (HasReplacementLow(input)) {
605 input = GetReplacementLow(input);
606 }
607 // We use SAR to preserve the sign in the high word.
608 ReplaceNode(
609 node, input,
610 graph()->NewNode(machine()->Word32Sar(), input,
611 graph()->NewNode(common()->Int32Constant(31))));
612 node->NullAllInputs();
613 break;
614 }
615 case IrOpcode::kChangeUint32ToUint64: {
616 DCHECK_EQ(1, node->InputCount());
617 Node* input = node->InputAt(0);
618 if (HasReplacementLow(input)) {
619 input = GetReplacementLow(input);
620 }
621 ReplaceNode(node, input, graph()->NewNode(common()->Int32Constant(0)));
622 node->NullAllInputs();
623 break;
624 }
625 case IrOpcode::kBitcastInt64ToFloat64: {
626 DCHECK_EQ(1, node->InputCount());
627 Node* input = node->InputAt(0);
628 Node* stack_slot = graph()->NewNode(
629 machine()->StackSlot(MachineRepresentation::kWord64));
630
631 Node* store_high_word = graph()->NewNode(
632 machine()->Store(
633 StoreRepresentation(MachineRepresentation::kWord32,
634 WriteBarrierKind::kNoWriteBarrier)),
635 stack_slot,
636 graph()->NewNode(
637 common()->Int32Constant(kInt64UpperHalfMemoryOffset)),
638 GetReplacementHigh(input), graph()->start(), graph()->start());
639
640 Node* store_low_word = graph()->NewNode(
641 machine()->Store(
642 StoreRepresentation(MachineRepresentation::kWord32,
643 WriteBarrierKind::kNoWriteBarrier)),
644 stack_slot,
645 graph()->NewNode(
646 common()->Int32Constant(kInt64LowerHalfMemoryOffset)),
647 GetReplacementLow(input), store_high_word, graph()->start());
648
649 Node* load =
650 graph()->NewNode(machine()->Load(MachineType::Float64()), stack_slot,
651 graph()->NewNode(common()->Int32Constant(0)),
652 store_low_word, graph()->start());
653
654 ReplaceNode(node, load, nullptr);
655 break;
656 }
657 case IrOpcode::kBitcastFloat64ToInt64: {
658 DCHECK_EQ(1, node->InputCount());
659 Node* input = node->InputAt(0);
660 if (HasReplacementLow(input)) {
661 input = GetReplacementLow(input);
662 }
663 Node* stack_slot = graph()->NewNode(
664 machine()->StackSlot(MachineRepresentation::kWord64));
665 Node* store = graph()->NewNode(
666 machine()->Store(
667 StoreRepresentation(MachineRepresentation::kFloat64,
668 WriteBarrierKind::kNoWriteBarrier)),
669 stack_slot, graph()->NewNode(common()->Int32Constant(0)), input,
670 graph()->start(), graph()->start());
671
672 Node* high_node = graph()->NewNode(
673 machine()->Load(MachineType::Int32()), stack_slot,
674 graph()->NewNode(
675 common()->Int32Constant(kInt64UpperHalfMemoryOffset)),
676 store, graph()->start());
677
678 Node* low_node = graph()->NewNode(
679 machine()->Load(MachineType::Int32()), stack_slot,
680 graph()->NewNode(
681 common()->Int32Constant(kInt64LowerHalfMemoryOffset)),
682 store, graph()->start());
683 ReplaceNode(node, low_node, high_node);
684 break;
685 }
686 case IrOpcode::kWord64RolLowerable:
687 DCHECK(machine()->Word32Rol().IsSupported());
688 V8_FALLTHROUGH;
689 case IrOpcode::kWord64RorLowerable: {
690 DCHECK_EQ(3, node->InputCount());
691 Node* input = node->InputAt(0);
692 Node* shift = HasReplacementLow(node->InputAt(1))
693 ? GetReplacementLow(node->InputAt(1))
694 : node->InputAt(1);
695 Int32Matcher m(shift);
696 if (m.HasResolvedValue()) {
697 // Precondition: 0 <= shift < 64.
698 int32_t shift_value = m.ResolvedValue() & 0x3F;
699 if (shift_value == 0) {
700 ReplaceNode(node, GetReplacementLow(input),
701 GetReplacementHigh(input));
702 } else if (shift_value == 32) {
703 ReplaceNode(node, GetReplacementHigh(input),
704 GetReplacementLow(input));
705 } else {
706 Node* low_input;
707 Node* high_input;
708 if (shift_value < 32) {
709 low_input = GetReplacementLow(input);
710 high_input = GetReplacementHigh(input);
711 } else {
712 low_input = GetReplacementHigh(input);
713 high_input = GetReplacementLow(input);
714 }
715 int32_t masked_shift_value = shift_value & 0x1F;
716 Node* masked_shift =
717 graph()->NewNode(common()->Int32Constant(masked_shift_value));
718 Node* inv_shift = graph()->NewNode(
719 common()->Int32Constant(32 - masked_shift_value));
720
721 auto* op1 = machine()->Word32Shr();
722 auto* op2 = machine()->Word32Shl();
723 bool is_ror = node->opcode() == IrOpcode::kWord64RorLowerable;
724 if (!is_ror) std::swap(op1, op2);
725
726 Node* low_node =
727 graph()->NewNode(machine()->Word32Or(),
728 graph()->NewNode(op1, low_input, masked_shift),
729 graph()->NewNode(op2, high_input, inv_shift));
730 Node* high_node =
731 graph()->NewNode(machine()->Word32Or(),
732 graph()->NewNode(op1, high_input, masked_shift),
733 graph()->NewNode(op2, low_input, inv_shift));
734 ReplaceNode(node, low_node, high_node);
735 }
736 } else {
737 Node* safe_shift = shift;
738 if (!machine()->Word32ShiftIsSafe()) {
739 safe_shift =
740 graph()->NewNode(machine()->Word32And(), shift,
741 graph()->NewNode(common()->Int32Constant(0x1F)));
742 }
743
744 bool is_ror = node->opcode() == IrOpcode::kWord64RorLowerable;
745 Node* inv_mask =
746 is_ror ? graph()->NewNode(
747 machine()->Word32Xor(),
748 graph()->NewNode(
749 machine()->Word32Shr(),
750 graph()->NewNode(common()->Int32Constant(-1)),
751 safe_shift),
752 graph()->NewNode(common()->Int32Constant(-1)))
753 : graph()->NewNode(
754 machine()->Word32Shl(),
755 graph()->NewNode(common()->Int32Constant(-1)),
756 safe_shift);
757
758 Node* bit_mask =
759 graph()->NewNode(machine()->Word32Xor(), inv_mask,
760 graph()->NewNode(common()->Int32Constant(-1)));
761
762 // We have to mask the shift value for this comparison. If
763 // !machine()->Word32ShiftIsSafe() then the masking should already be
764 // part of the graph.
765 Node* masked_shift6 = shift;
766 if (machine()->Word32ShiftIsSafe()) {
767 masked_shift6 =
768 graph()->NewNode(machine()->Word32And(), shift,
769 graph()->NewNode(common()->Int32Constant(0x3F)));
770 }
771
772 Diamond lt32(
773 graph(), common(),
774 graph()->NewNode(machine()->Int32LessThan(), masked_shift6,
775 graph()->NewNode(common()->Int32Constant(32))));
776 lt32.Chain(NodeProperties::GetControlInput(node));
777
778 // The low word and the high word can be swapped either at the input or
779 // at the output. We swap the inputs so that shift does not have to be
780 // kept for so long in a register.
781 Node* input_low =
782 lt32.Phi(MachineRepresentation::kWord32, GetReplacementLow(input),
783 GetReplacementHigh(input));
784 Node* input_high =
785 lt32.Phi(MachineRepresentation::kWord32, GetReplacementHigh(input),
786 GetReplacementLow(input));
787
788 const Operator* oper =
789 is_ror ? machine()->Word32Ror() : machine()->Word32Rol().op();
790
791 Node* rotate_low = graph()->NewNode(oper, input_low, safe_shift);
792 Node* rotate_high = graph()->NewNode(oper, input_high, safe_shift);
793
794 auto* mask1 = bit_mask;
795 auto* mask2 = inv_mask;
796 if (!is_ror) std::swap(mask1, mask2);
797
798 Node* low_node = graph()->NewNode(
799 machine()->Word32Or(),
800 graph()->NewNode(machine()->Word32And(), rotate_low, mask1),
801 graph()->NewNode(machine()->Word32And(), rotate_high, mask2));
802 Node* high_node = graph()->NewNode(
803 machine()->Word32Or(),
804 graph()->NewNode(machine()->Word32And(), rotate_high, mask1),
805 graph()->NewNode(machine()->Word32And(), rotate_low, mask2));
806 ReplaceNode(node, low_node, high_node);
807 }
808 break;
809 }
810 case IrOpcode::kWord64ClzLowerable: {
811 DCHECK_EQ(2, node->InputCount());
812 Node* input = node->InputAt(0);
813 Diamond d(
814 graph(), common(),
815 graph()->NewNode(machine()->Word32Equal(), GetReplacementHigh(input),
816 graph()->NewNode(common()->Int32Constant(0))));
817 d.Chain(NodeProperties::GetControlInput(node));
818
819 Node* low_node = d.Phi(
820 MachineRepresentation::kWord32,
821 graph()->NewNode(machine()->Int32Add(),
822 graph()->NewNode(machine()->Word32Clz(),
823 GetReplacementLow(input)),
824 graph()->NewNode(common()->Int32Constant(32))),
825 graph()->NewNode(machine()->Word32Clz(), GetReplacementHigh(input)));
826 ReplaceNode(node, low_node, graph()->NewNode(common()->Int32Constant(0)));
827 break;
828 }
829 case IrOpcode::kWord64CtzLowerable: {
830 DCHECK_EQ(2, node->InputCount());
831 DCHECK(machine()->Word32Ctz().IsSupported());
832 Node* input = node->InputAt(0);
833 Diamond d(
834 graph(), common(),
835 graph()->NewNode(machine()->Word32Equal(), GetReplacementLow(input),
836 graph()->NewNode(common()->Int32Constant(0))));
837 d.Chain(NodeProperties::GetControlInput(node));
838
839 Node* low_node =
840 d.Phi(MachineRepresentation::kWord32,
841 graph()->NewNode(machine()->Int32Add(),
842 graph()->NewNode(machine()->Word32Ctz().op(),
843 GetReplacementHigh(input)),
844 graph()->NewNode(common()->Int32Constant(32))),
845 graph()->NewNode(machine()->Word32Ctz().op(),
846 GetReplacementLow(input)));
847 ReplaceNode(node, low_node, graph()->NewNode(common()->Int32Constant(0)));
848 break;
849 }
850 case IrOpcode::kWord64Ror:
851 case IrOpcode::kWord64Rol:
852 case IrOpcode::kWord64Ctz:
853 case IrOpcode::kWord64Clz:
854 FATAL("%s operator should not be used in 32-bit systems",
855 node->op()->mnemonic());
856 case IrOpcode::kWord64Popcnt: {
857 DCHECK_EQ(1, node->InputCount());
858 Node* input = node->InputAt(0);
859 // We assume that a Word64Popcnt node only has been created if
860 // Word32Popcnt is actually supported.
861 DCHECK(machine()->Word32Popcnt().IsSupported());
862 ReplaceNode(node, graph()->NewNode(
863 machine()->Int32Add(),
864 graph()->NewNode(machine()->Word32Popcnt().op(),
865 GetReplacementLow(input)),
866 graph()->NewNode(machine()->Word32Popcnt().op(),
867 GetReplacementHigh(input))),
868 graph()->NewNode(common()->Int32Constant(0)));
869 break;
870 }
871 case IrOpcode::kPhi: {
872 MachineRepresentation rep = PhiRepresentationOf(node->op());
873 if (rep == MachineRepresentation::kWord64) {
874 // The replacement nodes have already been created, we only have to
875 // replace placeholder nodes.
876 Node* low_node = GetReplacementLow(node);
877 Node* high_node = GetReplacementHigh(node);
878 for (int i = 0; i < node->op()->ValueInputCount(); i++) {
879 low_node->ReplaceInput(i, GetReplacementLow(node->InputAt(i)));
880 high_node->ReplaceInput(i, GetReplacementHigh(node->InputAt(i)));
881 }
882 } else {
883 DefaultLowering(node);
884 }
885 break;
886 }
887 case IrOpcode::kLoopExitValue: {
888 MachineRepresentation rep = LoopExitValueRepresentationOf(node->op());
889 if (rep == MachineRepresentation::kWord64) {
890 Node* low_node = graph()->NewNode(
891 common()->LoopExitValue(MachineRepresentation::kWord32),
892 GetReplacementLow(node->InputAt(0)), node->InputAt(1));
893 Node* high_node = graph()->NewNode(
894 common()->LoopExitValue(MachineRepresentation::kWord32),
895 GetReplacementHigh(node->InputAt(0)), node->InputAt(1));
896 ReplaceNode(node, low_node, high_node);
897 } else {
898 DefaultLowering(node);
899 }
900 break;
901 }
902 case IrOpcode::kWord64ReverseBytes: {
903 Node* input = node->InputAt(0);
904 ReplaceNode(node,
905 graph()->NewNode(machine()->Word32ReverseBytes(),
906 GetReplacementHigh(input)),
907 graph()->NewNode(machine()->Word32ReverseBytes(),
908 GetReplacementLow(input)));
909 break;
910 }
911 case IrOpcode::kSignExtendWord8ToInt64: {
912 DCHECK_EQ(1, node->InputCount());
913 Node* input = node->InputAt(0);
914 if (HasReplacementLow(input)) {
915 input = GetReplacementLow(input);
916 }
917 // Sign extend low node to Int32
918 input = graph()->NewNode(machine()->SignExtendWord8ToInt32(), input);
919
920 // We use SAR to preserve the sign in the high word.
921 ReplaceNode(
922 node, input,
923 graph()->NewNode(machine()->Word32Sar(), input,
924 graph()->NewNode(common()->Int32Constant(31))));
925 node->NullAllInputs();
926 break;
927 }
928 case IrOpcode::kSignExtendWord16ToInt64: {
929 DCHECK_EQ(1, node->InputCount());
930 Node* input = node->InputAt(0);
931 if (HasReplacementLow(input)) {
932 input = GetReplacementLow(input);
933 }
934 // Sign extend low node to Int32
935 input = graph()->NewNode(machine()->SignExtendWord16ToInt32(), input);
936
937 // We use SAR to preserve the sign in the high word.
938 ReplaceNode(
939 node, input,
940 graph()->NewNode(machine()->Word32Sar(), input,
941 graph()->NewNode(common()->Int32Constant(31))));
942 node->NullAllInputs();
943 break;
944 }
945 case IrOpcode::kWord64AtomicLoad: {
946 DCHECK_EQ(4, node->InputCount());
947 AtomicLoadParameters params = AtomicLoadParametersOf(node->op());
948 DefaultLowering(node, true);
949 if (params.representation() == MachineType::Uint64()) {
950 NodeProperties::ChangeOp(
951 node, machine()->Word32AtomicPairLoad(params.order()));
952 ReplaceNodeWithProjections(node);
953 } else {
954 NodeProperties::ChangeOp(node, machine()->Word32AtomicLoad(params));
955 ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
956 }
957 break;
958 }
959 case IrOpcode::kWord64AtomicStore: {
960 DCHECK_EQ(5, node->InputCount());
961 AtomicStoreParameters params = AtomicStoreParametersOf(node->op());
962 if (params.representation() == MachineRepresentation::kWord64) {
963 LowerMemoryBaseAndIndex(node);
964 Node* value = node->InputAt(2);
965 node->ReplaceInput(2, GetReplacementLow(value));
966 node->InsertInput(zone(), 3, GetReplacementHigh(value));
967 NodeProperties::ChangeOp(
968 node, machine()->Word32AtomicPairStore(params.order()));
969 } else {
970 DefaultLowering(node, true);
971 NodeProperties::ChangeOp(node, machine()->Word32AtomicStore(params));
972 }
973 break;
974 }
975 #define ATOMIC_CASE(name) \
976 case IrOpcode::kWord64Atomic##name: { \
977 MachineType type = AtomicOpType(node->op()); \
978 if (type == MachineType::Uint64()) { \
979 LowerWord64AtomicBinop(node, machine()->Word32AtomicPair##name()); \
980 } else { \
981 LowerWord64AtomicNarrowOp(node, machine()->Word32Atomic##name(type)); \
982 } \
983 break; \
984 }
985 ATOMIC_CASE(Add)
986 ATOMIC_CASE(Sub)
987 ATOMIC_CASE(And)
988 ATOMIC_CASE(Or)
989 ATOMIC_CASE(Xor)
990 ATOMIC_CASE(Exchange)
991 #undef ATOMIC_CASE
992 case IrOpcode::kWord64AtomicCompareExchange: {
993 MachineType type = AtomicOpType(node->op());
994 if (type == MachineType::Uint64()) {
995 LowerMemoryBaseAndIndex(node);
996 Node* old_value = node->InputAt(2);
997 Node* new_value = node->InputAt(3);
998 node->ReplaceInput(2, GetReplacementLow(old_value));
999 node->ReplaceInput(3, GetReplacementHigh(old_value));
1000 node->InsertInput(zone(), 4, GetReplacementLow(new_value));
1001 node->InsertInput(zone(), 5, GetReplacementHigh(new_value));
1002 NodeProperties::ChangeOp(node,
1003 machine()->Word32AtomicPairCompareExchange());
1004 ReplaceNodeWithProjections(node);
1005 } else {
1006 DCHECK(type == MachineType::Uint32() || type == MachineType::Uint16() ||
1007 type == MachineType::Uint8());
1008 DefaultLowering(node, true);
1009 NodeProperties::ChangeOp(node,
1010 machine()->Word32AtomicCompareExchange(type));
1011 ReplaceNode(node, node, graph()->NewNode(common()->Int32Constant(0)));
1012 }
1013 break;
1014 }
1015 case IrOpcode::kI64x2Splat: {
1016 DCHECK_EQ(1, node->InputCount());
1017 Node* input = node->InputAt(0);
1018 node->ReplaceInput(0, GetReplacementLow(input));
1019 node->AppendInput(zone(), GetReplacementHigh(input));
1020 NodeProperties::ChangeOp(node, machine()->I64x2SplatI32Pair());
1021 break;
1022 }
1023 case IrOpcode::kI64x2ExtractLane: {
1024 DCHECK_EQ(1, node->InputCount());
1025 Node* input = node->InputAt(0);
1026 int32_t lane = OpParameter<int32_t>(node->op());
1027 ReplaceNode(
1028 node, graph()->NewNode(machine()->I32x4ExtractLane(lane * 2), input),
1029 graph()->NewNode(machine()->I32x4ExtractLane(lane * 2 + 1), input));
1030 break;
1031 }
1032 case IrOpcode::kI64x2ReplaceLane: {
1033 DCHECK_EQ(2, node->InputCount());
1034 int32_t lane = OpParameter<int32_t>(node->op());
1035 Node* input = node->InputAt(1);
1036 node->ReplaceInput(1, GetReplacementLow(input));
1037 node->AppendInput(zone(), GetReplacementHigh(input));
1038 NodeProperties::ChangeOp(node, machine()->I64x2ReplaceLaneI32Pair(lane));
1039 break;
1040 }
1041
1042 default: { DefaultLowering(node); }
1043 }
1044 }
1045
LowerComparison(Node * node,const Operator * high_word_op,const Operator * low_word_op)1046 void Int64Lowering::LowerComparison(Node* node, const Operator* high_word_op,
1047 const Operator* low_word_op) {
1048 DCHECK_EQ(2, node->InputCount());
1049 Node* left = node->InputAt(0);
1050 Node* right = node->InputAt(1);
1051 Node* replacement = graph()->NewNode(
1052 machine()->Word32Or(),
1053 graph()->NewNode(high_word_op, GetReplacementHigh(left),
1054 GetReplacementHigh(right)),
1055 graph()->NewNode(
1056 machine()->Word32And(),
1057 graph()->NewNode(machine()->Word32Equal(), GetReplacementHigh(left),
1058 GetReplacementHigh(right)),
1059 graph()->NewNode(low_word_op, GetReplacementLow(left),
1060 GetReplacementLow(right))));
1061
1062 ReplaceNode(node, replacement, nullptr);
1063 }
1064
DefaultLowering(Node * node,bool low_word_only)1065 bool Int64Lowering::DefaultLowering(Node* node, bool low_word_only) {
1066 bool something_changed = false;
1067 for (int i = NodeProperties::PastValueIndex(node) - 1; i >= 0; i--) {
1068 Node* input = node->InputAt(i);
1069 if (HasReplacementLow(input)) {
1070 something_changed = true;
1071 node->ReplaceInput(i, GetReplacementLow(input));
1072 }
1073 if (!low_word_only && HasReplacementHigh(input)) {
1074 something_changed = true;
1075 node->InsertInput(zone(), i + 1, GetReplacementHigh(input));
1076 }
1077 }
1078 return something_changed;
1079 }
1080
LowerCallDescriptor(const CallDescriptor * call_descriptor)1081 const CallDescriptor* Int64Lowering::LowerCallDescriptor(
1082 const CallDescriptor* call_descriptor) {
1083 if (special_case_) {
1084 auto replacement = special_case_->replacements.find(call_descriptor);
1085 if (replacement != special_case_->replacements.end()) {
1086 return replacement->second;
1087 }
1088 }
1089 return GetI32WasmCallDescriptor(zone(), call_descriptor);
1090 }
1091
ReplaceNode(Node * old,Node * new_low,Node * new_high)1092 void Int64Lowering::ReplaceNode(Node* old, Node* new_low, Node* new_high) {
1093 // if new_low == nullptr, then also new_high == nullptr.
1094 DCHECK(new_low != nullptr || new_high == nullptr);
1095 replacements_[old->id()].low = new_low;
1096 replacements_[old->id()].high = new_high;
1097 }
1098
HasReplacementLow(Node * node)1099 bool Int64Lowering::HasReplacementLow(Node* node) {
1100 return replacements_[node->id()].low != nullptr;
1101 }
1102
GetReplacementLow(Node * node)1103 Node* Int64Lowering::GetReplacementLow(Node* node) {
1104 Node* result = replacements_[node->id()].low;
1105 DCHECK(result);
1106 return result;
1107 }
1108
HasReplacementHigh(Node * node)1109 bool Int64Lowering::HasReplacementHigh(Node* node) {
1110 return replacements_[node->id()].high != nullptr;
1111 }
1112
GetReplacementHigh(Node * node)1113 Node* Int64Lowering::GetReplacementHigh(Node* node) {
1114 Node* result = replacements_[node->id()].high;
1115 DCHECK(result);
1116 return result;
1117 }
1118
PreparePhiReplacement(Node * phi)1119 void Int64Lowering::PreparePhiReplacement(Node* phi) {
1120 MachineRepresentation rep = PhiRepresentationOf(phi->op());
1121 if (rep == MachineRepresentation::kWord64) {
1122 // We have to create the replacements for a phi node before we actually
1123 // lower the phi to break potential cycles in the graph. The replacements of
1124 // input nodes do not exist yet, so we use a placeholder node to pass the
1125 // graph verifier.
1126 int value_count = phi->op()->ValueInputCount();
1127 Node** inputs_low = zone()->NewArray<Node*>(value_count + 1);
1128 Node** inputs_high = zone()->NewArray<Node*>(value_count + 1);
1129 for (int i = 0; i < value_count; i++) {
1130 inputs_low[i] = placeholder_;
1131 inputs_high[i] = placeholder_;
1132 }
1133 inputs_low[value_count] = NodeProperties::GetControlInput(phi, 0);
1134 inputs_high[value_count] = NodeProperties::GetControlInput(phi, 0);
1135 ReplaceNode(phi,
1136 graph()->NewNode(
1137 common()->Phi(MachineRepresentation::kWord32, value_count),
1138 value_count + 1, inputs_low, false),
1139 graph()->NewNode(
1140 common()->Phi(MachineRepresentation::kWord32, value_count),
1141 value_count + 1, inputs_high, false));
1142 }
1143 }
1144
ReplaceNodeWithProjections(Node * node)1145 void Int64Lowering::ReplaceNodeWithProjections(Node* node) {
1146 DCHECK(node != nullptr);
1147 Node* low_node =
1148 graph()->NewNode(common()->Projection(0), node, graph()->start());
1149 Node* high_node =
1150 graph()->NewNode(common()->Projection(1), node, graph()->start());
1151 ReplaceNode(node, low_node, high_node);
1152 }
1153
LowerMemoryBaseAndIndex(Node * node)1154 void Int64Lowering::LowerMemoryBaseAndIndex(Node* node) {
1155 DCHECK(node != nullptr);
1156 // Low word only replacements for memory operands for 32-bit address space.
1157 Node* base = node->InputAt(0);
1158 Node* index = node->InputAt(1);
1159 if (HasReplacementLow(base)) {
1160 node->ReplaceInput(0, GetReplacementLow(base));
1161 }
1162 if (HasReplacementLow(index)) {
1163 node->ReplaceInput(1, GetReplacementLow(index));
1164 }
1165 }
1166
1167 } // namespace compiler
1168 } // namespace internal
1169 } // namespace v8
1170