OLD | NEW |
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 | 7 |
8 namespace v8 { | 8 namespace v8 { |
9 namespace internal { | 9 namespace internal { |
10 namespace compiler { | 10 namespace compiler { |
(...skipping 19 matching lines...) Expand all Loading... |
30 : OperandGenerator(selector) {} | 30 : OperandGenerator(selector) {} |
31 | 31 |
32 InstructionOperand* UseOperand(Node* node, ImmediateMode mode) { | 32 InstructionOperand* UseOperand(Node* node, ImmediateMode mode) { |
33 if (CanBeImmediate(node, mode)) { | 33 if (CanBeImmediate(node, mode)) { |
34 return UseImmediate(node); | 34 return UseImmediate(node); |
35 } | 35 } |
36 return UseRegister(node); | 36 return UseRegister(node); |
37 } | 37 } |
38 | 38 |
39 bool CanBeImmediate(Node* node, ImmediateMode mode) { | 39 bool CanBeImmediate(Node* node, ImmediateMode mode) { |
40 Int32Matcher m(node); | 40 int64_t value; |
41 if (!m.HasValue()) return false; | 41 if (node->opcode() == IrOpcode::kInt32Constant) |
42 int64_t value = m.Value(); | 42 value = OpParameter<int32_t>(node); |
| 43 else if (node->opcode() == IrOpcode::kInt64Constant) |
| 44 value = OpParameter<int64_t>(node); |
| 45 else |
| 46 return false; |
43 unsigned ignored; | 47 unsigned ignored; |
44 switch (mode) { | 48 switch (mode) { |
45 case kLogical32Imm: | 49 case kLogical32Imm: |
46 // TODO(dcarney): some unencodable values can be handled by | 50 // TODO(dcarney): some unencodable values can be handled by |
47 // switching instructions. | 51 // switching instructions. |
48 return Assembler::IsImmLogical(static_cast<uint64_t>(value), 32, | 52 return Assembler::IsImmLogical(static_cast<uint64_t>(value), 32, |
49 &ignored, &ignored, &ignored); | 53 &ignored, &ignored, &ignored); |
50 case kLogical64Imm: | 54 case kLogical64Imm: |
51 return Assembler::IsImmLogical(static_cast<uint64_t>(value), 64, | 55 return Assembler::IsImmLogical(static_cast<uint64_t>(value), 64, |
52 &ignored, &ignored, &ignored); | 56 &ignored, &ignored, &ignored); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, | 104 static void VisitRRO(InstructionSelector* selector, ArchOpcode opcode, |
101 Node* node, ImmediateMode operand_mode) { | 105 Node* node, ImmediateMode operand_mode) { |
102 Arm64OperandGenerator g(selector); | 106 Arm64OperandGenerator g(selector); |
103 selector->Emit(opcode, g.DefineAsRegister(node), | 107 selector->Emit(opcode, g.DefineAsRegister(node), |
104 g.UseRegister(node->InputAt(0)), | 108 g.UseRegister(node->InputAt(0)), |
105 g.UseOperand(node->InputAt(1), operand_mode)); | 109 g.UseOperand(node->InputAt(1), operand_mode)); |
106 } | 110 } |
107 | 111 |
108 | 112 |
109 // Shared routine for multiple binary operations. | 113 // Shared routine for multiple binary operations. |
| 114 template <typename Matcher> |
110 static void VisitBinop(InstructionSelector* selector, Node* node, | 115 static void VisitBinop(InstructionSelector* selector, Node* node, |
111 InstructionCode opcode, ImmediateMode operand_mode, | 116 InstructionCode opcode, ImmediateMode operand_mode, |
112 FlagsContinuation* cont) { | 117 FlagsContinuation* cont) { |
113 Arm64OperandGenerator g(selector); | 118 Arm64OperandGenerator g(selector); |
114 Int32BinopMatcher m(node); | 119 Matcher m(node); |
115 InstructionOperand* inputs[4]; | 120 InstructionOperand* inputs[4]; |
116 size_t input_count = 0; | 121 size_t input_count = 0; |
117 InstructionOperand* outputs[2]; | 122 InstructionOperand* outputs[2]; |
118 size_t output_count = 0; | 123 size_t output_count = 0; |
119 | 124 |
120 inputs[input_count++] = g.UseRegister(m.left().node()); | 125 inputs[input_count++] = g.UseRegister(m.left().node()); |
121 inputs[input_count++] = g.UseOperand(m.right().node(), operand_mode); | 126 inputs[input_count++] = g.UseOperand(m.right().node(), operand_mode); |
122 | 127 |
123 if (cont->IsBranch()) { | 128 if (cont->IsBranch()) { |
124 inputs[input_count++] = g.Label(cont->true_block()); | 129 inputs[input_count++] = g.Label(cont->true_block()); |
(...skipping 10 matching lines...) Expand all Loading... |
135 DCHECK_GE(arraysize(inputs), input_count); | 140 DCHECK_GE(arraysize(inputs), input_count); |
136 DCHECK_GE(arraysize(outputs), output_count); | 141 DCHECK_GE(arraysize(outputs), output_count); |
137 | 142 |
138 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, | 143 Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, |
139 outputs, input_count, inputs); | 144 outputs, input_count, inputs); |
140 if (cont->IsBranch()) instr->MarkAsControl(); | 145 if (cont->IsBranch()) instr->MarkAsControl(); |
141 } | 146 } |
142 | 147 |
143 | 148 |
144 // Shared routine for multiple binary operations. | 149 // Shared routine for multiple binary operations. |
| 150 template <typename Matcher> |
145 static void VisitBinop(InstructionSelector* selector, Node* node, | 151 static void VisitBinop(InstructionSelector* selector, Node* node, |
146 ArchOpcode opcode, ImmediateMode operand_mode) { | 152 ArchOpcode opcode, ImmediateMode operand_mode) { |
147 FlagsContinuation cont; | 153 FlagsContinuation cont; |
148 VisitBinop(selector, node, opcode, operand_mode, &cont); | 154 VisitBinop<Matcher>(selector, node, opcode, operand_mode, &cont); |
149 } | 155 } |
150 | 156 |
151 | 157 |
152 void InstructionSelector::VisitLoad(Node* node) { | 158 void InstructionSelector::VisitLoad(Node* node) { |
153 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); | 159 MachineType rep = RepresentationOf(OpParameter<LoadRepresentation>(node)); |
154 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); | 160 MachineType typ = TypeOf(OpParameter<LoadRepresentation>(node)); |
155 Arm64OperandGenerator g(this); | 161 Arm64OperandGenerator g(this); |
156 Node* base = node->InputAt(0); | 162 Node* base = node->InputAt(0); |
157 Node* index = node->InputAt(1); | 163 Node* index = node->InputAt(1); |
158 ArchOpcode opcode; | 164 ArchOpcode opcode; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, | 261 Emit(opcode | AddressingModeField::encode(kMode_MRI), NULL, |
256 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); | 262 g.UseRegister(base), g.UseImmediate(index), g.UseRegister(value)); |
257 } else { | 263 } else { |
258 Emit(opcode | AddressingModeField::encode(kMode_MRR), NULL, | 264 Emit(opcode | AddressingModeField::encode(kMode_MRR), NULL, |
259 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); | 265 g.UseRegister(base), g.UseRegister(index), g.UseRegister(value)); |
260 } | 266 } |
261 } | 267 } |
262 | 268 |
263 | 269 |
264 void InstructionSelector::VisitWord32And(Node* node) { | 270 void InstructionSelector::VisitWord32And(Node* node) { |
265 VisitBinop(this, node, kArm64And32, kLogical32Imm); | 271 VisitBinop<Int32BinopMatcher>(this, node, kArm64And32, kLogical32Imm); |
266 } | 272 } |
267 | 273 |
268 | 274 |
269 void InstructionSelector::VisitWord64And(Node* node) { | 275 void InstructionSelector::VisitWord64And(Node* node) { |
270 VisitBinop(this, node, kArm64And, kLogical64Imm); | 276 VisitBinop<Int64BinopMatcher>(this, node, kArm64And, kLogical64Imm); |
271 } | 277 } |
272 | 278 |
273 | 279 |
274 void InstructionSelector::VisitWord32Or(Node* node) { | 280 void InstructionSelector::VisitWord32Or(Node* node) { |
275 VisitBinop(this, node, kArm64Or32, kLogical32Imm); | 281 VisitBinop<Int32BinopMatcher>(this, node, kArm64Or32, kLogical32Imm); |
276 } | 282 } |
277 | 283 |
278 | 284 |
279 void InstructionSelector::VisitWord64Or(Node* node) { | 285 void InstructionSelector::VisitWord64Or(Node* node) { |
280 VisitBinop(this, node, kArm64Or, kLogical64Imm); | 286 VisitBinop<Int64BinopMatcher>(this, node, kArm64Or, kLogical64Imm); |
281 } | 287 } |
282 | 288 |
283 | 289 |
284 void InstructionSelector::VisitWord32Xor(Node* node) { | 290 void InstructionSelector::VisitWord32Xor(Node* node) { |
285 Arm64OperandGenerator g(this); | 291 Arm64OperandGenerator g(this); |
286 Int32BinopMatcher m(node); | 292 Int32BinopMatcher m(node); |
287 if (m.right().Is(-1)) { | 293 if (m.right().Is(-1)) { |
288 Emit(kArm64Not32, g.DefineAsRegister(node), g.UseRegister(m.left().node())); | 294 Emit(kArm64Not32, g.DefineAsRegister(node), g.UseRegister(m.left().node())); |
289 } else { | 295 } else { |
290 VisitBinop(this, node, kArm64Xor32, kLogical32Imm); | 296 VisitBinop<Int32BinopMatcher>(this, node, kArm64Xor32, kLogical32Imm); |
291 } | 297 } |
292 } | 298 } |
293 | 299 |
294 | 300 |
295 void InstructionSelector::VisitWord64Xor(Node* node) { | 301 void InstructionSelector::VisitWord64Xor(Node* node) { |
296 Arm64OperandGenerator g(this); | 302 Arm64OperandGenerator g(this); |
297 Int64BinopMatcher m(node); | 303 Int64BinopMatcher m(node); |
298 if (m.right().Is(-1)) { | 304 if (m.right().Is(-1)) { |
299 Emit(kArm64Not, g.DefineAsRegister(node), g.UseRegister(m.left().node())); | 305 Emit(kArm64Not, g.DefineAsRegister(node), g.UseRegister(m.left().node())); |
300 } else { | 306 } else { |
301 VisitBinop(this, node, kArm64Xor, kLogical32Imm); | 307 VisitBinop<Int64BinopMatcher>(this, node, kArm64Xor, kLogical32Imm); |
302 } | 308 } |
303 } | 309 } |
304 | 310 |
305 | 311 |
306 void InstructionSelector::VisitWord32Shl(Node* node) { | 312 void InstructionSelector::VisitWord32Shl(Node* node) { |
307 VisitRRO(this, kArm64Shl32, node, kShift32Imm); | 313 VisitRRO(this, kArm64Shl32, node, kShift32Imm); |
308 } | 314 } |
309 | 315 |
310 | 316 |
311 void InstructionSelector::VisitWord64Shl(Node* node) { | 317 void InstructionSelector::VisitWord64Shl(Node* node) { |
(...skipping 25 matching lines...) Expand all Loading... |
337 VisitRRO(this, kArm64Ror32, node, kShift32Imm); | 343 VisitRRO(this, kArm64Ror32, node, kShift32Imm); |
338 } | 344 } |
339 | 345 |
340 | 346 |
341 void InstructionSelector::VisitWord64Ror(Node* node) { | 347 void InstructionSelector::VisitWord64Ror(Node* node) { |
342 VisitRRO(this, kArm64Ror, node, kShift64Imm); | 348 VisitRRO(this, kArm64Ror, node, kShift64Imm); |
343 } | 349 } |
344 | 350 |
345 | 351 |
346 void InstructionSelector::VisitInt32Add(Node* node) { | 352 void InstructionSelector::VisitInt32Add(Node* node) { |
347 VisitBinop(this, node, kArm64Add32, kArithmeticImm); | 353 VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, kArithmeticImm); |
348 } | 354 } |
349 | 355 |
350 | 356 |
351 void InstructionSelector::VisitInt64Add(Node* node) { | 357 void InstructionSelector::VisitInt64Add(Node* node) { |
352 VisitBinop(this, node, kArm64Add, kArithmeticImm); | 358 VisitBinop<Int64BinopMatcher>(this, node, kArm64Add, kArithmeticImm); |
353 } | 359 } |
354 | 360 |
355 | 361 |
356 void InstructionSelector::VisitInt32Sub(Node* node) { | 362 void InstructionSelector::VisitInt32Sub(Node* node) { |
357 Arm64OperandGenerator g(this); | 363 Arm64OperandGenerator g(this); |
358 Int32BinopMatcher m(node); | 364 Int32BinopMatcher m(node); |
359 if (m.left().Is(0)) { | 365 if (m.left().Is(0)) { |
360 Emit(kArm64Neg32, g.DefineAsRegister(node), | 366 Emit(kArm64Neg32, g.DefineAsRegister(node), |
361 g.UseRegister(m.right().node())); | 367 g.UseRegister(m.right().node())); |
362 } else { | 368 } else { |
363 VisitBinop(this, node, kArm64Sub32, kArithmeticImm); | 369 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm); |
364 } | 370 } |
365 } | 371 } |
366 | 372 |
367 | 373 |
368 void InstructionSelector::VisitInt64Sub(Node* node) { | 374 void InstructionSelector::VisitInt64Sub(Node* node) { |
369 Arm64OperandGenerator g(this); | 375 Arm64OperandGenerator g(this); |
370 Int64BinopMatcher m(node); | 376 Int64BinopMatcher m(node); |
371 if (m.left().Is(0)) { | 377 if (m.left().Is(0)) { |
372 Emit(kArm64Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node())); | 378 Emit(kArm64Neg, g.DefineAsRegister(node), g.UseRegister(m.right().node())); |
373 } else { | 379 } else { |
374 VisitBinop(this, node, kArm64Sub, kArithmeticImm); | 380 VisitBinop<Int64BinopMatcher>(this, node, kArm64Sub, kArithmeticImm); |
375 } | 381 } |
376 } | 382 } |
377 | 383 |
378 | 384 |
379 void InstructionSelector::VisitInt32Mul(Node* node) { | 385 void InstructionSelector::VisitInt32Mul(Node* node) { |
380 VisitRRR(this, kArm64Mul32, node); | 386 VisitRRR(this, kArm64Mul32, node); |
381 } | 387 } |
382 | 388 |
383 | 389 |
384 void InstructionSelector::VisitInt64Mul(Node* node) { | 390 void InstructionSelector::VisitInt64Mul(Node* node) { |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 void InstructionSelector::VisitFloat64Mod(Node* node) { | 501 void InstructionSelector::VisitFloat64Mod(Node* node) { |
496 Arm64OperandGenerator g(this); | 502 Arm64OperandGenerator g(this); |
497 Emit(kArm64Float64Mod, g.DefineAsFixed(node, d0), | 503 Emit(kArm64Float64Mod, g.DefineAsFixed(node, d0), |
498 g.UseFixed(node->InputAt(0), d0), | 504 g.UseFixed(node->InputAt(0), d0), |
499 g.UseFixed(node->InputAt(1), d1))->MarkAsCall(); | 505 g.UseFixed(node->InputAt(1), d1))->MarkAsCall(); |
500 } | 506 } |
501 | 507 |
502 | 508 |
503 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, | 509 void InstructionSelector::VisitInt32AddWithOverflow(Node* node, |
504 FlagsContinuation* cont) { | 510 FlagsContinuation* cont) { |
505 VisitBinop(this, node, kArm64Add32, kArithmeticImm, cont); | 511 VisitBinop<Int32BinopMatcher>(this, node, kArm64Add32, kArithmeticImm, cont); |
506 } | 512 } |
507 | 513 |
508 | 514 |
509 void InstructionSelector::VisitInt32SubWithOverflow(Node* node, | 515 void InstructionSelector::VisitInt32SubWithOverflow(Node* node, |
510 FlagsContinuation* cont) { | 516 FlagsContinuation* cont) { |
511 VisitBinop(this, node, kArm64Sub32, kArithmeticImm, cont); | 517 VisitBinop<Int32BinopMatcher>(this, node, kArm64Sub32, kArithmeticImm, cont); |
512 } | 518 } |
513 | 519 |
514 | 520 |
515 // Shared routine for multiple compare operations. | 521 // Shared routine for multiple compare operations. |
516 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, | 522 static void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
517 InstructionOperand* left, InstructionOperand* right, | 523 InstructionOperand* left, InstructionOperand* right, |
518 FlagsContinuation* cont) { | 524 FlagsContinuation* cont) { |
519 Arm64OperandGenerator g(selector); | 525 Arm64OperandGenerator g(selector); |
520 opcode = cont->Encode(opcode); | 526 opcode = cont->Encode(opcode); |
521 if (cont->IsBranch()) { | 527 if (cont->IsBranch()) { |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 // Caller clean up of stack for C-style calls. | 695 // Caller clean up of stack for C-style calls. |
690 if (is_c_frame && aligned_push_count > 0) { | 696 if (is_c_frame && aligned_push_count > 0) { |
691 DCHECK(deoptimization == NULL && continuation == NULL); | 697 DCHECK(deoptimization == NULL && continuation == NULL); |
692 Emit(kArchDrop | MiscField::encode(aligned_push_count), NULL); | 698 Emit(kArchDrop | MiscField::encode(aligned_push_count), NULL); |
693 } | 699 } |
694 } | 700 } |
695 | 701 |
696 } // namespace compiler | 702 } // namespace compiler |
697 } // namespace internal | 703 } // namespace internal |
698 } // namespace v8 | 704 } // namespace v8 |
OLD | NEW |