diff options
author | Chris Dickinson <christopher.s.dickinson@gmail.com> | 2015-05-05 13:48:55 -0700 |
---|---|---|
committer | Rod Vagg <rod@vagg.org> | 2015-08-04 11:56:09 -0700 |
commit | d58e780504bdba6c5897c48428fd984c5b5f96fe (patch) | |
tree | 033f1568ae3f9f077aceb843b42eb1ed1739ce0f /deps/v8/src/compiler/arm/instruction-selector-arm.cc | |
parent | 21d31c08e7d0b6865e52452750b20b05e6dca443 (diff) | |
download | node-new-d58e780504bdba6c5897c48428fd984c5b5f96fe.tar.gz |
deps: update v8 to 4.3.61.21
* @indutny's SealHandleScope patch (484bebc38319fc7c622478037922ad73b2edcbf9)
has been cherry picked onto the top of V8 to make it compile.
* There's some test breakage in contextify.
* This was merged at the request of the TC.
PR-URL: https://github.com/iojs/io.js/pull/1632
Diffstat (limited to 'deps/v8/src/compiler/arm/instruction-selector-arm.cc')
-rw-r--r-- | deps/v8/src/compiler/arm/instruction-selector-arm.cc | 179 |
1 files changed, 104 insertions, 75 deletions
diff --git a/deps/v8/src/compiler/arm/instruction-selector-arm.cc b/deps/v8/src/compiler/arm/instruction-selector-arm.cc index 47511a1ebf..276b810ed2 100644 --- a/deps/v8/src/compiler/arm/instruction-selector-arm.cc +++ b/deps/v8/src/compiler/arm/instruction-selector-arm.cc @@ -239,9 +239,8 @@ void VisitBinop(InstructionSelector* selector, Node* node, DCHECK_GE(arraysize(outputs), output_count); DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); - Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, - outputs, input_count, inputs); - if (cont->IsBranch()) instr->MarkAsControl(); + selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, + inputs); } @@ -579,9 +578,8 @@ void VisitShift(InstructionSelector* selector, Node* node, DCHECK_GE(arraysize(outputs), output_count); DCHECK_NE(kMode_None, AddressingModeField::decode(opcode)); - Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, - outputs, input_count, inputs); - if (cont->IsBranch()) instr->MarkAsControl(); + selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, + inputs); } @@ -645,6 +643,12 @@ void InstructionSelector::VisitWord32Ror(Node* node) { } +void InstructionSelector::VisitWord32Clz(Node* node) { + ArmOperandGenerator g(this); + Emit(kArmClz, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); +} + + void InstructionSelector::VisitInt32Add(Node* node) { ArmOperandGenerator g(this); Int32BinopMatcher m(node); @@ -956,6 +960,18 @@ void InstructionSelector::VisitFloat64Sub(Node* node) { ArmOperandGenerator g(this); Float64BinopMatcher m(node); if (m.left().IsMinusZero()) { + if (m.right().IsFloat64RoundDown() && + CanCover(m.node(), m.right().node())) { + if (m.right().InputAt(0)->opcode() == IrOpcode::kFloat64Sub && + CanCover(m.right().node(), m.right().InputAt(0))) { + Float64BinopMatcher mright0(m.right().InputAt(0)); + if (mright0.left().IsMinusZero()) { + Emit(kArmVrintpF64, g.DefineAsRegister(node), + g.UseRegister(mright0.right().node())); + return; + } + } + } Emit(kArmVnegF64, g.DefineAsRegister(node), g.UseRegister(m.right().node())); return; @@ -988,37 +1004,34 @@ void InstructionSelector::VisitFloat64Mod(Node* node) { } +void InstructionSelector::VisitFloat64Max(Node* node) { UNREACHABLE(); } + + +void InstructionSelector::VisitFloat64Min(Node* node) { UNREACHABLE(); } + + void InstructionSelector::VisitFloat64Sqrt(Node* node) { ArmOperandGenerator g(this); Emit(kArmVsqrtF64, g.DefineAsRegister(node), g.UseRegister(node->InputAt(0))); } -void InstructionSelector::VisitFloat64Floor(Node* node) { - DCHECK(CpuFeatures::IsSupported(ARMv8)); - VisitRRFloat64(this, kArmVfloorF64, node); -} - - -void InstructionSelector::VisitFloat64Ceil(Node* node) { - DCHECK(CpuFeatures::IsSupported(ARMv8)); - VisitRRFloat64(this, kArmVceilF64, node); +void InstructionSelector::VisitFloat64RoundDown(Node* node) { + VisitRRFloat64(this, kArmVrintmF64, node); } void InstructionSelector::VisitFloat64RoundTruncate(Node* node) { - DCHECK(CpuFeatures::IsSupported(ARMv8)); - VisitRRFloat64(this, kArmVroundTruncateF64, node); + VisitRRFloat64(this, kArmVrintzF64, node); } void InstructionSelector::VisitFloat64RoundTiesAway(Node* node) { - DCHECK(CpuFeatures::IsSupported(ARMv8)); - VisitRRFloat64(this, kArmVroundTiesAwayF64, node); + VisitRRFloat64(this, kArmVrintaF64, node); } -void InstructionSelector::VisitCall(Node* node) { +void InstructionSelector::VisitCall(Node* node, BasicBlock* handler) { ArmOperandGenerator g(this); const CallDescriptor* descriptor = OpParameter<const CallDescriptor*>(node); @@ -1043,6 +1056,13 @@ void InstructionSelector::VisitCall(Node* node) { Emit(kArmPush, g.NoOutput(), g.UseRegister(*i)); } + // Pass label of exception handler block. + CallDescriptor::Flags flags = descriptor->flags(); + if (handler != nullptr) { + flags |= CallDescriptor::kHasExceptionHandler; + buffer.instruction_args.push_back(g.Label(handler)); + } + // Select the appropriate opcode based on the call type. InstructionCode opcode; switch (descriptor->kind()) { @@ -1057,7 +1077,7 @@ void InstructionSelector::VisitCall(Node* node) { UNREACHABLE(); return; } - opcode |= MiscField::encode(descriptor->flags()); + opcode |= MiscField::encode(flags); // Emit the call instruction. InstructionOperand* first_output = @@ -1081,8 +1101,7 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node, if (cont->IsBranch()) { selector->Emit(cont->Encode(kArmVcmpF64), g.NoOutput(), g.UseRegister(m.left().node()), rhs, - g.Label(cont->true_block()), - g.Label(cont->false_block()))->MarkAsControl(); + g.Label(cont->true_block()), g.Label(cont->false_block())); } else { DCHECK(cont->IsSet()); selector->Emit(cont->Encode(kArmVcmpF64), @@ -1129,9 +1148,8 @@ void VisitWordCompare(InstructionSelector* selector, Node* node, DCHECK_GE(arraysize(inputs), input_count); DCHECK_GE(arraysize(outputs), output_count); - Instruction* instr = selector->Emit(cont->Encode(opcode), output_count, - outputs, input_count, inputs); - if (cont->IsBranch()) instr->MarkAsControl(); + selector->Emit(cont->Encode(opcode), output_count, outputs, input_count, + inputs); } @@ -1236,8 +1254,7 @@ void VisitWordCompareZero(InstructionSelector* selector, Node* user, InstructionOperand const value_operand = g.UseRegister(value); if (cont->IsBranch()) { selector->Emit(opcode, g.NoOutput(), value_operand, value_operand, - g.Label(cont->true_block()), - g.Label(cont->false_block()))->MarkAsControl(); + g.Label(cont->true_block()), g.Label(cont->false_block())); } else { selector->Emit(opcode, g.DefineAsRegister(cont->result()), value_operand, value_operand); @@ -1254,64 +1271,31 @@ void InstructionSelector::VisitBranch(Node* branch, BasicBlock* tbranch, } -void InstructionSelector::VisitSwitch(Node* node, BasicBlock* default_branch, - BasicBlock** case_branches, - int32_t* case_values, size_t case_count, - int32_t min_value, int32_t max_value) { +void InstructionSelector::VisitSwitch(Node* node, const SwitchInfo& sw) { ArmOperandGenerator g(this); InstructionOperand value_operand = g.UseRegister(node->InputAt(0)); - InstructionOperand default_operand = g.Label(default_branch); - // Note that {value_range} can be 0 if {min_value} is -2^31 and {max_value} - // is 2^31-1, so don't assume that it's non-zero below. - size_t value_range = - 1u + bit_cast<uint32_t>(max_value) - bit_cast<uint32_t>(min_value); - - // Determine whether to issue an ArchTableSwitch or an ArchLookupSwitch - // instruction. - size_t table_space_cost = 4 + value_range; + // Emit either ArchTableSwitch or ArchLookupSwitch. + size_t table_space_cost = 4 + sw.value_range; size_t table_time_cost = 3; - size_t lookup_space_cost = 3 + 2 * case_count; - size_t lookup_time_cost = case_count; - if (case_count > 0 && + size_t lookup_space_cost = 3 + 2 * sw.case_count; + size_t lookup_time_cost = sw.case_count; + if (sw.case_count > 0 && table_space_cost + 3 * table_time_cost <= lookup_space_cost + 3 * lookup_time_cost && - min_value > std::numeric_limits<int32_t>::min()) { + sw.min_value > std::numeric_limits<int32_t>::min()) { InstructionOperand index_operand = value_operand; - if (min_value) { + if (sw.min_value) { index_operand = g.TempRegister(); Emit(kArmSub | AddressingModeField::encode(kMode_Operand2_I), - index_operand, value_operand, g.TempImmediate(min_value)); - } - size_t input_count = 2 + value_range; - auto* inputs = zone()->NewArray<InstructionOperand>(input_count); - inputs[0] = index_operand; - std::fill(&inputs[1], &inputs[input_count], default_operand); - for (size_t index = 0; index < case_count; ++index) { - size_t value = case_values[index] - min_value; - BasicBlock* branch = case_branches[index]; - DCHECK_LE(0u, value); - DCHECK_LT(value + 2, input_count); - inputs[value + 2] = g.Label(branch); + index_operand, value_operand, g.TempImmediate(sw.min_value)); } - Emit(kArchTableSwitch, 0, nullptr, input_count, inputs, 0, nullptr) - ->MarkAsControl(); - return; + // Generate a table lookup. + return EmitTableSwitch(sw, index_operand); } // Generate a sequence of conditional jumps. - size_t input_count = 2 + case_count * 2; - auto* inputs = zone()->NewArray<InstructionOperand>(input_count); - inputs[0] = value_operand; - inputs[1] = default_operand; - for (size_t index = 0; index < case_count; ++index) { - int32_t value = case_values[index]; - BasicBlock* branch = case_branches[index]; - inputs[index * 2 + 2 + 0] = g.TempImmediate(value); - inputs[index * 2 + 2 + 1] = g.Label(branch); - } - Emit(kArchLookupSwitch, 0, nullptr, input_count, inputs, 0, nullptr) - ->MarkAsControl(); + return EmitLookupSwitch(sw, value_operand); } @@ -1387,6 +1371,52 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { } +void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { + ArmOperandGenerator g(this); + Emit(kArmVmovLowU32F64, g.DefineAsRegister(node), + g.UseRegister(node->InputAt(0))); +} + + +void InstructionSelector::VisitFloat64ExtractHighWord32(Node* node) { + ArmOperandGenerator g(this); + Emit(kArmVmovHighU32F64, g.DefineAsRegister(node), + g.UseRegister(node->InputAt(0))); +} + + +void InstructionSelector::VisitFloat64InsertLowWord32(Node* node) { + ArmOperandGenerator g(this); + Node* left = node->InputAt(0); + Node* right = node->InputAt(1); + if (left->opcode() == IrOpcode::kFloat64InsertHighWord32 && + CanCover(node, left)) { + left = left->InputAt(1); + Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), g.UseRegister(right), + g.UseRegister(left)); + return; + } + Emit(kArmVmovLowF64U32, g.DefineSameAsFirst(node), g.UseRegister(left), + g.UseRegister(right)); +} + + +void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) { + ArmOperandGenerator g(this); + Node* left = node->InputAt(0); + Node* right = node->InputAt(1); + if (left->opcode() == IrOpcode::kFloat64InsertLowWord32 && + CanCover(node, left)) { + left = left->InputAt(1); + Emit(kArmVmovF64U32U32, g.DefineAsRegister(node), g.UseRegister(left), + g.UseRegister(right)); + return; + } + Emit(kArmVmovHighF64U32, g.DefineSameAsFirst(node), g.UseRegister(left), + g.UseRegister(right)); +} + + // static MachineOperatorBuilder::Flags InstructionSelector::SupportedMachineOperatorFlags() { @@ -1395,8 +1425,7 @@ InstructionSelector::SupportedMachineOperatorFlags() { MachineOperatorBuilder::kUint32DivIsSafe; if (CpuFeatures::IsSupported(ARMv8)) { - flags |= MachineOperatorBuilder::kFloat64Floor | - MachineOperatorBuilder::kFloat64Ceil | + flags |= MachineOperatorBuilder::kFloat64RoundDown | MachineOperatorBuilder::kFloat64RoundTruncate | MachineOperatorBuilder::kFloat64RoundTiesAway; } |