| 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 |