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

Side by Side Diff: src/compiler/ia32/instruction-selector-ia32.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 | « src/compiler/arm64/instruction-selector-arm64.cc ('k') | src/compiler/instruction.h » ('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/compiler/instruction-selector-impl.h" 5 #include "src/compiler/instruction-selector-impl.h"
6 #include "src/compiler/node-matchers.h" 6 #include "src/compiler/node-matchers.h"
7 #include "src/compiler/node-properties.h" 7 #include "src/compiler/node-properties.h"
8 8
9 namespace v8 { 9 namespace v8 {
10 namespace internal { 10 namespace internal {
11 namespace compiler { 11 namespace compiler {
12 12
13 // Adds IA32-specific methods for generating operands. 13 // Adds IA32-specific methods for generating operands.
14 class IA32OperandGenerator FINAL : public OperandGenerator { 14 class IA32OperandGenerator FINAL : public OperandGenerator {
15 public: 15 public:
16 explicit IA32OperandGenerator(InstructionSelector* selector) 16 explicit IA32OperandGenerator(InstructionSelector* selector)
17 : OperandGenerator(selector) {} 17 : OperandGenerator(selector) {}
18 18
19 InstructionOperand* UseByteRegister(Node* node) { 19 InstructionOperand UseByteRegister(Node* node) {
20 // TODO(dcarney): relax constraint. 20 // TODO(dcarney): relax constraint.
21 return UseFixed(node, edx); 21 return UseFixed(node, edx);
22 } 22 }
23 23
24 bool CanBeImmediate(Node* node) { 24 bool CanBeImmediate(Node* node) {
25 switch (node->opcode()) { 25 switch (node->opcode()) {
26 case IrOpcode::kInt32Constant: 26 case IrOpcode::kInt32Constant:
27 case IrOpcode::kNumberConstant: 27 case IrOpcode::kNumberConstant:
28 case IrOpcode::kExternalConstant: 28 case IrOpcode::kExternalConstant:
29 return true; 29 return true;
30 case IrOpcode::kHeapConstant: { 30 case IrOpcode::kHeapConstant: {
31 // Constants in new space cannot be used as immediates in V8 because 31 // Constants in new space cannot be used as immediates in V8 because
32 // the GC does not scan code objects when collecting the new generation. 32 // the GC does not scan code objects when collecting the new generation.
33 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node); 33 Unique<HeapObject> value = OpParameter<Unique<HeapObject> >(node);
34 Isolate* isolate = value.handle()->GetIsolate(); 34 Isolate* isolate = value.handle()->GetIsolate();
35 return !isolate->heap()->InNewSpace(*value.handle()); 35 return !isolate->heap()->InNewSpace(*value.handle());
36 } 36 }
37 default: 37 default:
38 return false; 38 return false;
39 } 39 }
40 } 40 }
41 41
42 AddressingMode GenerateMemoryOperandInputs(Node* index, int scale, Node* base, 42 AddressingMode GenerateMemoryOperandInputs(Node* index, int scale, Node* base,
43 Node* displacement_node, 43 Node* displacement_node,
44 InstructionOperand* inputs[], 44 InstructionOperand inputs[],
45 size_t* input_count) { 45 size_t* input_count) {
46 AddressingMode mode = kMode_MRI; 46 AddressingMode mode = kMode_MRI;
47 int32_t displacement = (displacement_node == NULL) 47 int32_t displacement = (displacement_node == NULL)
48 ? 0 48 ? 0
49 : OpParameter<int32_t>(displacement_node); 49 : OpParameter<int32_t>(displacement_node);
50 if (base != NULL) { 50 if (base != NULL) {
51 if (base->opcode() == IrOpcode::kInt32Constant) { 51 if (base->opcode() == IrOpcode::kInt32Constant) {
52 displacement += OpParameter<int32_t>(base); 52 displacement += OpParameter<int32_t>(base);
53 base = NULL; 53 base = NULL;
54 } 54 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 } 92 }
93 } else { 93 } else {
94 inputs[(*input_count)++] = TempImmediate(displacement); 94 inputs[(*input_count)++] = TempImmediate(displacement);
95 return kMode_MI; 95 return kMode_MI;
96 } 96 }
97 } 97 }
98 return mode; 98 return mode;
99 } 99 }
100 100
101 AddressingMode GetEffectiveAddressMemoryOperand(Node* node, 101 AddressingMode GetEffectiveAddressMemoryOperand(Node* node,
102 InstructionOperand* inputs[], 102 InstructionOperand inputs[],
103 size_t* input_count) { 103 size_t* input_count) {
104 BaseWithIndexAndDisplacement32Matcher m(node, true); 104 BaseWithIndexAndDisplacement32Matcher m(node, true);
105 DCHECK(m.matches()); 105 DCHECK(m.matches());
106 if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) { 106 if ((m.displacement() == NULL || CanBeImmediate(m.displacement()))) {
107 return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(), 107 return GenerateMemoryOperandInputs(m.index(), m.scale(), m.base(),
108 m.displacement(), inputs, input_count); 108 m.displacement(), inputs, input_count);
109 } else { 109 } else {
110 inputs[(*input_count)++] = UseRegister(node->InputAt(0)); 110 inputs[(*input_count)++] = UseRegister(node->InputAt(0));
111 inputs[(*input_count)++] = UseRegister(node->InputAt(1)); 111 inputs[(*input_count)++] = UseRegister(node->InputAt(1));
112 return kMode_MR1; 112 return kMode_MR1;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 case kRepTagged: // Fall through. 150 case kRepTagged: // Fall through.
151 case kRepWord32: 151 case kRepWord32:
152 opcode = kIA32Movl; 152 opcode = kIA32Movl;
153 break; 153 break;
154 default: 154 default:
155 UNREACHABLE(); 155 UNREACHABLE();
156 return; 156 return;
157 } 157 }
158 158
159 IA32OperandGenerator g(this); 159 IA32OperandGenerator g(this);
160 InstructionOperand* outputs[1]; 160 InstructionOperand outputs[1];
161 outputs[0] = g.DefineAsRegister(node); 161 outputs[0] = g.DefineAsRegister(node);
162 InstructionOperand* inputs[3]; 162 InstructionOperand inputs[3];
163 size_t input_count = 0; 163 size_t input_count = 0;
164 AddressingMode mode = 164 AddressingMode mode =
165 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); 165 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
166 InstructionCode code = opcode | AddressingModeField::encode(mode); 166 InstructionCode code = opcode | AddressingModeField::encode(mode);
167 Emit(code, 1, outputs, input_count, inputs); 167 Emit(code, 1, outputs, input_count, inputs);
168 } 168 }
169 169
170 170
171 void InstructionSelector::VisitStore(Node* node) { 171 void InstructionSelector::VisitStore(Node* node) {
172 IA32OperandGenerator g(this); 172 IA32OperandGenerator g(this);
173 Node* base = node->InputAt(0); 173 Node* base = node->InputAt(0);
174 Node* index = node->InputAt(1); 174 Node* index = node->InputAt(1);
175 Node* value = node->InputAt(2); 175 Node* value = node->InputAt(2);
176 176
177 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node); 177 StoreRepresentation store_rep = OpParameter<StoreRepresentation>(node);
178 MachineType rep = RepresentationOf(store_rep.machine_type()); 178 MachineType rep = RepresentationOf(store_rep.machine_type());
179 if (store_rep.write_barrier_kind() == kFullWriteBarrier) { 179 if (store_rep.write_barrier_kind() == kFullWriteBarrier) {
180 DCHECK_EQ(kRepTagged, rep); 180 DCHECK_EQ(kRepTagged, rep);
181 // TODO(dcarney): refactor RecordWrite function to take temp registers 181 // TODO(dcarney): refactor RecordWrite function to take temp registers
182 // and pass them here instead of using fixed regs 182 // and pass them here instead of using fixed regs
183 // TODO(dcarney): handle immediate indices. 183 // TODO(dcarney): handle immediate indices.
184 InstructionOperand* temps[] = {g.TempRegister(ecx), g.TempRegister(edx)}; 184 InstructionOperand temps[] = {g.TempRegister(ecx), g.TempRegister(edx)};
185 Emit(kIA32StoreWriteBarrier, NULL, g.UseFixed(base, ebx), 185 Emit(kIA32StoreWriteBarrier, g.NoOutput(), g.UseFixed(base, ebx),
186 g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps), 186 g.UseFixed(index, ecx), g.UseFixed(value, edx), arraysize(temps),
187 temps); 187 temps);
188 return; 188 return;
189 } 189 }
190 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind()); 190 DCHECK_EQ(kNoWriteBarrier, store_rep.write_barrier_kind());
191 191
192 ArchOpcode opcode; 192 ArchOpcode opcode;
193 switch (rep) { 193 switch (rep) {
194 case kRepFloat32: 194 case kRepFloat32:
195 opcode = kIA32Movss; 195 opcode = kIA32Movss;
(...skipping 10 matching lines...) Expand all
206 break; 206 break;
207 case kRepTagged: // Fall through. 207 case kRepTagged: // Fall through.
208 case kRepWord32: 208 case kRepWord32:
209 opcode = kIA32Movl; 209 opcode = kIA32Movl;
210 break; 210 break;
211 default: 211 default:
212 UNREACHABLE(); 212 UNREACHABLE();
213 return; 213 return;
214 } 214 }
215 215
216 InstructionOperand* val; 216 InstructionOperand val;
217 if (g.CanBeImmediate(value)) { 217 if (g.CanBeImmediate(value)) {
218 val = g.UseImmediate(value); 218 val = g.UseImmediate(value);
219 } else if (rep == kRepWord8 || rep == kRepBit) { 219 } else if (rep == kRepWord8 || rep == kRepBit) {
220 val = g.UseByteRegister(value); 220 val = g.UseByteRegister(value);
221 } else { 221 } else {
222 val = g.UseRegister(value); 222 val = g.UseRegister(value);
223 } 223 }
224 224
225 InstructionOperand* inputs[4]; 225 InstructionOperand inputs[4];
226 size_t input_count = 0; 226 size_t input_count = 0;
227 AddressingMode mode = 227 AddressingMode mode =
228 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count); 228 g.GetEffectiveAddressMemoryOperand(node, inputs, &input_count);
229 InstructionCode code = opcode | AddressingModeField::encode(mode); 229 InstructionCode code = opcode | AddressingModeField::encode(mode);
230 inputs[input_count++] = val; 230 inputs[input_count++] = val;
231 Emit(code, 0, static_cast<InstructionOperand**>(NULL), input_count, inputs); 231 Emit(code, 0, static_cast<InstructionOperand*>(NULL), input_count, inputs);
232 } 232 }
233 233
234 234
235 void InstructionSelector::VisitCheckedLoad(Node* node) { 235 void InstructionSelector::VisitCheckedLoad(Node* node) {
236 MachineType rep = RepresentationOf(OpParameter<MachineType>(node)); 236 MachineType rep = RepresentationOf(OpParameter<MachineType>(node));
237 MachineType typ = TypeOf(OpParameter<MachineType>(node)); 237 MachineType typ = TypeOf(OpParameter<MachineType>(node));
238 IA32OperandGenerator g(this); 238 IA32OperandGenerator g(this);
239 Node* const buffer = node->InputAt(0); 239 Node* const buffer = node->InputAt(0);
240 Node* const offset = node->InputAt(1); 240 Node* const offset = node->InputAt(1);
241 Node* const length = node->InputAt(2); 241 Node* const length = node->InputAt(2);
(...skipping 11 matching lines...) Expand all
253 case kRepFloat32: 253 case kRepFloat32:
254 opcode = kCheckedLoadFloat32; 254 opcode = kCheckedLoadFloat32;
255 break; 255 break;
256 case kRepFloat64: 256 case kRepFloat64:
257 opcode = kCheckedLoadFloat64; 257 opcode = kCheckedLoadFloat64;
258 break; 258 break;
259 default: 259 default:
260 UNREACHABLE(); 260 UNREACHABLE();
261 return; 261 return;
262 } 262 }
263 InstructionOperand* offset_operand = g.UseRegister(offset); 263 InstructionOperand offset_operand = g.UseRegister(offset);
264 InstructionOperand* length_operand = 264 InstructionOperand length_operand =
265 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length); 265 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
266 if (g.CanBeImmediate(buffer)) { 266 if (g.CanBeImmediate(buffer)) {
267 Emit(opcode | AddressingModeField::encode(kMode_MRI), 267 Emit(opcode | AddressingModeField::encode(kMode_MRI),
268 g.DefineAsRegister(node), offset_operand, length_operand, 268 g.DefineAsRegister(node), offset_operand, length_operand,
269 offset_operand, g.UseImmediate(buffer)); 269 offset_operand, g.UseImmediate(buffer));
270 } else { 270 } else {
271 Emit(opcode | AddressingModeField::encode(kMode_MR1), 271 Emit(opcode | AddressingModeField::encode(kMode_MR1),
272 g.DefineAsRegister(node), offset_operand, length_operand, 272 g.DefineAsRegister(node), offset_operand, length_operand,
273 g.UseRegister(buffer), offset_operand); 273 g.UseRegister(buffer), offset_operand);
274 } 274 }
(...skipping 21 matching lines...) Expand all
296 case kRepFloat32: 296 case kRepFloat32:
297 opcode = kCheckedStoreFloat32; 297 opcode = kCheckedStoreFloat32;
298 break; 298 break;
299 case kRepFloat64: 299 case kRepFloat64:
300 opcode = kCheckedStoreFloat64; 300 opcode = kCheckedStoreFloat64;
301 break; 301 break;
302 default: 302 default:
303 UNREACHABLE(); 303 UNREACHABLE();
304 return; 304 return;
305 } 305 }
306 InstructionOperand* value_operand = 306 InstructionOperand value_operand =
307 g.CanBeImmediate(value) 307 g.CanBeImmediate(value)
308 ? g.UseImmediate(value) 308 ? g.UseImmediate(value)
309 : ((rep == kRepWord8 || rep == kRepBit) ? g.UseByteRegister(value) 309 : ((rep == kRepWord8 || rep == kRepBit) ? g.UseByteRegister(value)
310 : g.UseRegister(value)); 310 : g.UseRegister(value));
311 InstructionOperand* offset_operand = g.UseRegister(offset); 311 InstructionOperand offset_operand = g.UseRegister(offset);
312 InstructionOperand* length_operand = 312 InstructionOperand length_operand =
313 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length); 313 g.CanBeImmediate(length) ? g.UseImmediate(length) : g.UseRegister(length);
314 if (g.CanBeImmediate(buffer)) { 314 if (g.CanBeImmediate(buffer)) {
315 Emit(opcode | AddressingModeField::encode(kMode_MRI), nullptr, 315 Emit(opcode | AddressingModeField::encode(kMode_MRI), g.NoOutput(),
316 offset_operand, length_operand, value_operand, offset_operand, 316 offset_operand, length_operand, value_operand, offset_operand,
317 g.UseImmediate(buffer)); 317 g.UseImmediate(buffer));
318 } else { 318 } else {
319 Emit(opcode | AddressingModeField::encode(kMode_MR1), nullptr, 319 Emit(opcode | AddressingModeField::encode(kMode_MR1), g.NoOutput(),
320 offset_operand, length_operand, value_operand, g.UseRegister(buffer), 320 offset_operand, length_operand, value_operand, g.UseRegister(buffer),
321 offset_operand); 321 offset_operand);
322 } 322 }
323 } 323 }
324 324
325 325
326 // Shared routine for multiple binary operations. 326 // Shared routine for multiple binary operations.
327 static void VisitBinop(InstructionSelector* selector, Node* node, 327 static void VisitBinop(InstructionSelector* selector, Node* node,
328 InstructionCode opcode, FlagsContinuation* cont) { 328 InstructionCode opcode, FlagsContinuation* cont) {
329 IA32OperandGenerator g(selector); 329 IA32OperandGenerator g(selector);
330 Int32BinopMatcher m(node); 330 Int32BinopMatcher m(node);
331 Node* left = m.left().node(); 331 Node* left = m.left().node();
332 Node* right = m.right().node(); 332 Node* right = m.right().node();
333 InstructionOperand* inputs[4]; 333 InstructionOperand inputs[4];
334 size_t input_count = 0; 334 size_t input_count = 0;
335 InstructionOperand* outputs[2]; 335 InstructionOperand outputs[2];
336 size_t output_count = 0; 336 size_t output_count = 0;
337 337
338 // TODO(turbofan): match complex addressing modes. 338 // TODO(turbofan): match complex addressing modes.
339 if (left == right) { 339 if (left == right) {
340 // If both inputs refer to the same operand, enforce allocating a register 340 // If both inputs refer to the same operand, enforce allocating a register
341 // for both of them to ensure that we don't end up generating code like 341 // for both of them to ensure that we don't end up generating code like
342 // this: 342 // this:
343 // 343 //
344 // mov eax, [ebp-0x10] 344 // mov eax, [ebp-0x10]
345 // add eax, [ebp-0x10] 345 // add eax, [ebp-0x10]
346 // jo label 346 // jo label
347 InstructionOperand* const input = g.UseRegister(left); 347 InstructionOperand const input = g.UseRegister(left);
348 inputs[input_count++] = input; 348 inputs[input_count++] = input;
349 inputs[input_count++] = input; 349 inputs[input_count++] = input;
350 } else if (g.CanBeImmediate(right)) { 350 } else if (g.CanBeImmediate(right)) {
351 inputs[input_count++] = g.UseRegister(left); 351 inputs[input_count++] = g.UseRegister(left);
352 inputs[input_count++] = g.UseImmediate(right); 352 inputs[input_count++] = g.UseImmediate(right);
353 } else { 353 } else {
354 if (node->op()->HasProperty(Operator::kCommutative) && 354 if (node->op()->HasProperty(Operator::kCommutative) &&
355 g.CanBeBetterLeftOperand(right)) { 355 g.CanBeBetterLeftOperand(right)) {
356 std::swap(left, right); 356 std::swap(left, right);
357 } 357 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 ArchOpcode opcode) { 433 ArchOpcode opcode) {
434 IA32OperandGenerator g(selector); 434 IA32OperandGenerator g(selector);
435 selector->Emit(opcode, g.DefineAsFixed(node, edx), 435 selector->Emit(opcode, g.DefineAsFixed(node, edx),
436 g.UseFixed(node->InputAt(0), eax), 436 g.UseFixed(node->InputAt(0), eax),
437 g.UseUniqueRegister(node->InputAt(1))); 437 g.UseUniqueRegister(node->InputAt(1)));
438 } 438 }
439 439
440 440
441 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) { 441 void VisitDiv(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
442 IA32OperandGenerator g(selector); 442 IA32OperandGenerator g(selector);
443 InstructionOperand* temps[] = {g.TempRegister(edx)}; 443 InstructionOperand temps[] = {g.TempRegister(edx)};
444 selector->Emit(opcode, g.DefineAsFixed(node, eax), 444 selector->Emit(opcode, g.DefineAsFixed(node, eax),
445 g.UseFixed(node->InputAt(0), eax), 445 g.UseFixed(node->InputAt(0), eax),
446 g.UseUnique(node->InputAt(1)), arraysize(temps), temps); 446 g.UseUnique(node->InputAt(1)), arraysize(temps), temps);
447 } 447 }
448 448
449 449
450 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) { 450 void VisitMod(InstructionSelector* selector, Node* node, ArchOpcode opcode) {
451 IA32OperandGenerator g(selector); 451 IA32OperandGenerator g(selector);
452 selector->Emit(opcode, g.DefineAsFixed(node, edx), 452 selector->Emit(opcode, g.DefineAsFixed(node, edx),
453 g.UseFixed(node->InputAt(0), eax), 453 g.UseFixed(node->InputAt(0), eax),
454 g.UseUnique(node->InputAt(1))); 454 g.UseUnique(node->InputAt(1)));
455 } 455 }
456 456
457 void EmitLea(InstructionSelector* selector, Node* result, Node* index, 457 void EmitLea(InstructionSelector* selector, Node* result, Node* index,
458 int scale, Node* base, Node* displacement) { 458 int scale, Node* base, Node* displacement) {
459 IA32OperandGenerator g(selector); 459 IA32OperandGenerator g(selector);
460 InstructionOperand* inputs[4]; 460 InstructionOperand inputs[4];
461 size_t input_count = 0; 461 size_t input_count = 0;
462 AddressingMode mode = g.GenerateMemoryOperandInputs( 462 AddressingMode mode = g.GenerateMemoryOperandInputs(
463 index, scale, base, displacement, inputs, &input_count); 463 index, scale, base, displacement, inputs, &input_count);
464 464
465 DCHECK_NE(0, static_cast<int>(input_count)); 465 DCHECK_NE(0, static_cast<int>(input_count));
466 DCHECK_GE(arraysize(inputs), input_count); 466 DCHECK_GE(arraysize(inputs), input_count);
467 467
468 InstructionOperand* outputs[1]; 468 InstructionOperand outputs[1];
469 outputs[0] = g.DefineAsRegister(result); 469 outputs[0] = g.DefineAsRegister(result);
470 470
471 InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea; 471 InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea;
472 472
473 selector->Emit(opcode, 1, outputs, input_count, inputs); 473 selector->Emit(opcode, 1, outputs, input_count, inputs);
474 } 474 }
475 475
476 } // namespace 476 } // namespace
477 477
478 478
(...skipping 24 matching lines...) Expand all
503 } 503 }
504 504
505 505
506 void InstructionSelector::VisitInt32Add(Node* node) { 506 void InstructionSelector::VisitInt32Add(Node* node) {
507 IA32OperandGenerator g(this); 507 IA32OperandGenerator g(this);
508 508
509 // Try to match the Add to a lea pattern 509 // Try to match the Add to a lea pattern
510 BaseWithIndexAndDisplacement32Matcher m(node); 510 BaseWithIndexAndDisplacement32Matcher m(node);
511 if (m.matches() && 511 if (m.matches() &&
512 (m.displacement() == NULL || g.CanBeImmediate(m.displacement()))) { 512 (m.displacement() == NULL || g.CanBeImmediate(m.displacement()))) {
513 InstructionOperand* inputs[4]; 513 InstructionOperand inputs[4];
514 size_t input_count = 0; 514 size_t input_count = 0;
515 AddressingMode mode = g.GenerateMemoryOperandInputs( 515 AddressingMode mode = g.GenerateMemoryOperandInputs(
516 m.index(), m.scale(), m.base(), m.displacement(), inputs, &input_count); 516 m.index(), m.scale(), m.base(), m.displacement(), inputs, &input_count);
517 517
518 DCHECK_NE(0, static_cast<int>(input_count)); 518 DCHECK_NE(0, static_cast<int>(input_count));
519 DCHECK_GE(arraysize(inputs), input_count); 519 DCHECK_GE(arraysize(inputs), input_count);
520 520
521 InstructionOperand* outputs[1]; 521 InstructionOperand outputs[1];
522 outputs[0] = g.DefineAsRegister(node); 522 outputs[0] = g.DefineAsRegister(node);
523 523
524 InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea; 524 InstructionCode opcode = AddressingModeField::encode(mode) | kIA32Lea;
525 Emit(opcode, 1, outputs, input_count, inputs); 525 Emit(opcode, 1, outputs, input_count, inputs);
526 return; 526 return;
527 } 527 }
528 528
529 // No lea pattern match, use add 529 // No lea pattern match, use add
530 VisitBinop(this, node, kIA32Add); 530 VisitBinop(this, node, kIA32Add);
531 } 531 }
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1))); 675 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
676 } else { 676 } else {
677 Emit(kSSEFloat64Div, g.DefineSameAsFirst(node), 677 Emit(kSSEFloat64Div, g.DefineSameAsFirst(node),
678 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1))); 678 g.UseRegister(node->InputAt(0)), g.Use(node->InputAt(1)));
679 } 679 }
680 } 680 }
681 681
682 682
683 void InstructionSelector::VisitFloat64Mod(Node* node) { 683 void InstructionSelector::VisitFloat64Mod(Node* node) {
684 IA32OperandGenerator g(this); 684 IA32OperandGenerator g(this);
685 InstructionOperand* temps[] = {g.TempRegister(eax)}; 685 InstructionOperand temps[] = {g.TempRegister(eax)};
686 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node), 686 Emit(kSSEFloat64Mod, g.DefineSameAsFirst(node),
687 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1, 687 g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1)), 1,
688 temps); 688 temps);
689 } 689 }
690 690
691 691
692 void InstructionSelector::VisitFloat64Sqrt(Node* node) { 692 void InstructionSelector::VisitFloat64Sqrt(Node* node) {
693 IA32OperandGenerator g(this); 693 IA32OperandGenerator g(this);
694 Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0))); 694 Emit(kSSEFloat64Sqrt, g.DefineAsRegister(node), g.Use(node->InputAt(0)));
695 } 695 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 731
732 CallBuffer buffer(zone(), descriptor, frame_state_descriptor); 732 CallBuffer buffer(zone(), descriptor, frame_state_descriptor);
733 733
734 // Compute InstructionOperands for inputs and outputs. 734 // Compute InstructionOperands for inputs and outputs.
735 InitializeCallBuffer(node, &buffer, true, true); 735 InitializeCallBuffer(node, &buffer, true, true);
736 736
737 // Push any stack arguments. 737 // Push any stack arguments.
738 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend(); 738 for (auto i = buffer.pushed_nodes.rbegin(); i != buffer.pushed_nodes.rend();
739 ++i) { 739 ++i) {
740 // TODO(titzer): handle pushing double parameters. 740 // TODO(titzer): handle pushing double parameters.
741 InstructionOperand* value = 741 InstructionOperand value =
742 g.CanBeImmediate(*i) ? g.UseImmediate(*i) : IsSupported(ATOM) 742 g.CanBeImmediate(*i) ? g.UseImmediate(*i) : IsSupported(ATOM)
743 ? g.UseRegister(*i) 743 ? g.UseRegister(*i)
744 : g.Use(*i); 744 : g.Use(*i);
745 Emit(kIA32Push, nullptr, value); 745 Emit(kIA32Push, g.NoOutput(), value);
746 } 746 }
747 747
748 // Select the appropriate opcode based on the call type. 748 // Select the appropriate opcode based on the call type.
749 InstructionCode opcode; 749 InstructionCode opcode;
750 switch (descriptor->kind()) { 750 switch (descriptor->kind()) {
751 case CallDescriptor::kCallCodeObject: { 751 case CallDescriptor::kCallCodeObject: {
752 opcode = kArchCallCodeObject; 752 opcode = kArchCallCodeObject;
753 break; 753 break;
754 } 754 }
755 case CallDescriptor::kCallJSFunction: 755 case CallDescriptor::kCallJSFunction:
756 opcode = kArchCallJSFunction; 756 opcode = kArchCallJSFunction;
757 break; 757 break;
758 default: 758 default:
759 UNREACHABLE(); 759 UNREACHABLE();
760 return; 760 return;
761 } 761 }
762 opcode |= MiscField::encode(descriptor->flags()); 762 opcode |= MiscField::encode(descriptor->flags());
763 763
764 // Emit the call instruction. 764 // Emit the call instruction.
765 InstructionOperand** first_output = 765 InstructionOperand* first_output =
766 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL; 766 buffer.outputs.size() > 0 ? &buffer.outputs.front() : NULL;
767 Instruction* call_instr = 767 Instruction* call_instr =
768 Emit(opcode, buffer.outputs.size(), first_output, 768 Emit(opcode, buffer.outputs.size(), first_output,
769 buffer.instruction_args.size(), &buffer.instruction_args.front()); 769 buffer.instruction_args.size(), &buffer.instruction_args.front());
770 call_instr->MarkAsCall(); 770 call_instr->MarkAsCall();
771 } 771 }
772 772
773 773
774 namespace { 774 namespace {
775 775
776 // Shared routine for multiple compare operations. 776 // Shared routine for multiple compare operations.
777 void VisitCompare(InstructionSelector* selector, InstructionCode opcode, 777 void VisitCompare(InstructionSelector* selector, InstructionCode opcode,
778 InstructionOperand* left, InstructionOperand* right, 778 InstructionOperand left, InstructionOperand right,
779 FlagsContinuation* cont) { 779 FlagsContinuation* cont) {
780 IA32OperandGenerator g(selector); 780 IA32OperandGenerator g(selector);
781 if (cont->IsBranch()) { 781 if (cont->IsBranch()) {
782 selector->Emit(cont->Encode(opcode), NULL, left, right, 782 selector->Emit(cont->Encode(opcode), g.NoOutput(), left, right,
783 g.Label(cont->true_block()), 783 g.Label(cont->true_block()),
784 g.Label(cont->false_block()))->MarkAsControl(); 784 g.Label(cont->false_block()))->MarkAsControl();
785 } else { 785 } else {
786 DCHECK(cont->IsSet()); 786 DCHECK(cont->IsSet());
787 // TODO(titzer): Needs byte register. 787 // TODO(titzer): Needs byte register.
788 selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()), 788 selector->Emit(cont->Encode(opcode), g.DefineAsRegister(cont->result()),
789 left, right); 789 left, right);
790 } 790 }
791 } 791 }
792 792
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 MachineOperatorBuilder::kFloat64Ceil | 1008 MachineOperatorBuilder::kFloat64Ceil |
1009 MachineOperatorBuilder::kFloat64RoundTruncate | 1009 MachineOperatorBuilder::kFloat64RoundTruncate |
1010 MachineOperatorBuilder::kWord32ShiftIsSafe; 1010 MachineOperatorBuilder::kWord32ShiftIsSafe;
1011 } 1011 }
1012 return MachineOperatorBuilder::Flag::kNoFlags; 1012 return MachineOperatorBuilder::Flag::kNoFlags;
1013 } 1013 }
1014 1014
1015 } // namespace compiler 1015 } // namespace compiler
1016 } // namespace internal 1016 } // namespace internal
1017 } // namespace v8 1017 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/arm64/instruction-selector-arm64.cc ('k') | src/compiler/instruction.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698