| 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 #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 { |
| (...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 | 464 |
| 465 DCHECK_NE(0u, input_count); | 465 DCHECK_NE(0u, input_count); |
| 466 DCHECK((output_count != 0) || IsComparisonField::decode(properties)); | 466 DCHECK((output_count != 0) || IsComparisonField::decode(properties)); |
| 467 DCHECK_GE(arraysize(inputs), input_count); | 467 DCHECK_GE(arraysize(inputs), input_count); |
| 468 DCHECK_GE(arraysize(outputs), output_count); | 468 DCHECK_GE(arraysize(outputs), output_count); |
| 469 | 469 |
| 470 opcode = cont->Encode(opcode); | 470 opcode = cont->Encode(opcode); |
| 471 if (cont->IsDeoptimize()) { | 471 if (cont->IsDeoptimize()) { |
| 472 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, | 472 selector->EmitDeoptimize(opcode, output_count, outputs, input_count, inputs, |
| 473 cont->reason(), cont->frame_state()); | 473 cont->reason(), cont->frame_state()); |
| 474 } else if (cont->IsTrap()) { |
| 475 inputs[input_count++] = g.UseImmediate(cont->trap_id()); |
| 476 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 474 } else { | 477 } else { |
| 475 selector->Emit(opcode, output_count, outputs, input_count, inputs); | 478 selector->Emit(opcode, output_count, outputs, input_count, inputs); |
| 476 } | 479 } |
| 477 } | 480 } |
| 478 | 481 |
| 479 | 482 |
| 480 // Shared routine for multiple binary operations. | 483 // Shared routine for multiple binary operations. |
| 481 template <typename Matcher> | 484 template <typename Matcher> |
| 482 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, | 485 void VisitBinop(InstructionSelector* selector, Node* node, ArchOpcode opcode, |
| 483 ImmediateMode operand_mode) { | 486 ImmediateMode operand_mode) { |
| (...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1377 | 1380 |
| 1378 InstructionCode opcode = cont->Encode(kArm64Cmp) | | 1381 InstructionCode opcode = cont->Encode(kArm64Cmp) | |
| 1379 AddressingModeField::encode(kMode_Operand2_R_SXTW); | 1382 AddressingModeField::encode(kMode_Operand2_R_SXTW); |
| 1380 if (cont->IsBranch()) { | 1383 if (cont->IsBranch()) { |
| 1381 selector->Emit(opcode, g.NoOutput(), result, result, | 1384 selector->Emit(opcode, g.NoOutput(), result, result, |
| 1382 g.Label(cont->true_block()), g.Label(cont->false_block())); | 1385 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 1383 } else if (cont->IsDeoptimize()) { | 1386 } else if (cont->IsDeoptimize()) { |
| 1384 InstructionOperand in[] = {result, result}; | 1387 InstructionOperand in[] = {result, result}; |
| 1385 selector->EmitDeoptimize(opcode, 0, nullptr, 2, in, cont->reason(), | 1388 selector->EmitDeoptimize(opcode, 0, nullptr, 2, in, cont->reason(), |
| 1386 cont->frame_state()); | 1389 cont->frame_state()); |
| 1390 } else if (cont->IsSet()) { |
| 1391 selector->Emit(opcode, g.DefineAsRegister(cont->result()), result, result); |
| 1387 } else { | 1392 } else { |
| 1388 DCHECK(cont->IsSet()); | 1393 DCHECK(cont->IsTrap()); |
| 1389 selector->Emit(opcode, g.DefineAsRegister(cont->result()), result, result); | 1394 selector->Emit(opcode, g.NoOutput(), result, result, |
| 1395 g.UseImmediate(cont->trap_id())); |
| 1390 } | 1396 } |
| 1391 } | 1397 } |
| 1392 | 1398 |
| 1393 } // namespace | 1399 } // namespace |
| 1394 | 1400 |
| 1395 void InstructionSelector::VisitInt32Mul(Node* node) { | 1401 void InstructionSelector::VisitInt32Mul(Node* node) { |
| 1396 Arm64OperandGenerator g(this); | 1402 Arm64OperandGenerator g(this); |
| 1397 Int32BinopMatcher m(node); | 1403 Int32BinopMatcher m(node); |
| 1398 | 1404 |
| 1399 // First, try to reduce the multiplication to addition with left shift. | 1405 // First, try to reduce the multiplication to addition with left shift. |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1993 InstructionOperand left, InstructionOperand right, | 1999 InstructionOperand left, InstructionOperand right, |
| 1994 FlagsContinuation* cont) { | 2000 FlagsContinuation* cont) { |
| 1995 Arm64OperandGenerator g(selector); | 2001 Arm64OperandGenerator g(selector); |
| 1996 opcode = cont->Encode(opcode); | 2002 opcode = cont->Encode(opcode); |
| 1997 if (cont->IsBranch()) { | 2003 if (cont->IsBranch()) { |
| 1998 selector->Emit(opcode, g.NoOutput(), left, right, | 2004 selector->Emit(opcode, g.NoOutput(), left, right, |
| 1999 g.Label(cont->true_block()), g.Label(cont->false_block())); | 2005 g.Label(cont->true_block()), g.Label(cont->false_block())); |
| 2000 } else if (cont->IsDeoptimize()) { | 2006 } else if (cont->IsDeoptimize()) { |
| 2001 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->reason(), | 2007 selector->EmitDeoptimize(opcode, g.NoOutput(), left, right, cont->reason(), |
| 2002 cont->frame_state()); | 2008 cont->frame_state()); |
| 2009 } else if (cont->IsSet()) { |
| 2010 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); |
| 2003 } else { | 2011 } else { |
| 2004 DCHECK(cont->IsSet()); | 2012 DCHECK(cont->IsTrap()); |
| 2005 selector->Emit(opcode, g.DefineAsRegister(cont->result()), left, right); | 2013 selector->Emit(opcode, g.NoOutput(), left, right, |
| 2014 g.UseImmediate(cont->trap_id())); |
| 2006 } | 2015 } |
| 2007 } | 2016 } |
| 2008 | 2017 |
| 2009 | 2018 |
| 2010 // Shared routine for multiple word compare operations. | 2019 // Shared routine for multiple word compare operations. |
| 2011 void VisitWordCompare(InstructionSelector* selector, Node* node, | 2020 void VisitWordCompare(InstructionSelector* selector, Node* node, |
| 2012 InstructionCode opcode, FlagsContinuation* cont, | 2021 InstructionCode opcode, FlagsContinuation* cont, |
| 2013 bool commutative, ImmediateMode immediate_mode) { | 2022 bool commutative, ImmediateMode immediate_mode) { |
| 2014 Arm64OperandGenerator g(selector); | 2023 Arm64OperandGenerator g(selector); |
| 2015 Node* left = node->InputAt(0); | 2024 Node* left = node->InputAt(0); |
| (...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2511 default: | 2520 default: |
| 2512 break; | 2521 break; |
| 2513 } | 2522 } |
| 2514 } | 2523 } |
| 2515 | 2524 |
| 2516 // Branch could not be combined with a compare, compare against 0 and branch. | 2525 // Branch could not be combined with a compare, compare against 0 and branch. |
| 2517 if (cont->IsBranch()) { | 2526 if (cont->IsBranch()) { |
| 2518 selector->Emit(cont->Encode(kArm64CompareAndBranch32), g.NoOutput(), | 2527 selector->Emit(cont->Encode(kArm64CompareAndBranch32), g.NoOutput(), |
| 2519 g.UseRegister(value), g.Label(cont->true_block()), | 2528 g.UseRegister(value), g.Label(cont->true_block()), |
| 2520 g.Label(cont->false_block())); | 2529 g.Label(cont->false_block())); |
| 2521 } else { | 2530 } else if (cont->IsDeoptimize()) { |
| 2522 DCHECK(cont->IsDeoptimize()); | |
| 2523 selector->EmitDeoptimize(cont->Encode(kArm64Tst32), g.NoOutput(), | 2531 selector->EmitDeoptimize(cont->Encode(kArm64Tst32), g.NoOutput(), |
| 2524 g.UseRegister(value), g.UseRegister(value), | 2532 g.UseRegister(value), g.UseRegister(value), |
| 2525 cont->reason(), cont->frame_state()); | 2533 cont->reason(), cont->frame_state()); |
| 2534 } else { |
| 2535 DCHECK(cont->IsTrap()); |
| 2536 selector->Emit(cont->Encode(kArm64Tst32), g.NoOutput(), |
| 2537 g.UseRegister(value), g.UseRegister(value), |
| 2538 g.UseImmediate(cont->trap_id())); |
| 2526 } | 2539 } |
| 2527 } | 2540 } |
| 2528 | 2541 |
| 2529 } // namespace | 2542 } // namespace |
| 2530 | 2543 |
| 2531 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, | 2544 void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, |
| 2532 BasicBlock* fbranch) { | 2545 BasicBlock* fbranch) { |
| 2533 FlagsContinuation cont(kNotEqual, tbranch, fbranch); | 2546 FlagsContinuation cont(kNotEqual, tbranch, fbranch); |
| 2534 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); | 2547 VisitWordCompareZero(this, branch, branch->InputAt(0), &cont); |
| 2535 } | 2548 } |
| 2536 | 2549 |
| 2537 void InstructionSelector::VisitDeoptimizeIf(Node* node) { | 2550 void InstructionSelector::VisitDeoptimizeIf(Node* node) { |
| 2538 FlagsContinuation cont = FlagsContinuation::ForDeoptimize( | 2551 FlagsContinuation cont = FlagsContinuation::ForDeoptimize( |
| 2539 kNotEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); | 2552 kNotEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); |
| 2540 VisitWordCompareZero(this, node, node->InputAt(0), &cont); | 2553 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 2541 } | 2554 } |
| 2542 | 2555 |
| 2543 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { | 2556 void InstructionSelector::VisitDeoptimizeUnless(Node* node) { |
| 2544 FlagsContinuation cont = FlagsContinuation::ForDeoptimize( | 2557 FlagsContinuation cont = FlagsContinuation::ForDeoptimize( |
| 2545 kEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); | 2558 kEqual, DeoptimizeReasonOf(node->op()), node->InputAt(1)); |
| 2546 VisitWordCompareZero(this, node, node->InputAt(0), &cont); | 2559 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 2547 } | 2560 } |
| 2548 | 2561 |
| 2549 void InstructionSelector::VisitTrapIf(Node* node, Runtime::FunctionId func_id) { | 2562 void InstructionSelector::VisitTrapIf(Node* node, Runtime::FunctionId func_id) { |
| 2550 UNREACHABLE(); | 2563 FlagsContinuation cont = |
| 2564 FlagsContinuation::ForTrap(kNotEqual, func_id, node->InputAt(1)); |
| 2565 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 2551 } | 2566 } |
| 2552 | 2567 |
| 2553 void InstructionSelector::VisitTrapUnless(Node* node, | 2568 void InstructionSelector::VisitTrapUnless(Node* node, |
| 2554 Runtime::FunctionId func_id) { | 2569 Runtime::FunctionId func_id) { |
| 2555 UNREACHABLE(); | 2570 FlagsContinuation cont = |
| 2571 FlagsContinuation::ForTrap(kEqual, func_id, node->InputAt(1)); |
| 2572 VisitWordCompareZero(this, node, node->InputAt(0), &cont); |
| 2556 } | 2573 } |
| 2557 | 2574 |
| 2558 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { | 2575 void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { |
| 2559 Arm64OperandGenerator g(this); | 2576 Arm64OperandGenerator g(this); |
| 2560 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); | 2577 InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); |
| 2561 | 2578 |
| 2562 // Emit either ArchTableSwitch or ArchLookupSwitch. | 2579 // Emit either ArchTableSwitch or ArchLookupSwitch. |
| 2563 size_t table_space_cost = 4 + sw.value_range; | 2580 size_t table_space_cost = 4 + sw.value_range; |
| 2564 size_t table_time_cost = 3; | 2581 size_t table_time_cost = 3; |
| 2565 size_t lookup_space_cost = 3 + 2 * sw.case_count; | 2582 size_t lookup_space_cost = 3 + 2 * sw.case_count; |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2919 // static | 2936 // static |
| 2920 MachineOperatorBuilder::AlignmentRequirements | 2937 MachineOperatorBuilder::AlignmentRequirements |
| 2921 InstructionSelector::AlignmentRequirements() { | 2938 InstructionSelector::AlignmentRequirements() { |
| 2922 return MachineOperatorBuilder::AlignmentRequirements:: | 2939 return MachineOperatorBuilder::AlignmentRequirements:: |
| 2923 FullUnalignedAccessSupport(); | 2940 FullUnalignedAccessSupport(); |
| 2924 } | 2941 } |
| 2925 | 2942 |
| 2926 } // namespace compiler | 2943 } // namespace compiler |
| 2927 } // namespace internal | 2944 } // namespace internal |
| 2928 } // namespace v8 | 2945 } // namespace v8 |
| OLD | NEW |