Chromium Code Reviews| Index: src/compiler/mips/instruction-selector-mips-unittest.cc |
| diff --git a/src/compiler/mips/instruction-selector-mips-unittest.cc b/src/compiler/mips/instruction-selector-mips-unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..34e799d6b62636f627a408ba0680f0d2e0cf18ac |
| --- /dev/null |
| +++ b/src/compiler/mips/instruction-selector-mips-unittest.cc |
| @@ -0,0 +1,798 @@ |
| +// Copyright 2014 the V8 project authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file |
| + |
| +#include "src/compiler/instruction-selector-unittest.h" |
| + |
| +namespace v8 { |
| +namespace internal { |
| +namespace compiler { |
| + |
| +namespace { |
| + |
| +template <typename T> |
| +struct MachInst { |
| + T constructor; |
| + const char* constructor_name; |
| + ArchOpcode arch_opcode; |
| + MachineType machine_type; |
| +}; |
| + |
|
Benedikt Meurer
2014/09/25 05:37:11
You should add std::ostream& operator<<(std::ostre
paul.l...
2014/09/25 17:18:39
Done.
|
| +typedef MachInst<Node* (RawMachineAssembler::*)(Node*)> MachInst1; |
| +typedef MachInst<Node* (RawMachineAssembler::*)(Node*, Node*)> MachInst2; |
| + |
| +// To avoid duplicated code IntCmp helper structure |
| +// is created. It contains MachInst2 with two nodes and expected_size |
| +// because different cmp instructions have different size. |
| +struct IntCmp { |
| + MachInst2 mi; |
| + uint32_t expected_size; |
| +}; |
| + |
| +struct FPCmp { |
| + MachInst2 mi; |
| + FlagsCondition cond; |
| +}; |
| + |
| +static const FPCmp kFPCmpInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
|
| + {{&RawMachineAssembler::Float64Equal, "Float64Equal", kMipsFloat64Cmp, |
| + kMachFloat64}, |
| + kUnorderedEqual}, |
| + {{&RawMachineAssembler::Float64LessThan, "Float64LessThan", kMipsFloat64Cmp, |
| + kMachFloat64}, |
| + kUnorderedLessThan}, |
| + {{&RawMachineAssembler::Float64LessThanOrEqual, "Float64LessThanOrEqual", |
| + kMipsFloat64Cmp, kMachFloat64}, |
| + kUnorderedLessThanOrEqual}, |
| + {{&RawMachineAssembler::Float64GreaterThan, "Float64GreaterThan", |
| + kMipsFloat64Cmp, kMachFloat64}, |
| + kUnorderedLessThan}, |
| + {{&RawMachineAssembler::Float64GreaterThanOrEqual, |
| + "Float64GreaterThanOrEqual", kMipsFloat64Cmp, kMachFloat64}, |
| + kUnorderedLessThanOrEqual}}; |
| + |
| +struct Conversion { |
| + // The machine_type field in MachInst1 represents the destination type. |
| + MachInst1 mi; |
| + MachineType src_machine_type; |
| +}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Logical instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const MachInst2 kLogicalInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:40
Done.
|
| + {&RawMachineAssembler::WordAnd, "WordAnd", kMipsAnd, kMachInt16}, |
| + {&RawMachineAssembler::WordOr, "WordOr", kMipsOr, kMachInt16}, |
| + {&RawMachineAssembler::WordXor, "WordXor", kMipsXor, kMachInt16}, |
| + {&RawMachineAssembler::Word32And, "Word32And", kMipsAnd, kMachInt32}, |
| + {&RawMachineAssembler::Word32Or, "Word32Or", kMipsOr, kMachInt32}, |
| + {&RawMachineAssembler::Word32Xor, "Word32Xor", kMipsXor, kMachInt32}}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Shift instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const MachInst2 kShiftInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
|
| + {&RawMachineAssembler::WordShl, "WordShl", kMipsShl, kMachInt16}, |
| + {&RawMachineAssembler::WordShr, "WordShr", kMipsShr, kMachInt16}, |
| + {&RawMachineAssembler::WordSar, "WordSar", kMipsSar, kMachInt16}, |
| + {&RawMachineAssembler::WordRor, "WordRor", kMipsRor, kMachInt16}, |
| + {&RawMachineAssembler::Word32Shl, "Word32Shl", kMipsShl, kMachInt32}, |
| + {&RawMachineAssembler::Word32Shr, "Word32Shr", kMipsShr, kMachInt32}, |
| + {&RawMachineAssembler::Word32Sar, "Word32Sar", kMipsSar, kMachInt32}, |
| + {&RawMachineAssembler::Word32Ror, "Word32Ror", kMipsRor, kMachInt32}}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// MUL/DIV instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const MachInst2 kMulDivInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
|
| + {&RawMachineAssembler::Int32Mul, "Int32Mul", kMipsMul, kMachInt32}, |
| + {&RawMachineAssembler::Int32Div, "Int32Div", kMipsDiv, kMachInt32}, |
| + {&RawMachineAssembler::Int32UDiv, "Int32UDiv", kMipsDivU, kMachUint32}, |
| + {&RawMachineAssembler::Float64Mul, "Float64Mul", kMipsFloat64Mul, |
| + kMachFloat64}, |
| + {&RawMachineAssembler::Float64Div, "Float64Div", kMipsFloat64Div, |
| + kMachFloat64}}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// MOD instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const MachInst2 kModInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
|
| + {&RawMachineAssembler::Int32Mod, "Int32Mod", kMipsMod, kMachInt32}, |
| + {&RawMachineAssembler::Int32UMod, "Int32UMod", kMipsModU, kMachInt32}, |
| + {&RawMachineAssembler::Float64Mod, "Float64Mod", kMipsFloat64Mod, |
| + kMachFloat64}}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Arithmetic FPU instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const MachInst2 kFPArithInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
|
| + {&RawMachineAssembler::Float64Add, "Float64Add", kMipsFloat64Add, |
| + kMachFloat64}, |
| + {&RawMachineAssembler::Float64Sub, "Float64Sub", kMipsFloat64Sub, |
| + kMachFloat64}}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// IntArithTest instructions, two nodes. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const MachInst2 kAddSubInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
|
| + {&RawMachineAssembler::Int32Add, "Int32Add", kMipsAdd, kMachInt32}, |
| + {&RawMachineAssembler::Int32Sub, "Int32Sub", kMipsSub, kMachInt32}, |
| + {&RawMachineAssembler::Int32AddWithOverflow, "Int32AddWithOverflow", |
| + kMipsAddOvf, kMachInt32}, |
| + {&RawMachineAssembler::Int32SubWithOverflow, "Int32SubWithOverflow", |
| + kMipsSubOvf, kMachInt32}}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// IntArithTest instructions, one node. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const MachInst1 kAddSubOneInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
|
| + {&RawMachineAssembler::Int32Neg, "Int32Neg", kMipsSub, kMachInt32}, |
| + // TODO(dusmil): check this ... |
| + // {&RawMachineAssembler::WordEqual , "WordEqual" , kMipsTst, kMachInt32} |
| +}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Arithmetic compare instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const IntCmp kCmpInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:39
Done.
|
| + {{&RawMachineAssembler::WordEqual, "WordEqual", kMipsCmp, kMachInt16}, 1U}, |
| + {{&RawMachineAssembler::WordNotEqual, "WordNotEqual", kMipsCmp, kMachInt16}, |
| + 2U}, |
| + {{&RawMachineAssembler::Word32Equal, "Word32Equal", kMipsCmp, kMachInt32}, |
| + 1U}, |
| + {{&RawMachineAssembler::Word32NotEqual, "Word32NotEqual", kMipsCmp, |
| + kMachInt32}, |
| + 2U}, |
| + {{&RawMachineAssembler::Int32LessThan, "Int32LessThan", kMipsCmp, |
| + kMachInt32}, |
| + 1U}, |
| + {{&RawMachineAssembler::Int32LessThanOrEqual, "Int32LessThanOrEqual", |
| + kMipsCmp, kMachInt32}, |
| + 1U}, |
| + {{&RawMachineAssembler::Int32GreaterThan, "Int32GreaterThan", kMipsCmp, |
| + kMachInt32}, |
| + 1U}, |
| + {{&RawMachineAssembler::Int32GreaterThanOrEqual, "Int32GreaterThanOrEqual", |
| + kMipsCmp, kMachInt32}, |
| + 1U}, |
| + {{&RawMachineAssembler::Uint32LessThan, "Uint32LessThan", kMipsCmp, |
| + kMachUint32}, |
| + 1U}, |
| + {{&RawMachineAssembler::Uint32LessThanOrEqual, "Uint32LessThanOrEqual", |
| + kMipsCmp, kMachUint32}, |
| + 1U}}; |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Conversion instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| +static const Conversion kConversionInstructions[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: no need to use static, it's in an anonymous n
paul.l...
2014/09/25 17:18:40
Done.
|
| + // Conversion instructions are related to machine_operator.h: |
| + // FPU conversions: |
| + // Convert representation of integers between float64 and int32/uint32. |
| + // The precise rounding mode and handling of out of range inputs are *not* |
| + // defined for these operators, since they are intended only for use with |
| + // integers. |
| + // mips instruction: cvt_d_w |
| + {{&RawMachineAssembler::ChangeInt32ToFloat64, "ChangeInt32ToFloat64", |
| + kMipsInt32ToFloat64, kMachFloat64}, |
| + kMachInt32}, |
| + |
| + // mips instruction: cvt_d_uw |
| + {{&RawMachineAssembler::ChangeUint32ToFloat64, "ChangeUint32ToFloat64", |
| + kMipsUint32ToFloat64, kMachFloat64}, |
| + kMachInt32}, |
| + |
| + // mips instruction: trunc_w_d |
| + {{&RawMachineAssembler::ChangeFloat64ToInt32, "ChangeFloat64ToInt32", |
| + kMipsFloat64ToInt32, kMachFloat64}, |
| + kMachInt32}, |
| + |
| + // mips instruction: trunc_uw_d |
| + {{&RawMachineAssembler::ChangeFloat64ToUint32, "ChangeFloat64ToUint32", |
| + kMipsFloat64ToUint32, kMachFloat64}, |
| + kMachInt32}}; |
| + |
| +} // namespace |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<FPCmp> InstructionSelectorFPCmpTest; |
| + |
| + |
| +TEST_P(InstructionSelectorFPCmpTest, Parameter) { |
| + const FPCmp cmp = GetParam(); |
| + StreamBuilder m(this, kMachInt32, cmp.mi.machine_type, cmp.mi.machine_type); |
| + m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| + EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| + EXPECT_EQ(cmp.cond, s[0]->flags_condition()); |
| +} |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPCmpTest, |
| + ::testing::ValuesIn(kFPCmpInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Arithmetic compare instructions integers. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<IntCmp> InstructionSelectorCmpTest; |
| + |
| + |
| +TEST_P(InstructionSelectorCmpTest, Parameter) { |
| + const IntCmp cmp = GetParam(); |
| + const MachineType type = cmp.mi.machine_type; |
| + StreamBuilder m(this, type, type, type); |
| + m.Return((m.*cmp.mi.constructor)(m.Parameter(0), m.Parameter(1))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(cmp.expected_size, s.size()); |
| + EXPECT_EQ(cmp.mi.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorCmpTest, |
| + ::testing::ValuesIn(kCmpInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Shift instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MachInst2> |
| + InstructionSelectorShiftTest; |
| + |
| + |
| +TEST_P(InstructionSelectorShiftTest, Immediate) { |
| + const MachInst2 dpi = GetParam(); |
| + const MachineType type = dpi.machine_type; |
| + TRACED_FORRANGE(int32_t, imm, 0, (ElementSizeOf(type) * 8) - 1) { |
| + StreamBuilder m(this, type, type); |
| + m.Return((m.*dpi.constructor)(m.Parameter(0), m.Int32Constant(imm))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_TRUE(s[0]->InputAt(1)->IsImmediate()); |
| + EXPECT_EQ(imm, s.ToInt32(s[0]->InputAt(1))); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| + } |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorShiftTest, |
| + ::testing::ValuesIn(kShiftInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Logical instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MachInst2> |
| + InstructionSelectorLogicalTest; |
| + |
| + |
| +TEST_P(InstructionSelectorLogicalTest, Parameter) { |
| + const MachInst2 dpi = GetParam(); |
| + const MachineType type = dpi.machine_type; |
| + StreamBuilder m(this, type, type, type); |
| + m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, |
| + ::testing::ValuesIn(kLogicalInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// MUL/DIV instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MachInst2> |
| + InstructionSelectorMulDivTest; |
| + |
| + |
| +TEST_P(InstructionSelectorMulDivTest, Parameter) { |
| + const MachInst2 dpi = GetParam(); |
| + const MachineType type = dpi.machine_type; |
| + StreamBuilder m(this, type, type, type); |
| + m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorMulDivTest, |
| + ::testing::ValuesIn(kMulDivInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// MOD instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MachInst2> InstructionSelectorModTest; |
| + |
| + |
| +TEST_P(InstructionSelectorModTest, Parameter) { |
| + const MachInst2 dpi = GetParam(); |
| + const MachineType type = dpi.machine_type; |
| + StreamBuilder m(this, type, type, type); |
| + m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorModTest, |
| + ::testing::ValuesIn(kModInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Floating point instructions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MachInst2> |
| + InstructionSelectorFPArithTest; |
| + |
| + |
| +TEST_P(InstructionSelectorFPArithTest, Parameter) { |
| + const MachInst2 fpa = GetParam(); |
| + StreamBuilder m(this, fpa.machine_type, fpa.machine_type, fpa.machine_type); |
| + m.Return((m.*fpa.constructor)(m.Parameter(0), m.Parameter(1))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(fpa.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorFPArithTest, |
| + ::testing::ValuesIn(kFPArithInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Integer arithmetic. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MachInst2> |
| + InstructionSelectorIntArithTwoTest; |
| + |
| + |
| +TEST_P(InstructionSelectorIntArithTwoTest, Parameter) { |
| + const MachInst2 intpa = GetParam(); |
| + StreamBuilder m(this, intpa.machine_type, intpa.machine_type, |
| + intpa.machine_type); |
| + m.Return((m.*intpa.constructor)(m.Parameter(0), m.Parameter(1))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| + InstructionSelectorIntArithTwoTest, |
| + ::testing::ValuesIn(kAddSubInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// One node. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MachInst1> |
| + InstructionSelectorIntArithOneTest; |
| + |
| + |
| +TEST_P(InstructionSelectorIntArithOneTest, Parameter) { |
| + const MachInst1 intpa = GetParam(); |
| + StreamBuilder m(this, intpa.machine_type, intpa.machine_type, |
| + intpa.machine_type); |
| + m.Return((m.*intpa.constructor)(m.Parameter(0))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(intpa.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| + InstructionSelectorIntArithOneTest, |
| + ::testing::ValuesIn(kAddSubOneInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Conversions. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<Conversion> |
| + InstructionSelectorConversionTest; |
| + |
| + |
| +TEST_P(InstructionSelectorConversionTest, Parameter) { |
| + const Conversion conv = GetParam(); |
| + StreamBuilder m(this, conv.mi.machine_type, conv.src_machine_type); |
| + m.Return((m.*conv.mi.constructor)(m.Parameter(0))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(conv.mi.arch_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(1U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| + InstructionSelectorConversionTest, |
| + ::testing::ValuesIn(kConversionInstructions)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Loads and stores. |
| +// ---------------------------------------------------------------------------- |
| + |
| +namespace { |
| + |
| +struct MemoryAccess { |
| + MachineType type; |
| + ArchOpcode load_opcode; |
| + ArchOpcode store_opcode; |
| +}; |
| + |
| + |
| +static const MemoryAccess kMemoryAccesses[] = { |
| + {kMachInt8, kMipsLb, kMipsSb}, |
| + {kMachUint8, kMipsLbu, kMipsSb}, |
| + {kMachInt16, kMipsLh, kMipsSh}, |
| + {kMachUint16, kMipsLhu, kMipsSh}, |
| + {kMachInt32, kMipsLw, kMipsSw}, |
| + {kRepFloat32, kMipsLwc1, kMipsSwc1}, |
| + {kRepFloat64, kMipsLdc1, kMipsSdc1}}; |
| + |
| + |
| +struct MemoryAccessImm { |
| + MachineType type; |
| + ArchOpcode load_opcode; |
| + ArchOpcode store_opcode; |
| + bool (InstructionSelectorTest::Stream::*val_predicate)( |
| + const InstructionOperand*) const; |
| + const int32_t immediates[40]; |
| +}; |
| + |
|
Benedikt Meurer
2014/09/25 05:37:11
You should add
std::ostream& operator<<(std::ostr
paul.l...
2014/09/25 17:18:39
Done.
|
| + |
| +struct MemoryAccessImm1 { |
| + MachineType type; |
| + ArchOpcode load_opcode; |
| + ArchOpcode store_opcode; |
| + bool (InstructionSelectorTest::Stream::*val_predicate)( |
| + const InstructionOperand*) const; |
| + const int32_t immediates[5]; |
| +}; |
| + |
|
Benedikt Meurer
2014/09/25 05:37:11
Stream operator, see above.
paul.l...
2014/09/25 17:18:39
Done.
|
| + |
| +// ---------------------------------------------------------------------------- |
| +// Loads and stores immediate values. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +static const MemoryAccessImm kMemoryAccessesImm[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: static, see above.
paul.l...
2014/09/25 17:18:40
Done.
|
| + {kMachInt8, |
| + kMipsLb, |
| + kMipsSb, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| + -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| + 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
| + {kMachUint8, |
| + kMipsLbu, |
| + kMipsSb, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| + -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| + 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
| + {kMachInt16, |
| + kMipsLh, |
| + kMipsSh, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| + -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| + 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
| + {kMachUint16, |
| + kMipsLhu, |
| + kMipsSh, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| + -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| + 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
| + {kMachInt32, |
| + kMipsLw, |
| + kMipsSw, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| + -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| + 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
| + {kMachFloat32, |
| + kMipsLwc1, |
| + kMipsSwc1, |
| + &InstructionSelectorTest::Stream::IsDouble, |
| + {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| + -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| + 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}, |
| + {kMachFloat64, |
| + kMipsLdc1, |
| + kMipsSdc1, |
| + &InstructionSelectorTest::Stream::IsDouble, |
| + {-4095, -3340, -3231, -3224, -3088, -1758, -1203, -123, -117, -91, -89, |
| + -87, -86, -82, -44, -23, -3, 0, 7, 10, 39, 52, 69, 71, 91, 92, 107, 109, |
| + 115, 124, 286, 655, 1362, 1569, 2587, 3067, 3096, 3462, 3510, 4095}}}; |
| + |
| + |
| +static const MemoryAccessImm1 kMemoryAccessImmMoreThan16bit[] = { |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: static, see above.
paul.l...
2014/09/25 17:18:39
Done.
|
| + {kMachInt8, |
| + kMipsLb, |
| + kMipsSb, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-65000, -55000, 32777, 55000, 65000}}, |
| + {kMachInt8, |
| + kMipsLbu, |
| + kMipsSb, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-65000, -55000, 32777, 55000, 65000}}, |
| + {kMachInt16, |
| + kMipsLh, |
| + kMipsSh, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-65000, -55000, 32777, 55000, 65000}}, |
| + {kMachInt16, |
| + kMipsLhu, |
| + kMipsSh, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-65000, -55000, 32777, 55000, 65000}}, |
| + {kMachInt32, |
| + kMipsLw, |
| + kMipsSw, |
| + &InstructionSelectorTest::Stream::IsInteger, |
| + {-65000, -55000, 32777, 55000, 65000}}, |
| + {kMachFloat32, |
| + kMipsLwc1, |
| + kMipsSwc1, |
| + &InstructionSelectorTest::Stream::IsDouble, |
| + {-65000, -55000, 32777, 55000, 65000}}, |
| + {kMachFloat64, |
| + kMipsLdc1, |
| + kMipsSdc1, |
| + &InstructionSelectorTest::Stream::IsDouble, |
| + {-65000, -55000, 32777, 55000, 65000}}}; |
| + |
| +} // namespace |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MemoryAccess> |
| + InstructionSelectorMemoryAccessTest; |
| + |
| + |
| +TEST_P(InstructionSelectorMemoryAccessTest, LoadWithParameters) { |
| + const MemoryAccess memacc = GetParam(); |
| + StreamBuilder m(this, memacc.type, kMachPtr, kMachInt32); |
| + m.Return(m.Load(memacc.type, m.Parameter(0))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| +} |
| + |
| + |
| +TEST_P(InstructionSelectorMemoryAccessTest, StoreWithParameters) { |
| + const MemoryAccess memacc = GetParam(); |
| + StreamBuilder m(this, kMachInt32, kMachPtr, kMachInt32, memacc.type); |
| + m.Store(memacc.type, m.Parameter(0), m.Parameter(1)); |
| + m.Return(m.Int32Constant(0)); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| + InstructionSelectorMemoryAccessTest, |
| + ::testing::ValuesIn(kMemoryAccesses)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Load immediate. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MemoryAccessImm> |
| + InstructionSelectorMemoryAccessImmTest; |
| + |
| + |
| +TEST_P(InstructionSelectorMemoryAccessImmTest, LoadWithImmediateIndex) { |
| + const MemoryAccessImm memacc = GetParam(); |
| + TRACED_FOREACH(int32_t, index, memacc.immediates) { |
| + StreamBuilder m(this, memacc.type, kMachPtr); |
| + m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(memacc.load_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| + ASSERT_EQ(2U, s[0]->InputCount()); |
| + ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| + EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
| + ASSERT_EQ(1U, s[0]->OutputCount()); |
| + EXPECT_TRUE((s.*memacc.val_predicate)(s[0]->Output())); |
| + } |
| +} |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Store immediate. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +TEST_P(InstructionSelectorMemoryAccessImmTest, StoreWithImmediateIndex) { |
| + const MemoryAccessImm memacc = GetParam(); |
| + TRACED_FOREACH(int32_t, index, memacc.immediates) { |
| + StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); |
| + m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), |
| + m.Parameter(1)); |
| + m.Return(m.Int32Constant(0)); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(memacc.store_opcode, s[0]->arch_opcode()); |
| + EXPECT_EQ(kMode_MRI, s[0]->addressing_mode()); |
| + ASSERT_EQ(3U, s[0]->InputCount()); |
| + ASSERT_EQ(InstructionOperand::IMMEDIATE, s[0]->InputAt(1)->kind()); |
| + EXPECT_EQ(index, s.ToInt32(s[0]->InputAt(1))); |
| + EXPECT_EQ(0U, s[0]->OutputCount()); |
| + } |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| + InstructionSelectorMemoryAccessImmTest, |
| + ::testing::ValuesIn(kMemoryAccessesImm)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// Load/store offsets more than 16 bits. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +typedef InstructionSelectorTestWithParam<MemoryAccessImm1> |
| + InstructionSelectorMemoryAccessImmMoreThan16bitTest; |
| + |
| + |
| +TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, |
| + LoadWithImmediateIndex) { |
| + const MemoryAccessImm1 memacc = GetParam(); |
| + TRACED_FOREACH(int32_t, index, memacc.immediates) { |
| + StreamBuilder m(this, memacc.type, kMachPtr); |
| + m.Return(m.Load(memacc.type, m.Parameter(0), m.Int32Constant(index))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(2U, s.size()); |
| + // kMipsAdd is expected opcode. |
| + // size more than 16 bits wide. |
| + EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); |
| + EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| + } |
| +} |
| + |
| + |
| +TEST_P(InstructionSelectorMemoryAccessImmMoreThan16bitTest, |
| + StoreWithImmediateIndex) { |
| + const MemoryAccessImm1 memacc = GetParam(); |
| + TRACED_FOREACH(int32_t, index, memacc.immediates) { |
| + StreamBuilder m(this, kMachInt32, kMachPtr, memacc.type); |
| + m.Store(memacc.type, m.Parameter(0), m.Int32Constant(index), |
| + m.Parameter(1)); |
| + m.Return(m.Int32Constant(0)); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(2U, s.size()); |
| + // kMipsAdd is expected opcode |
| + // size more than 16 bits wide |
| + EXPECT_EQ(kMipsAdd, s[0]->arch_opcode()); |
| + EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| + EXPECT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| + } |
| +} |
| + |
| + |
| +INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, |
| + InstructionSelectorMemoryAccessImmMoreThan16bitTest, |
| + ::testing::ValuesIn(kMemoryAccessImmMoreThan16bit)); |
| + |
| + |
| +// ---------------------------------------------------------------------------- |
| +// kMipsTst testing. |
| +// ---------------------------------------------------------------------------- |
| + |
| + |
| +TEST_F(InstructionSelectorTest, Word32EqualWithZero) { |
| + { |
| + StreamBuilder m(this, kMachInt32, kMachInt32); |
| + m.Return(m.Word32Equal(m.Parameter(0), m.Int32Constant(0))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(kMipsTst, s[0]->arch_opcode()); |
| + EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| + ASSERT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| + EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| + EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| + } |
| + { |
| + StreamBuilder m(this, kMachInt32, kMachInt32); |
| + m.Return(m.Word32Equal(m.Int32Constant(0), m.Parameter(0))); |
| + Stream s = m.Build(); |
| + ASSERT_EQ(1U, s.size()); |
| + EXPECT_EQ(kMipsTst, s[0]->arch_opcode()); |
| + EXPECT_EQ(kMode_None, s[0]->addressing_mode()); |
| + ASSERT_EQ(2U, s[0]->InputCount()); |
| + EXPECT_EQ(s.ToVreg(s[0]->InputAt(0)), s.ToVreg(s[0]->InputAt(1))); |
| + EXPECT_EQ(1U, s[0]->OutputCount()); |
| + EXPECT_EQ(kFlags_set, s[0]->flags_mode()); |
| + EXPECT_EQ(kEqual, s[0]->flags_condition()); |
| + } |
| +} |
| + |
| + |
|
Benedikt Meurer
2014/09/25 05:37:11
Nit: extra new line :-)
paul.l...
2014/09/25 17:18:39
Done.
|
| +} // namespace compiler |
| +} // namespace internal |
| +} // namespace v8 |