Index: test/unittests/compiler/arm/instruction-selector-arm-unittest.cc |
diff --git a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc |
index 85e52488b478411160bc8dccfc5a055692ce21d5..8534c1c79a72d86a70636ded0f18216c4da24b30 100644 |
--- a/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc |
+++ b/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc |
@@ -31,7 +31,7 @@ std::ostream& operator<<(std::ostream& os, const DPI& dpi) { |
} |
-static const DPI kDPIs[] = { |
+const DPI kDPIs[] = { |
{&RawMachineAssembler::Word32And, "Word32And", kArmAnd, kArmAnd, kArmTst}, |
{&RawMachineAssembler::Word32Or, "Word32Or", kArmOrr, kArmOrr, kArmOrr}, |
{&RawMachineAssembler::Word32Xor, "Word32Xor", kArmEor, kArmEor, kArmTeq}, |
@@ -39,6 +39,32 @@ static const DPI kDPIs[] = { |
{&RawMachineAssembler::Int32Sub, "Int32Sub", kArmSub, kArmRsb, kArmCmp}}; |
+// Floating point arithmetic instructions. |
+struct FAI { |
+ Constructor constructor; |
+ const char* constructor_name; |
+ MachineType machine_type; |
+ ArchOpcode arch_opcode; |
+}; |
+ |
+ |
+std::ostream& operator<<(std::ostream& os, const FAI& fai) { |
+ return os << fai.constructor_name; |
+} |
+ |
+ |
+const FAI kFAIs[] = { |
+ {&RawMachineAssembler::Float32Add, "Float32Add", kMachFloat32, kArmVaddF32}, |
+ {&RawMachineAssembler::Float64Add, "Float64Add", kMachFloat64, kArmVaddF64}, |
+ {&RawMachineAssembler::Float32Sub, "Float32Sub", kMachFloat32, kArmVsubF32}, |
+ {&RawMachineAssembler::Float64Sub, "Float64Sub", kMachFloat64, kArmVsubF64}, |
+ {&RawMachineAssembler::Float32Mul, "Float32Mul", kMachFloat32, kArmVmulF32}, |
+ {&RawMachineAssembler::Float64Mul, "Float64Mul", kMachFloat64, kArmVmulF64}, |
+ {&RawMachineAssembler::Float32Div, "Float32Div", kMachFloat32, kArmVdivF32}, |
+ {&RawMachineAssembler::Float64Div, "Float64Div", kMachFloat64, |
+ kArmVdivF64}}; |
+ |
+ |
// Data processing instructions with overflow. |
struct ODPI { |
Constructor constructor; |
@@ -53,10 +79,10 @@ std::ostream& operator<<(std::ostream& os, const ODPI& odpi) { |
} |
-static const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow, |
- "Int32AddWithOverflow", kArmAdd, kArmAdd}, |
- {&RawMachineAssembler::Int32SubWithOverflow, |
- "Int32SubWithOverflow", kArmSub, kArmRsb}}; |
+const ODPI kODPIs[] = {{&RawMachineAssembler::Int32AddWithOverflow, |
+ "Int32AddWithOverflow", kArmAdd, kArmAdd}, |
+ {&RawMachineAssembler::Int32SubWithOverflow, |
+ "Int32SubWithOverflow", kArmSub, kArmRsb}}; |
// Shifts. |
@@ -75,50 +101,34 @@ std::ostream& operator<<(std::ostream& os, const Shift& shift) { |
} |
-static const Shift kShifts[] = { |
- {&RawMachineAssembler::Word32Sar, "Word32Sar", 1, 32, |
- kMode_Operand2_R_ASR_I, kMode_Operand2_R_ASR_R}, |
- {&RawMachineAssembler::Word32Shl, "Word32Shl", 0, 31, |
- kMode_Operand2_R_LSL_I, kMode_Operand2_R_LSL_R}, |
- {&RawMachineAssembler::Word32Shr, "Word32Shr", 1, 32, |
- kMode_Operand2_R_LSR_I, kMode_Operand2_R_LSR_R}, |
- {&RawMachineAssembler::Word32Ror, "Word32Ror", 1, 31, |
- kMode_Operand2_R_ROR_I, kMode_Operand2_R_ROR_R}}; |
+const Shift kShifts[] = {{&RawMachineAssembler::Word32Sar, "Word32Sar", 1, 32, |
+ kMode_Operand2_R_ASR_I, kMode_Operand2_R_ASR_R}, |
+ {&RawMachineAssembler::Word32Shl, "Word32Shl", 0, 31, |
+ kMode_Operand2_R_LSL_I, kMode_Operand2_R_LSL_R}, |
+ {&RawMachineAssembler::Word32Shr, "Word32Shr", 1, 32, |
+ kMode_Operand2_R_LSR_I, kMode_Operand2_R_LSR_R}, |
+ {&RawMachineAssembler::Word32Ror, "Word32Ror", 1, 31, |
+ kMode_Operand2_R_ROR_I, kMode_Operand2_R_ROR_R}}; |
// Immediates (random subset). |
-static const int32_t kImmediates[] = { |
+const int32_t kImmediates[] = { |
std::numeric_limits<int32_t>::min(), -2147483617, -2147483606, -2113929216, |
- -2080374784, -1996488704, -1879048192, -1459617792, |
- -1358954496, -1342177265, -1275068414, -1073741818, |
- -1073741777, -855638016, -805306368, -402653184, |
- -268435444, -16777216, 0, 35, |
- 61, 105, 116, 171, |
- 245, 255, 692, 1216, |
- 1248, 1520, 1600, 1888, |
- 3744, 4080, 5888, 8384, |
- 9344, 9472, 9792, 13312, |
- 15040, 15360, 20736, 22272, |
- 23296, 32000, 33536, 37120, |
- 45824, 47872, 56320, 59392, |
- 65280, 72704, 101376, 147456, |
- 161792, 164864, 167936, 173056, |
- 195584, 209920, 212992, 356352, |
- 655360, 704512, 716800, 851968, |
- 901120, 1044480, 1523712, 2572288, |
- 3211264, 3588096, 3833856, 3866624, |
- 4325376, 5177344, 6488064, 7012352, |
- 7471104, 14090240, 16711680, 19398656, |
- 22282240, 28573696, 30408704, 30670848, |
- 43253760, 54525952, 55312384, 56623104, |
- 68157440, 115343360, 131072000, 187695104, |
- 188743680, 195035136, 197132288, 203423744, |
- 218103808, 267386880, 268435470, 285212672, |
- 402653185, 415236096, 595591168, 603979776, |
- 603979778, 629145600, 1073741835, 1073741855, |
- 1073741861, 1073741884, 1157627904, 1476395008, |
- 1476395010, 1610612741, 2030043136, 2080374785, |
- 2097152000}; |
+ -2080374784, -1996488704, -1879048192, -1459617792, -1358954496, |
+ -1342177265, -1275068414, -1073741818, -1073741777, -855638016, -805306368, |
+ -402653184, -268435444, -16777216, 0, 35, 61, 105, 116, 171, 245, 255, 692, |
+ 1216, 1248, 1520, 1600, 1888, 3744, 4080, 5888, 8384, 9344, 9472, 9792, |
+ 13312, 15040, 15360, 20736, 22272, 23296, 32000, 33536, 37120, 45824, 47872, |
+ 56320, 59392, 65280, 72704, 101376, 147456, 161792, 164864, 167936, 173056, |
+ 195584, 209920, 212992, 356352, 655360, 704512, 716800, 851968, 901120, |
+ 1044480, 1523712, 2572288, 3211264, 3588096, 3833856, 3866624, 4325376, |
+ 5177344, 6488064, 7012352, 7471104, 14090240, 16711680, 19398656, 22282240, |
+ 28573696, 30408704, 30670848, 43253760, 54525952, 55312384, 56623104, |
+ 68157440, 115343360, 131072000, 187695104, 188743680, 195035136, 197132288, |
+ 203423744, 218103808, 267386880, 268435470, 285212672, 402653185, 415236096, |
+ 595591168, 603979776, 603979778, 629145600, 1073741835, 1073741855, |
+ 1073741861, 1073741884, 1157627904, 1476395008, 1476395010, 1610612741, |
+ 2030043136, 2080374785, 2097152000}; |
} // namespace |
@@ -1217,7 +1227,7 @@ std::ostream& operator<<(std::ostream& os, const MemoryAccess& memacc) { |
} |
-static const MemoryAccess kMemoryAccesses[] = { |
+const MemoryAccess kMemoryAccesses[] = { |
{kMachInt8, |
kArmLdrsb, |
kArmStrb, |
@@ -1482,19 +1492,100 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
// Floating point comparisons. |
-const Comparison kFPComparisons[] = { |
+namespace { |
+ |
+const Comparison kF32Comparisons[] = { |
+ {&RawMachineAssembler::Float32Equal, "Float32Equal", kEqual, kNotEqual}, |
+ {&RawMachineAssembler::Float32LessThan, "Float32LessThan", |
+ kUnsignedLessThan, kUnsignedGreaterThanOrEqual}, |
+ {&RawMachineAssembler::Float32LessThanOrEqual, "Float32LessThanOrEqual", |
+ kUnsignedLessThanOrEqual, kUnsignedGreaterThan}}; |
+ |
+} // namespace |
+ |
+typedef InstructionSelectorTestWithParam<Comparison> |
+ InstructionSelectorF32ComparisonTest; |
+ |
+ |
+TEST_P(InstructionSelectorF32ComparisonTest, WithParameters) { |
+ const Comparison& cmp = GetParam(); |
+ StreamBuilder m(this, kMachInt32, kMachFloat32, kMachFloat32); |
+ m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))); |
+ Stream const s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition()); |
+} |
+ |
+ |
+TEST_P(InstructionSelectorF32ComparisonTest, NegatedWithParameters) { |
+ const Comparison& cmp = GetParam(); |
+ StreamBuilder m(this, kMachInt32, kMachFloat32, kMachFloat32); |
+ m.Return( |
+ m.WordBinaryNot((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1)))); |
+ Stream const s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(cmp.negated_flags_condition, s[0]->flags_condition()); |
+} |
+ |
+ |
+TEST_P(InstructionSelectorF32ComparisonTest, WithImmediateZeroOnRight) { |
+ const Comparison& cmp = GetParam(); |
+ StreamBuilder m(this, kMachInt32, kMachFloat32); |
+ m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float32Constant(0.0))); |
+ Stream const s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(cmp.flags_condition, s[0]->flags_condition()); |
+} |
+ |
+ |
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
+ InstructionSelectorF32ComparisonTest, |
+ ::testing::ValuesIn(kF32Comparisons)); |
+ |
+ |
+TEST_F(InstructionSelectorTest, Float32EqualWithImmediateZeroOnLeft) { |
+ StreamBuilder m(this, kMachInt32, kMachFloat32); |
+ m.Return(m.Float32Equal(m.Float32Constant(0.0f), m.Parameter(0))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVcmpF32, s[0]->arch_opcode()); |
+ EXPECT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
+ EXPECT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
+ EXPECT_EQ(kEqual, s[0]->flags_condition()); |
+} |
+ |
+ |
+namespace { |
+ |
+const Comparison kF64Comparisons[] = { |
{&RawMachineAssembler::Float64Equal, "Float64Equal", kEqual, kNotEqual}, |
{&RawMachineAssembler::Float64LessThan, "Float64LessThan", |
kUnsignedLessThan, kUnsignedGreaterThanOrEqual}, |
{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", |
kUnsignedLessThanOrEqual, kUnsignedGreaterThan}}; |
+} // namespace |
typedef InstructionSelectorTestWithParam<Comparison> |
- InstructionSelectorFPComparisonTest; |
+ InstructionSelectorF64ComparisonTest; |
-TEST_P(InstructionSelectorFPComparisonTest, WithParameters) { |
+TEST_P(InstructionSelectorF64ComparisonTest, WithParameters) { |
const Comparison& cmp = GetParam(); |
StreamBuilder m(this, kMachInt32, kMachFloat64, kMachFloat64); |
m.Return((m.*cmp.constructor)(m.Parameter(0), m.Parameter(1))); |
@@ -1508,7 +1599,7 @@ TEST_P(InstructionSelectorFPComparisonTest, WithParameters) { |
} |
-TEST_P(InstructionSelectorFPComparisonTest, NegatedWithParameters) { |
+TEST_P(InstructionSelectorF64ComparisonTest, NegatedWithParameters) { |
const Comparison& cmp = GetParam(); |
StreamBuilder m(this, kMachInt32, kMachFloat64, kMachFloat64); |
m.Return( |
@@ -1523,7 +1614,7 @@ TEST_P(InstructionSelectorFPComparisonTest, NegatedWithParameters) { |
} |
-TEST_P(InstructionSelectorFPComparisonTest, WithImmediateZeroOnRight) { |
+TEST_P(InstructionSelectorF64ComparisonTest, WithImmediateZeroOnRight) { |
const Comparison& cmp = GetParam(); |
StreamBuilder m(this, kMachInt32, kMachFloat64); |
m.Return((m.*cmp.constructor)(m.Parameter(0), m.Float64Constant(0.0))); |
@@ -1539,8 +1630,8 @@ TEST_P(InstructionSelectorFPComparisonTest, WithImmediateZeroOnRight) { |
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
- InstructionSelectorFPComparisonTest, |
- ::testing::ValuesIn(kFPComparisons)); |
+ InstructionSelectorF64ComparisonTest, |
+ ::testing::ValuesIn(kF64Comparisons)); |
TEST_F(InstructionSelectorTest, Float64EqualWithImmediateZeroOnLeft) { |
@@ -1558,7 +1649,141 @@ TEST_F(InstructionSelectorTest, Float64EqualWithImmediateZeroOnLeft) { |
// ----------------------------------------------------------------------------- |
-// Miscellaneous. |
+// Floating point arithmetic. |
+ |
+ |
+typedef InstructionSelectorTestWithParam<FAI> InstructionSelectorFAITest; |
+ |
+ |
+TEST_P(InstructionSelectorFAITest, Parameters) { |
+ const FAI& fai = GetParam(); |
+ StreamBuilder m(this, fai.machine_type, fai.machine_type, fai.machine_type); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const p1 = m.Parameter(1); |
+ Node* const r = (m.*fai.constructor)(p0, p1); |
+ m.Return(r); |
+ Stream const s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(fai.arch_opcode, s[0]->arch_opcode()); |
+ EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
+ ASSERT_EQ(2U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(s.ToVreg(r), s.ToVreg(s[0]->OutputAt(0))); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+} |
+ |
+ |
+INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFAITest, |
+ ::testing::ValuesIn(kFAIs)); |
+ |
+ |
+TEST_F(InstructionSelectorTest, Float32AddWithFloat32Mul) { |
+ { |
+ StreamBuilder m(this, kMachFloat32, kMachFloat32, kMachFloat32, |
+ kMachFloat32); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const p1 = m.Parameter(1); |
+ Node* const p2 = m.Parameter(2); |
+ Node* const n = m.Float32Add(m.Float32Mul(p0, p1), p2); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode()); |
+ ASSERT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0))); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); |
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_TRUE( |
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+ } |
+ { |
+ StreamBuilder m(this, kMachFloat32, kMachFloat32, kMachFloat32, |
+ kMachFloat32); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const p1 = m.Parameter(1); |
+ Node* const p2 = m.Parameter(2); |
+ Node* const n = m.Float32Add(p0, m.Float32Mul(p1, p2)); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVmlaF32, s[0]->arch_opcode()); |
+ ASSERT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_TRUE( |
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+ } |
+} |
+ |
+ |
+TEST_F(InstructionSelectorTest, Float64AddWithFloat64Mul) { |
+ { |
+ StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64, |
+ kMachFloat64); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const p1 = m.Parameter(1); |
+ Node* const p2 = m.Parameter(2); |
+ Node* const n = m.Float64Add(m.Float64Mul(p0, p1), p2); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode()); |
+ ASSERT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(0))); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(1))); |
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(2))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_TRUE( |
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+ } |
+ { |
+ StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64, |
+ kMachFloat64); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const p1 = m.Parameter(1); |
+ Node* const p2 = m.Parameter(2); |
+ Node* const n = m.Float64Add(p0, m.Float64Mul(p1, p2)); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVmlaF64, s[0]->arch_opcode()); |
+ ASSERT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_TRUE( |
+ UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+ } |
+} |
+ |
+ |
+TEST_F(InstructionSelectorTest, Float32SubWithMinusZero) { |
+ StreamBuilder m(this, kMachFloat32, kMachFloat32); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const n = m.Float32Sub(m.Float32Constant(-0.0f), p0); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVnegF32, s[0]->arch_opcode()); |
+ ASSERT_EQ(1U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+} |
TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) { |
@@ -1576,6 +1801,84 @@ TEST_F(InstructionSelectorTest, Float64SubWithMinusZero) { |
} |
+TEST_F(InstructionSelectorTest, Float32SubWithFloat32Mul) { |
+ StreamBuilder m(this, kMachFloat32, kMachFloat32, kMachFloat32, kMachFloat32); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const p1 = m.Parameter(1); |
+ Node* const p2 = m.Parameter(2); |
+ Node* const n = m.Float32Sub(p0, m.Float32Mul(p1, p2)); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVmlsF32, s[0]->arch_opcode()); |
+ ASSERT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+} |
+ |
+ |
+TEST_F(InstructionSelectorTest, Float64SubWithFloat64Mul) { |
+ StreamBuilder m(this, kMachFloat64, kMachFloat64, kMachFloat64, kMachFloat64); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const p1 = m.Parameter(1); |
+ Node* const p2 = m.Parameter(2); |
+ Node* const n = m.Float64Sub(p0, m.Float64Mul(p1, p2)); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVmlsF64, s[0]->arch_opcode()); |
+ ASSERT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1))); |
+ EXPECT_EQ(s.ToVreg(p2), s.ToVreg(s[0]->InputAt(2))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_TRUE(UnallocatedOperand::cast(s[0]->Output())->HasSameAsInputPolicy()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+} |
+ |
+ |
+TEST_F(InstructionSelectorTest, Float32Sqrt) { |
+ StreamBuilder m(this, kMachFloat32, kMachFloat32); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const n = m.Float32Sqrt(p0); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVsqrtF32, s[0]->arch_opcode()); |
+ ASSERT_EQ(1U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+} |
+ |
+ |
+TEST_F(InstructionSelectorTest, Float64Sqrt) { |
+ StreamBuilder m(this, kMachFloat64, kMachFloat64); |
+ Node* const p0 = m.Parameter(0); |
+ Node* const n = m.Float64Sqrt(p0); |
+ m.Return(n); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArmVsqrtF64, s[0]->arch_opcode()); |
+ ASSERT_EQ(1U, s[0]->InputCount()); |
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0))); |
+ ASSERT_EQ(1U, s[0]->OutputCount()); |
+ EXPECT_EQ(s.ToVreg(n), s.ToVreg(s[0]->Output())); |
+ EXPECT_EQ(kFlags_none, s[0]->flags_mode()); |
+} |
+ |
+ |
+// ----------------------------------------------------------------------------- |
+// Miscellaneous. |
+ |
+ |
TEST_F(InstructionSelectorTest, Int32AddWithInt32Mul) { |
{ |
StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32, kMachInt32); |