summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/arm/instruction-selector-arm.cc
diff options
context:
space:
mode:
authorChris Dickinson <christopher.s.dickinson@gmail.com>2015-05-05 13:48:55 -0700
committerRod Vagg <rod@vagg.org>2015-08-04 11:56:09 -0700
commitd58e780504bdba6c5897c48428fd984c5b5f96fe (patch)
tree033f1568ae3f9f077aceb843b42eb1ed1739ce0f /deps/v8/src/compiler/arm/instruction-selector-arm.cc
parent21d31c08e7d0b6865e52452750b20b05e6dca443 (diff)
downloadnode-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.cc179
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;
}