Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: src/compiler/arm/instruction-selector-arm.cc

Issue 889843003: [turbofan] Don't allocate UnallocatedOperands in Zone memory during instruction selection (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/compiler/arm64/instruction-selector-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/base/bits.h" 5 #include "src/base/bits.h"
6 #include "src/compiler/instruction-selector-impl.h" 6 #include "src/compiler/instruction-selector-impl.h"
7 #include "src/compiler/node-matchers.h" 7 #include "src/compiler/node-matchers.h"
8 #include "src/compiler/node-properties.h" 8 #include "src/compiler/node-properties.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 selector->Emit(opcode, g.DefineAsRegister(node), 92 selector->Emit(opcode, g.DefineAsRegister(node),
93 g.UseRegister(node->InputAt(0)), 93 g.UseRegister(node->InputAt(0)),
94 g.UseRegister(node->InputAt(1))); 94 g.UseRegister(node->InputAt(1)));
95 } 95 }
96 96
97 97
98 template <IrOpcode::Value kOpcode, int kImmMin, int kImmMax, 98 template <IrOpcode::Value kOpcode, int kImmMin, int kImmMax,
99 AddressingMode kImmMode, AddressingMode kRegMode> 99 AddressingMode kImmMode, AddressingMode kRegMode>
100 bool TryMatchShift(InstructionSelector* selector, 100 bool TryMatchShift(InstructionSelector* selector,
101 InstructionCode* opcode_return, Node* node, 101 InstructionCode* opcode_return, Node* node,
102 InstructionOperand** value_return, 102 InstructionOperand* value_return,
103 InstructionOperand** shift_return) { 103 InstructionOperand* shift_return) {
104 ArmOperandGenerator g(selector); 104 ArmOperandGenerator g(selector);
105 if (node->opcode() == kOpcode) { 105 if (node->opcode() == kOpcode) {
106 Int32BinopMatcher m(node); 106 Int32BinopMatcher m(node);
107 *value_return = g.UseRegister(m.left().node()); 107 *value_return = g.UseRegister(m.left().node());
108 if (m.right().IsInRange(kImmMin, kImmMax)) { 108 if (m.right().IsInRange(kImmMin, kImmMax)) {
109 *opcode_return |= AddressingModeField::encode(kImmMode); 109 *opcode_return |= AddressingModeField::encode(kImmMode);
110 *shift_return = g.UseImmediate(m.right().node()); 110 *shift_return = g.UseImmediate(m.right().node());
111 } else { 111 } else {
112 *opcode_return |= AddressingModeField::encode(kRegMode); 112 *opcode_return |= AddressingModeField::encode(kRegMode);
113 *shift_return = g.UseRegister(m.right().node()); 113 *shift_return = g.UseRegister(m.right().node());
114 } 114 }
115 return true; 115 return true;
116 } 116 }
117 return false; 117 return false;
118 } 118 }
119 119
120 120
121 bool TryMatchROR(InstructionSelector* selector, InstructionCode* opcode_return, 121 bool TryMatchROR(InstructionSelector* selector, InstructionCode* opcode_return,
122 Node* node, InstructionOperand** value_return, 122 Node* node, InstructionOperand* value_return,
123 InstructionOperand** shift_return) { 123 InstructionOperand* shift_return) {
124 return TryMatchShift<IrOpcode::kWord32Ror, 1, 31, kMode_Operand2_R_ROR_I, 124 return TryMatchShift<IrOpcode::kWord32Ror, 1, 31, kMode_Operand2_R_ROR_I,
125 kMode_Operand2_R_ROR_R>(selector, opcode_return, node, 125 kMode_Operand2_R_ROR_R>(selector, opcode_return, node,
126 value_return, shift_return); 126 value_return, shift_return);
127 } 127 }
128 128
129 129
130 bool TryMatchASR(InstructionSelector* selector, InstructionCode* opcode_return, 130 bool TryMatchASR(InstructionSelector* selector, InstructionCode* opcode_return,
131 Node* node, InstructionOperand** value_return, 131 Node* node, InstructionOperand* value_return,
132 InstructionOperand** shift_return) { 132 InstructionOperand* shift_return) {
133 return TryMatchShift<IrOpcode::kWord32Sar, 1, 32, kMode_Operand2_R_ASR_I, 133 return TryMatchShift<IrOpcode::kWord32Sar, 1, 32, kMode_Operand2_R_ASR_I,
134 kMode_Operand2_R_ASR_R>(selector, opcode_return, node, 134 kMode_Operand2_R_ASR_R>(selector, opcode_return, node,
135 value_return, shift_return); 135 value_return, shift_return);
136 } 136 }
137 137
138 138
139 bool TryMatchLSL(InstructionSelector* selector, InstructionCode* opcode_return, 139 bool TryMatchLSL(InstructionSelector* selector, InstructionCode* opcode_return,
140 Node* node, InstructionOperand** value_return, 140 Node* node, InstructionOperand* value_return,
141 InstructionOperand** shift_return) { 141 InstructionOperand* shift_return) {
142 return TryMatchShift<IrOpcode::kWord32Shl, 0, 31, kMode_Operand2_R_LSL_I, 142 return TryMatchShift<IrOpcode::kWord32Shl, 0, 31, kMode_Operand2_R_LSL_I,
143 kMode_Operand2_R_LSL_R>(selector, opcode_return, node, 143 kMode_Operand2_R_LSL_R>(selector, opcode_return, node,
144 value_return, shift_return); 144 value_return, shift_return);
145 } 145 }
146 146
147 147
148 bool TryMatchLSR(InstructionSelector* selector, InstructionCode* opcode_return, 148 bool TryMatchLSR(InstructionSelector* selector, InstructionCode* opcode_return,
149 Node* node, InstructionOperand** value_return, 149 Node* node, InstructionOperand* value_return,
150 InstructionOperand** shift_return) { 150 InstructionOperand* shift_return) {
151 return TryMatchShift<IrOpcode::kWord32Shr, 1, 32, kMode_Operand2_R_LSR_I, 151 return TryMatchShift<IrOpcode::kWord32Shr, 1, 32, kMode_Operand2_R_LSR_I,
152 kMode_Operand2_R_LSR_R>(selector, opcode_return, node, 152 kMode_Operand2_R_LSR_R>(selector, opcode_return, node,
153 value_return, shift_return); 153 value_return, shift_return);
154 } 154 }
155 155
156 156
157 bool TryMatchShift(InstructionSelector* selector, 157 bool TryMatchShift(InstructionSelector* selector,
158 InstructionCode* opcode_return, Node* node, 158 InstructionCode* opcode_return, Node* node,
159 InstructionOperand** value_return, 159 InstructionOperand* value_return,
160 InstructionOperand** shift_return) { 160 InstructionOperand* shift_return) {
161 return ( 161 return (
162 TryMatchASR(selector, opcode_return, node, value_return, shift_return) || 162 TryMatchASR(selector, opcode_return, node, value_return, shift_return) ||
163 TryMatchLSL(selector, opcode_return, node, value_return, shift_return) || 163 TryMatchLSL(selector, opcode_return, node, value_return, shift_return) ||
164 TryMatchLSR(selector, opcode_return, node, value_return, shift_return) || 164 TryMatchLSR(selector, opcode_return, node, value_return, shift_return) ||
165 TryMatchROR(selector, opcode_return, node, value_return, shift_return)); 165 TryMatchROR(selector, opcode_return, node, value_return, shift_return));
166 } 166 }
167 167
168 168
169 bool TryMatchImmediateOrShift(InstructionSelector* selector, 169 bool TryMatchImmediateOrShift(InstructionSelector* selector,
170 InstructionCode* opcode_return, Node* node, 170 InstructionCode* opcode_return, Node* node,
171 size_t* input_count_return, 171 size_t* input_count_return,
172 InstructionOperand** inputs) { 172 InstructionOperand* inputs) {
173 ArmOperandGenerator g(selector); 173 ArmOperandGenerator g(selector);
174 if (g.CanBeImmediate(node, *opcode_return)) { 174 if (g.CanBeImmediate(node, *opcode_return)) {
175 *opcode_return |= AddressingModeField::encode(kMode_Operand2_I); 175 *opcode_return |= AddressingModeField::encode(kMode_Operand2_I);
176 inputs[0] = g.UseImmediate(node); 176 inputs[0] = g.UseImmediate(node);
177 *input_count_return = 1; 177 *input_count_return = 1;
178 return true; 178 return true;
179 } 179 }
180 if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) { 180 if (TryMatchShift(selector, opcode_return, node, &inputs[0], &inputs[1])) {
181 *input_count_return = 2; 181 *input_count_return = 2;
182 return true; 182 return true;
183 } 183 }
184 return false; 184 return false;
185 } 185 }
186 186
187 187
188 void VisitBinop(InstructionSelector* selector, Node* node, 188 void VisitBinop(InstructionSelector* selector, Node* node,
189 InstructionCode opcode, InstructionCode reverse_opcode, 189 InstructionCode opcode, InstructionCode reverse_opcode,
190 FlagsContinuation* cont) { 190 FlagsContinuation* cont) {
191 ArmOperandGenerator g(selector); 191 ArmOperandGenerator g(selector);
192 Int32BinopMatcher m(node); 192 Int32BinopMatcher m(node);
193 InstructionOperand* inputs[5]; 193 InstructionOperand inputs[5];
194 size_t input_count = 0; 194 size_t input_count = 0;
195 InstructionOperand* outputs[2]; 195 InstructionOperand outputs[2];
196 size_t output_count = 0; 196 size_t output_count = 0;
197 197
198 if (m.left().node() == m.right().node()) { 198 if (m.left().node() == m.right().node()) {
199 // If both inputs refer to the same operand, enforce allocating a register 199 // If both inputs refer to the same operand, enforce allocating a register
200 // for both of them to ensure that we don't end up generating code like 200 // for both of them to ensure that we don't end up generating code like
201 // this: 201 // this:
202 // 202 //
203 // mov r0, r1, asr #16 203 // mov r0, r1, asr #16
204 // adds r0, r0, r1, asr #16 204 // adds r0, r0, r1, asr #16
205 // bvs label 205 // bvs label
206 InstructionOperand* const input = g.UseRegister(m.left().node()); 206 InstructionOperand const input = g.UseRegister(m.left().node());
207 opcode |= AddressingModeField::encode(kMode_Operand2_R); 207 opcode |= AddressingModeField::encode(kMode_Operand2_R);
208 inputs[input_count++] = input; 208 inputs[input_count++] = input;
209 inputs[input_count++] = input; 209 inputs[input_count++] = input;
210 } else if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), 210 } else if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
211 &input_count, &inputs[1])) { 211 &input_count, &inputs[1])) {
212 inputs[0] = g.UseRegister(m.left().node()); 212 inputs[0] = g.UseRegister(m.left().node());
213 input_count++; 213 input_count++;
214 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode, 214 } else if (TryMatchImmediateOrShift(selector, &reverse_opcode,
215 m.left().node(), &input_count, 215 m.left().node(), &input_count,
216 &inputs[1])) { 216 &inputs[1])) {
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 Node* index = node->InputAt(1); 302 Node* index = node->InputAt(1);
303 Node* value = node->InputAt(2); 303 Node* value = node->InputAt(2);
304 304
305 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); 305 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
306 MachineType rep = RepresentationOf(store_rep.machine_type()); 306 MachineType rep = RepresentationOf(store_rep.machine_type());
307 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { 307 if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
308 DCHECK(rep == kRepTagged); 308 DCHECK(rep == kRepTagged);
309 // TODO(dcarney): refactor RecordWrite function to take temp registers 309 // TODO(dcarney): refactor RecordWrite function to take temp registers
310 // and pass them here instead of using fixed regs 310 // and pass them here instead of using fixed regs
311 // TODO(dcarney): handle immediate indices. 311 // TODO(dcarney): handle immediate indices.
312 InstructionOperand* temps[] = {g.TempRegister(r5), g.TempRegister(r6)}; 312 InstructionOperand temps[] = {g.TempRegister(r5), g.TempRegister(r6)};
313 Emit(kArmStoreWriteBarrier, NULL, g.UseFixed(base, r4), 313 Emit(kArmStoreWriteBarrier, g.NoOutput(), g.UseFixed(base, r4),
314 g.UseFixed(index, r5), g.UseFixed(value, r6), arraysize(temps), 314 g.UseFixed(index, r5), g.UseFixed(value, r6), arraysize(temps), temps);
315 temps);
316 return; 315 return;
317 } 316 }
318 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); 317 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
319 318
320 ArchOpcode opcode; 319 ArchOpcode opcode;
321 switch (rep) { 320 switch (rep) {
322 case kRepFloat32: 321 case kRepFloat32:
323 opcode = kArmVstrF32; 322 opcode = kArmVstrF32;
324 break; 323 break;
325 case kRepFloat64: 324 case kRepFloat64:
326 opcode = kArmVstrF64; 325 opcode = kArmVstrF64;
327 break; 326 break;
328 case kRepBit: // Fall through. 327 case kRepBit: // Fall through.
329 case kRepWord8: 328 case kRepWord8:
330 opcode = kArmStrb; 329 opcode = kArmStrb;
331 break; 330 break;
332 case kRepWord16: 331 case kRepWord16:
333 opcode = kArmStrh; 332 opcode = kArmStrh;
334 break; 333 break;
335 case kRepTagged: // Fall through. 334 case kRepTagged: // Fall through.
336 case kRepWord32: 335 case kRepWord32:
337 opcode = kArmStr; 336 opcode = kArmStr;
338 break; 337 break;
339 default: 338 default:
340 UNREACHABLE(); 339 UNREACHABLE();
341 return; 340 return;
342 } 341 }
343 342
344 if (g.CanBeImmediate(index, opcode)) { 343 if (g.CanBeImmediate(index, opcode)) {
345 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), NULL, 344 Emit(opcode | AddressingModeField::encode(kMode_Offset_RI), g.NoOutput(),
346 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); 345 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value));
347 } else { 346 } else {
348 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), NULL, 347 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), g.NoOutput(),
349 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); 348 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value));
350 } 349 }
351 } 350 }
352 351
353 352
354 void InstructionSelector::VisitCheckedLoad(Node* node) { 353 void InstructionSelector::VisitCheckedLoad(Node* node) {
355 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); 354 MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
356 MachineType typ = TypeOf(OpParameter<MachineType>(node)); 355 MachineType typ = TypeOf(OpParameter<MachineType>(node));
357 ArmOperandGenerator g(this); 356 ArmOperandGenerator g(this);
358 Node* const buffer = node->InputAt(0); 357 Node* const buffer = node->InputAt(0);
(...skipping 13 matching lines...) Expand all
372 case kRepFloat32: 371 case kRepFloat32:
373 opcode = kCheckedLoadFloat32; 372 opcode = kCheckedLoadFloat32;
374 break; 373 break;
375 case kRepFloat64: 374 case kRepFloat64:
376 opcode = kCheckedLoadFloat64; 375 opcode = kCheckedLoadFloat64;
377 break; 376 break;
378 default: 377 default:
379 UNREACHABLE(); 378 UNREACHABLE();
380 return; 379 return;
381 } 380 }
382 InstructionOperand* offset_operand = g.UseRegister(offset); 381 InstructionOperand offset_operand = g.UseRegister(offset);
383 InstructionOperand* length_operand = g.CanBeImmediate(length, kArmCmp) 382 InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp)
384 ? g.UseImmediate(length) 383 ? g.UseImmediate(length)
385 : g.UseRegister(length); 384 : g.UseRegister(length);
386 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), 385 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR),
387 g.DefineAsRegister(node), offset_operand, length_operand, 386 g.DefineAsRegister(node), offset_operand, length_operand,
388 g.UseRegister(buffer), offset_operand); 387 g.UseRegister(buffer), offset_operand);
389 } 388 }
390 389
391 390
392 void InstructionSelector::VisitCheckedStore(Node* node) { 391 void InstructionSelector::VisitCheckedStore(Node* node) {
393 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); 392 MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
394 ArmOperandGenerator g(this); 393 ArmOperandGenerator g(this);
395 Node* const buffer = node->InputAt(0); 394 Node* const buffer = node->InputAt(0);
(...skipping 14 matching lines...) Expand all
410 case kRepFloat32: 409 case kRepFloat32:
411 opcode = kCheckedStoreFloat32; 410 opcode = kCheckedStoreFloat32;
412 break; 411 break;
413 case kRepFloat64: 412 case kRepFloat64:
414 opcode = kCheckedStoreFloat64; 413 opcode = kCheckedStoreFloat64;
415 break; 414 break;
416 default: 415 default:
417 UNREACHABLE(); 416 UNREACHABLE();
418 return; 417 return;
419 } 418 }
420 InstructionOperand* offset_operand = g.UseRegister(offset); 419 InstructionOperand offset_operand = g.UseRegister(offset);
421 InstructionOperand* length_operand = g.CanBeImmediate(length, kArmCmp) 420 InstructionOperand length_operand = g.CanBeImmediate(length, kArmCmp)
422 ? g.UseImmediate(length) 421 ? g.UseImmediate(length)
423 : g.UseRegister(length); 422 : g.UseRegister(length);
424 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), nullptr, 423 Emit(opcode | AddressingModeField::encode(kMode_Offset_RR), g.NoOutput(),
425 offset_operand, length_operand, g.UseRegister(value), 424 offset_operand, length_operand, g.UseRegister(value),
426 g.UseRegister(buffer), offset_operand); 425 g.UseRegister(buffer), offset_operand);
427 } 426 }
428 427
429 428
430 namespace { 429 namespace {
431 430
432 void EmitBic(InstructionSelector* selector, Node* node, Node* left, 431 void EmitBic(InstructionSelector* selector, Node* node, Node* left,
433 Node* right) { 432 Node* right) {
434 ArmOperandGenerator g(selector); 433 ArmOperandGenerator g(selector);
435 InstructionCode opcode = kArmBic; 434 InstructionCode opcode = kArmBic;
436 InstructionOperand* value_operand; 435 InstructionOperand value_operand;
437 InstructionOperand* shift_operand; 436 InstructionOperand shift_operand;
438 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) { 437 if (TryMatchShift(selector, &opcode, right, &value_operand, &shift_operand)) {
439 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left), 438 selector->Emit(opcode, g.DefineAsRegister(node), g.UseRegister(left),
440 value_operand, shift_operand); 439 value_operand, shift_operand);
441 return; 440 return;
442 } 441 }
443 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), 442 selector->Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
444 g.DefineAsRegister(node), g.UseRegister(left), 443 g.DefineAsRegister(node), g.UseRegister(left),
445 g.UseRegister(right)); 444 g.UseRegister(right));
446 } 445 }
447 446
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 void InstructionSelector::VisitWord32Or(Node* node) { 527 void InstructionSelector::VisitWord32Or(Node* node) {
529 VisitBinop(this, node, kArmOrr, kArmOrr); 528 VisitBinop(this, node, kArmOrr, kArmOrr);
530 } 529 }
531 530
532 531
533 void InstructionSelector::VisitWord32Xor(Node* node) { 532 void InstructionSelector::VisitWord32Xor(Node* node) {
534 ArmOperandGenerator g(this); 533 ArmOperandGenerator g(this);
535 Int32BinopMatcher m(node); 534 Int32BinopMatcher m(node);
536 if (m.right().Is(-1)) { 535 if (m.right().Is(-1)) {
537 InstructionCode opcode = kArmMvn; 536 InstructionCode opcode = kArmMvn;
538 InstructionOperand* value_operand; 537 InstructionOperand value_operand;
539 InstructionOperand* shift_operand; 538 InstructionOperand shift_operand;
540 if (TryMatchShift(this, &opcode, m.left().node(), &value_operand, 539 if (TryMatchShift(this, &opcode, m.left().node(), &value_operand,
541 &shift_operand)) { 540 &shift_operand)) {
542 Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand); 541 Emit(opcode, g.DefineAsRegister(node), value_operand, shift_operand);
543 return; 542 return;
544 } 543 }
545 Emit(opcode | AddressingModeField::encode(kMode_Operand2_R), 544 Emit(opcode | AddressingModeField::encode(kMode_Operand2_R),
546 g.DefineAsRegister(node), g.UseRegister(m.left().node())); 545 g.DefineAsRegister(node), g.UseRegister(m.left().node()));
547 return; 546 return;
548 } 547 }
549 VisitBinop(this, node, kArmEor, kArmEor); 548 VisitBinop(this, node, kArmEor, kArmEor);
550 } 549 }
551 550
552 551
553 namespace { 552 namespace {
554 553
555 template <typename TryMatchShift> 554 template <typename TryMatchShift>
556 void VisitShift(InstructionSelector* selector, Node* node, 555 void VisitShift(InstructionSelector* selector, Node* node,
557 TryMatchShift try_match_shift, FlagsContinuation* cont) { 556 TryMatchShift try_match_shift, FlagsContinuation* cont) {
558 ArmOperandGenerator g(selector); 557 ArmOperandGenerator g(selector);
559 InstructionCode opcode = kArmMov; 558 InstructionCode opcode = kArmMov;
560 InstructionOperand* inputs[4]; 559 InstructionOperand inputs[4];
561 size_t input_count = 2; 560 size_t input_count = 2;
562 InstructionOperand* outputs[2]; 561 InstructionOperand outputs[2];
563 size_t output_count = 0; 562 size_t output_count = 0;
564 563
565 CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1])); 564 CHECK(try_match_shift(selector, &opcode, node, &inputs[0], &inputs[1]));
566 565
567 if (cont->IsBranch()) { 566 if (cont->IsBranch()) {
568 inputs[input_count++] = g.Label(cont->true_block()); 567 inputs[input_count++] = g.Label(cont->true_block());
569 inputs[input_count++] = g.Label(cont->false_block()); 568 inputs[input_count++] = g.Label(cont->false_block());
570 } 569 }
571 570
572 outputs[output_count++] = g.DefineAsRegister(node); 571 outputs[output_count++] = g.DefineAsRegister(node);
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
802 801
803 void InstructionSelector::VisitInt32MulHigh(Node* node) { 802 void InstructionSelector::VisitInt32MulHigh(Node* node) {
804 ArmOperandGenerator g(this); 803 ArmOperandGenerator g(this);
805 Emit(kArmSmmul, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)), 804 Emit(kArmSmmul, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0)),
806 g.UseRegister(node->InputAt(1))); 805 g.UseRegister(node->InputAt(1)));
807 } 806 }
808 807
809 808
810 void InstructionSelector::VisitUint32MulHigh(Node* node) { 809 void InstructionSelector::VisitUint32MulHigh(Node* node) {
811 ArmOperandGenerator g(this); 810 ArmOperandGenerator g(this);
812 InstructionOperand* outputs[] = {g.TempRegister(), g.DefineAsRegister(node)}; 811 InstructionOperand outputs[] = {g.TempRegister(), g.DefineAsRegister(node)};
813 InstructionOperand* inputs[] = {g.UseRegister(node->InputAt(0)), 812 InstructionOperand inputs[] = {g.UseRegister(node->InputAt(0)),
814 g.UseRegister(node->InputAt(1))}; 813 g.UseRegister(node->InputAt(1))};
815 Emit(kArmUmull, arraysize(outputs), outputs, arraysize(inputs), inputs); 814 Emit(kArmUmull, arraysize(outputs), outputs, arraysize(inputs), inputs);
816 } 815 }
817 816
818 817
819 static void EmitDiv(InstructionSelector* selector, ArchOpcode div_opcode, 818 static void EmitDiv(InstructionSelector* selector, ArchOpcode div_opcode,
820 ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode, 819 ArchOpcode f64i32_opcode, ArchOpcode i32f64_opcode,
821 InstructionOperand* result_operand, 820 InstructionOperand result_operand,
822 InstructionOperand* left_operand, 821 InstructionOperand left_operand,
823 InstructionOperand* right_operand) { 822 InstructionOperand right_operand) {
824 ArmOperandGenerator g(selector); 823 ArmOperandGenerator g(selector);
825 if (selector->IsSupported(SUDIV)) { 824 if (selector->IsSupported(SUDIV)) {
826 selector->Emit(div_opcode, result_operand, left_operand, right_operand); 825 selector->Emit(div_opcode, result_operand, left_operand, right_operand);
827 return; 826 return;
828 } 827 }
829 InstructionOperand* left_double_operand = g.TempDoubleRegister(); 828 InstructionOperand left_double_operand = g.TempDoubleRegister();
830 InstructionOperand* right_double_operand = g.TempDoubleRegister(); 829 InstructionOperand right_double_operand = g.TempDoubleRegister();
831 InstructionOperand* result_double_operand = g.TempDoubleRegister(); 830 InstructionOperand result_double_operand = g.TempDoubleRegister();
832 selector->Emit(f64i32_opcode, left_double_operand, left_operand); 831 selector->Emit(f64i32_opcode, left_double_operand, left_operand);
833 selector->Emit(f64i32_opcode, right_double_operand, right_operand); 832 selector->Emit(f64i32_opcode, right_double_operand, right_operand);
834 selector->Emit(kArmVdivF64, result_double_operand, left_double_operand, 833 selector->Emit(kArmVdivF64, result_double_operand, left_double_operand,
835 right_double_operand); 834 right_double_operand);
836 selector->Emit(i32f64_opcode, result_operand, result_double_operand); 835 selector->Emit(i32f64_opcode, result_operand, result_double_operand);
837 } 836 }
838 837
839 838
840 static void VisitDiv(InstructionSelector* selector, Node* node, 839 static void VisitDiv(InstructionSelector* selector, Node* node,
841 ArchOpcode div_opcode, ArchOpcode f64i32_opcode, 840 ArchOpcode div_opcode, ArchOpcode f64i32_opcode,
(...skipping 14 matching lines...) Expand all
856 void InstructionSelector::VisitUint32Div(Node* node) { 855 void InstructionSelector::VisitUint32Div(Node* node) {
857 VisitDiv(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64); 856 VisitDiv(this, node, kArmUdiv, kArmVcvtF64U32, kArmVcvtU32F64);
858 } 857 }
859 858
860 859
861 static void VisitMod(InstructionSelector* selector, Node* node, 860 static void VisitMod(InstructionSelector* selector, Node* node,
862 ArchOpcode div_opcode, ArchOpcode f64i32_opcode, 861 ArchOpcode div_opcode, ArchOpcode f64i32_opcode,
863 ArchOpcode i32f64_opcode) { 862 ArchOpcode i32f64_opcode) {
864 ArmOperandGenerator g(selector); 863 ArmOperandGenerator g(selector);
865 Int32BinopMatcher m(node); 864 Int32BinopMatcher m(node);
866 InstructionOperand* div_operand = g.TempRegister(); 865 InstructionOperand div_operand = g.TempRegister();
867 InstructionOperand* result_operand = g.DefineAsRegister(node); 866 InstructionOperand result_operand = g.DefineAsRegister(node);
868 InstructionOperand* left_operand = g.UseRegister(m.left().node()); 867 InstructionOperand left_operand = g.UseRegister(m.left().node());
869 InstructionOperand* right_operand = g.UseRegister(m.right().node()); 868 InstructionOperand right_operand = g.UseRegister(m.right().node());
870 EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode, div_operand, 869 EmitDiv(selector, div_opcode, f64i32_opcode, i32f64_opcode, div_operand,
871 left_operand, right_operand); 870 left_operand, right_operand);
872 if (selector->IsSupported(MLS)) { 871 if (selector->IsSupported(MLS)) {
873 selector->Emit(kArmMls, result_operand, div_operand, right_operand, 872 selector->Emit(kArmMls, result_operand, div_operand, right_operand,
874 left_operand); 873 left_operand);
875 return; 874 return;
876 } 875 }
877 InstructionOperand* mul_operand = g.TempRegister(); 876 InstructionOperand mul_operand = g.TempRegister();
878 selector->Emit(kArmMul, mul_operand, div_operand, right_operand); 877 selector->Emit(kArmMul, mul_operand, div_operand, right_operand);
879 selector->Emit(kArmSub, result_operand, left_operand, mul_operand); 878 selector->Emit(kArmSub, result_operand, left_operand, mul_operand);
880 } 879 }
881 880
882 881
883 void InstructionSelector::VisitInt32Mod(Node* node) { 882 void InstructionSelector::VisitInt32Mod(Node* node) {
884 VisitMod(this, node, kArmSdiv, kArmVcvtF64S32, kArmVcvtS32F64); 883 VisitMod(this, node, kArmSdiv, kArmVcvtF64S32, kArmVcvtS32F64);
885 } 884 }
886 885
887 886
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1034 // Compute InstructionOperands for inputs and outputs. 1033 // Compute InstructionOperands for inputs and outputs.
1035 // TODO(turbofan): on ARM64 it's probably better to use the code object in a 1034 // TODO(turbofan): on ARM64 it's probably better to use the code object in a
1036 // register if there are multiple uses of it. Improve constant pool and the 1035 // register if there are multiple uses of it. Improve constant pool and the
1037 // heuristics in the register allocator for where to emit constants. 1036 // heuristics in the register allocator for where to emit constants.
1038 InitializeCallBuffer(node, &buffer, true, false); 1037 InitializeCallBuffer(node, &buffer, true, false);
1039 1038
1040 // TODO(dcarney): might be possible to use claim/poke instead 1039 // TODO(dcarney): might be possible to use claim/poke instead
1041 // Push any stack arguments. 1040 // Push any stack arguments.
1042 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); 1041 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
1043 ++i) { 1042 ++i) {
1044 Emit(kArmPush, nullptr, g.UseRegister(*i)); 1043 Emit(kArmPush, g.NoOutput(), g.UseRegister(*i));
1045 } 1044 }
1046 1045
1047 // Select the appropriate opcode based on the call type. 1046 // Select the appropriate opcode based on the call type.
1048 InstructionCode opcode; 1047 InstructionCode opcode;
1049 switch (descriptor->kind()) { 1048 switch (descriptor->kind()) {
1050 case CallDescriptor::kCallCodeObject: { 1049 case CallDescriptor::kCallCodeObject: {
1051 opcode = kArchCallCodeObject; 1050 opcode = kArchCallCodeObject;
1052 break; 1051 break;
1053 } 1052 }
1054 case CallDescriptor::kCallJSFunction: 1053 case CallDescriptor::kCallJSFunction:
1055 opcode = kArchCallJSFunction; 1054 opcode = kArchCallJSFunction;
1056 break; 1055 break;
1057 default: 1056 default:
1058 UNREACHABLE(); 1057 UNREACHABLE();
1059 return; 1058 return;
1060 } 1059 }
1061 opcode |= MiscField::encode(descriptor->flags()); 1060 opcode |= MiscField::encode(descriptor->flags());
1062 1061
1063 // Emit the call instruction. 1062 // Emit the call instruction.
1064 InstructionOperand** first_output = 1063 InstructionOperand* first_output =
1065 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; 1064 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
1066 Instruction* call_instr = 1065 Instruction* call_instr =
1067 Emit(opcode, buffer.outputs.size(), first_output, 1066 Emit(opcode, buffer.outputs.size(), first_output,
1068 buffer.instruction_args.size(), &buffer.instruction_args.front()); 1067 buffer.instruction_args.size(), &buffer.instruction_args.front());
1069 call_instr->MarkAsCall(); 1068 call_instr->MarkAsCall();
1070 } 1069 }
1071 1070
1072 1071
1073 namespace { 1072 namespace {
1074 1073
1075 // Shared routine for multiple float compare operations. 1074 // Shared routine for multiple float compare operations.
1076 void VisitFloat64Compare(InstructionSelector* selector, Node* node, 1075 void VisitFloat64Compare(InstructionSelector* selector, Node* node,
1077 FlagsContinuation* cont) { 1076 FlagsContinuation* cont) {
1078 ArmOperandGenerator g(selector); 1077 ArmOperandGenerator g(selector);
1079 Float64BinopMatcher m(node); 1078 Float64BinopMatcher m(node);
1080 InstructionOperand* rhs = m.right().Is(0.0) ? g.UseImmediate(m.right().node()) 1079 InstructionOperand rhs = m.right().Is(0.0) ? g.UseImmediate(m.right().node())
1081 : g.UseRegister(m.right().node()); 1080 : g.UseRegister(m.right().node());
1082 if (cont->IsBranch()) { 1081 if (cont->IsBranch()) {
1083 selector->Emit(cont->Encode(kArmVcmpF64), nullptr, 1082 selector->Emit(cont->Encode(kArmVcmpF64), g.NoOutput(),
1084 g.UseRegister(m.left().node()), rhs, 1083 g.UseRegister(m.left().node()), rhs,
1085 g.Label(cont->true_block()), 1084 g.Label(cont->true_block()),
1086 g.Label(cont->false_block()))->MarkAsControl(); 1085 g.Label(cont->false_block()))->MarkAsControl();
1087 } else { 1086 } else {
1088 DCHECK(cont->IsSet()); 1087 DCHECK(cont->IsSet());
1089 selector->Emit(cont->Encode(kArmVcmpF64), 1088 selector->Emit(cont->Encode(kArmVcmpF64),
1090 g.DefineAsRegister(cont->result()), 1089 g.DefineAsRegister(cont->result()),
1091 g.UseRegister(m.left().node()), rhs); 1090 g.UseRegister(m.left().node()), rhs);
1092 } 1091 }
1093 } 1092 }
1094 1093
1095 1094
1096 // Shared routine for multiple word compare operations. 1095 // Shared routine for multiple word compare operations.
1097 void VisitWordCompare(InstructionSelector* selector, Node* node, 1096 void VisitWordCompare(InstructionSelector* selector, Node* node,
1098 InstructionCode opcode, FlagsContinuation* cont) { 1097 InstructionCode opcode, FlagsContinuation* cont) {
1099 ArmOperandGenerator g(selector); 1098 ArmOperandGenerator g(selector);
1100 Int32BinopMatcher m(node); 1099 Int32BinopMatcher m(node);
1101 InstructionOperand* inputs[5]; 1100 InstructionOperand inputs[5];
1102 size_t input_count = 0; 1101 size_t input_count = 0;
1103 InstructionOperand* outputs[1]; 1102 InstructionOperand outputs[1];
1104 size_t output_count = 0; 1103 size_t output_count = 0;
1105 1104
1106 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(), 1105 if (TryMatchImmediateOrShift(selector, &opcode, m.right().node(),
1107 &input_count, &inputs[1])) { 1106 &input_count, &inputs[1])) {
1108 inputs[0] = g.UseRegister(m.left().node()); 1107 inputs[0] = g.UseRegister(m.left().node());
1109 input_count++; 1108 input_count++;
1110 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(), 1109 } else if (TryMatchImmediateOrShift(selector, &opcode, m.left().node(),
1111 &input_count, &inputs[1])) { 1110 &input_count, &inputs[1])) {
1112 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute(); 1111 if (!node->op()->HasProperty(Operator::kCommutative)) cont->Commute();
1113 inputs[0] = g.UseRegister(m.right().node()); 1112 inputs[0] = g.UseRegister(m.right().node());
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 default: 1226 default:
1228 break; 1227 break;
1229 } 1228 }
1230 break; 1229 break;
1231 } 1230 }
1232 1231
1233 // Continuation could not be combined with a compare, emit compare against 0. 1232 // Continuation could not be combined with a compare, emit compare against 0.
1234 ArmOperandGenerator g(selector); 1233 ArmOperandGenerator g(selector);
1235 InstructionCode const opcode = 1234 InstructionCode const opcode =
1236 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R); 1235 cont->Encode(kArmTst) | AddressingModeField::encode(kMode_Operand2_R);
1237 InstructionOperand* const value_operand = g.UseRegister(value); 1236 InstructionOperand const value_operand = g.UseRegister(value);
1238 if (cont->IsBranch()) { 1237 if (cont->IsBranch()) {
1239 selector->Emit(opcode, nullptr, value_operand, value_operand, 1238 selector->Emit(opcode, g.NoOutput(), value_operand, value_operand,
1240 g.Label(cont->true_block()), 1239 g.Label(cont->true_block()),
1241 g.Label(cont->false_block()))->MarkAsControl(); 1240 g.Label(cont->false_block()))->MarkAsControl();
1242 } else { 1241 } else {
1243 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, 1242 selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand,
1244 value_operand); 1243 value_operand);
1245 } 1244 }
1246 } 1245 }
1247 1246
1248 } // namespace 1247 } // namespace
1249 1248
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1339 MachineOperatorBuilder::kFloat64Ceil | 1338 MachineOperatorBuilder::kFloat64Ceil |
1340 MachineOperatorBuilder::kFloat64RoundTruncate | 1339 MachineOperatorBuilder::kFloat64RoundTruncate |
1341 MachineOperatorBuilder::kFloat64RoundTiesAway; 1340 MachineOperatorBuilder::kFloat64RoundTiesAway;
1342 } 1341 }
1343 return flags; 1342 return flags;
1344 } 1343 }
1345 1344
1346 } // namespace compiler 1345 } // namespace compiler
1347 } // namespace internal 1346 } // namespace internal
1348 } // namespace v8 1347 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/arm64/instruction-selector-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698