Index: src/compiler/arm64/instruction-selector-arm64.cc |
diff --git a/src/compiler/arm64/instruction-selector-arm64.cc b/src/compiler/arm64/instruction-selector-arm64.cc |
index fbc7df27e3157e33347a507d9769b86245865c5a..88b77fff488716d5797ea70089a104d6ce77d12a 100644 |
--- a/src/compiler/arm64/instruction-selector-arm64.cc |
+++ b/src/compiler/arm64/instruction-selector-arm64.cc |
@@ -1343,18 +1343,6 @@ void InstructionSelector::VisitFloat64Mod(Node* node) { |
} |
-void InstructionSelector::VisitFloat32Max(Node* node) { UNREACHABLE(); } |
- |
- |
-void InstructionSelector::VisitFloat64Max(Node* node) { UNREACHABLE(); } |
- |
- |
-void InstructionSelector::VisitFloat32Min(Node* node) { UNREACHABLE(); } |
- |
- |
-void InstructionSelector::VisitFloat64Min(Node* node) { UNREACHABLE(); } |
- |
- |
void InstructionSelector::VisitFloat32Abs(Node* node) { |
VisitRR(this, kArm64Float32Abs, node); |
} |
@@ -1601,6 +1589,21 @@ void VisitCompare(InstructionSelector* selector, InstructionCode opcode, |
} |
+// Shared routine for multiple compare-and-select operations. |
+void VisitCompareAndSelect(InstructionSelector* selector, |
+ InstructionCode opcode, InstructionOperand cmp_left, |
+ InstructionOperand cmp_right, |
+ InstructionOperand if_true, |
+ InstructionOperand if_false, |
+ FlagsContinuation* cont) { |
+ Arm64OperandGenerator g(selector); |
+ opcode = cont->Encode(opcode); |
+ DCHECK(cont->IsSelect()); |
+ selector->Emit(opcode, g.DefineAsRegister(cont->result()), cmp_left, |
+ cmp_right, if_true, if_false); |
+} |
+ |
+ |
// Shared routine for multiple word compare operations. |
void VisitWordCompare(InstructionSelector* selector, Node* node, |
InstructionCode opcode, FlagsContinuation* cont, |
@@ -1651,7 +1654,7 @@ void VisitWord64Test(InstructionSelector* selector, Node* node, |
} |
-// Shared routine for multiple float64 compare operations. |
+// Shared routine for multiple float32 compare operations. |
void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
FlagsContinuation* cont) { |
Arm64OperandGenerator g(selector); |
@@ -1666,6 +1669,24 @@ void VisitFloat32Compare(InstructionSelector* selector, Node* node, |
} |
+void VisitFloat32CompareAndSelect(InstructionSelector* selector, Node* node, |
+ InstructionCode opcode, Node* cmp_left, |
+ Node* cmp_right, Node* sel_true, |
+ Node* sel_false, FlagsContinuation* cont) { |
+ // (cmp_left <op> cmp_right) ? sel_true : sel_false |
+ Arm64OperandGenerator g(selector); |
+ if (Float32Matcher(cmp_right).Is(0.0f)) { |
+ VisitCompareAndSelect(selector, opcode, g.UseRegister(cmp_left), |
+ g.UseImmediate(cmp_right), g.UseRegister(sel_true), |
+ g.UseRegister(sel_false), cont); |
+ } else { |
+ VisitCompareAndSelect(selector, opcode, g.UseRegister(cmp_left), |
+ g.UseRegister(cmp_right), g.UseRegister(sel_true), |
+ g.UseRegister(sel_false), cont); |
+ } |
+} |
+ |
+ |
// Shared routine for multiple float64 compare operations. |
void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
FlagsContinuation* cont) { |
@@ -1680,6 +1701,24 @@ void VisitFloat64Compare(InstructionSelector* selector, Node* node, |
} |
} |
+ |
+void VisitFloat64CompareAndSelect(InstructionSelector* selector, Node* node, |
+ InstructionCode opcode, Node* cmp_left, |
+ Node* cmp_right, Node* sel_true, |
+ Node* sel_false, FlagsContinuation* cont) { |
+ // (cmp_left <op> cmp_right) ? sel_true : sel_false |
+ Arm64OperandGenerator g(selector); |
+ if (Float64Matcher(cmp_right).Is(0.0)) { |
+ VisitCompareAndSelect(selector, opcode, g.UseRegister(cmp_left), |
+ g.UseImmediate(cmp_right), g.UseRegister(sel_true), |
+ g.UseRegister(sel_false), cont); |
+ } else { |
+ VisitCompareAndSelect(selector, opcode, g.UseRegister(cmp_left), |
+ g.UseRegister(cmp_right), g.UseRegister(sel_true), |
+ g.UseRegister(sel_false), cont); |
+ } |
+} |
+ |
} // namespace |
@@ -2027,6 +2066,42 @@ void InstructionSelector::VisitFloat64LessThanOrEqual(Node* node) { |
} |
+void InstructionSelector::VisitFloat32Max(Node* node) { |
+ // (b < a) ? a : b |
+ FlagsContinuation cont(kUnsignedLessThan, node, kFlags_select); |
+ VisitFloat32CompareAndSelect(this, node, kArm64Float32CmpAndFloat32Sel, |
+ node->InputAt(1), node->InputAt(0), |
+ node->InputAt(0), node->InputAt(1), &cont); |
+} |
+ |
+ |
+void InstructionSelector::VisitFloat32Min(Node* node) { |
+ // (a < b) ? a : b |
+ FlagsContinuation cont(kUnsignedLessThan, node, kFlags_select); |
+ VisitFloat32CompareAndSelect(this, node, kArm64Float32CmpAndFloat32Sel, |
+ node->InputAt(0), node->InputAt(1), |
+ node->InputAt(0), node->InputAt(1), &cont); |
+} |
+ |
+ |
+void InstructionSelector::VisitFloat64Max(Node* node) { |
+ // (b < a) ? a : b |
+ FlagsContinuation cont(kUnsignedLessThan, node, kFlags_select); |
+ VisitFloat64CompareAndSelect(this, node, kArm64Float64CmpAndFloat64Sel, |
+ node->InputAt(1), node->InputAt(0), |
+ node->InputAt(0), node->InputAt(1), &cont); |
+} |
+ |
+ |
+void InstructionSelector::VisitFloat64Min(Node* node) { |
+ // (a < b) ? a : b |
+ FlagsContinuation cont(kUnsignedLessThan, node, kFlags_select); |
+ VisitFloat64CompareAndSelect(this, node, kArm64Float64CmpAndFloat64Sel, |
+ node->InputAt(0), node->InputAt(1), |
+ node->InputAt(0), node->InputAt(1), &cont); |
+} |
+ |
+ |
void InstructionSelector::VisitFloat64ExtractLowWord32(Node* node) { |
Arm64OperandGenerator g(this); |
Emit(kArm64Float64ExtractLowWord32, g.DefineAsRegister(node), |
@@ -2079,7 +2154,11 @@ void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) { |
// static |
MachineOperatorBuilder::Flags |
InstructionSelector::SupportedMachineOperatorFlags() { |
- return MachineOperatorBuilder::kFloat64RoundDown | |
+ return MachineOperatorBuilder::kFloat32Max | |
+ MachineOperatorBuilder::kFloat32Min | |
+ MachineOperatorBuilder::kFloat64Max | |
+ MachineOperatorBuilder::kFloat64Min | |
+ MachineOperatorBuilder::kFloat64RoundDown | |
MachineOperatorBuilder::kFloat64RoundTruncate | |
MachineOperatorBuilder::kFloat64RoundTiesAway | |
MachineOperatorBuilder::kWord32ShiftIsSafe | |