Index: test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc |
diff --git a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc |
index 6f0388907c063f010af14b4333387823345c965f..b4c31457182c80476dea307a3d1fe4788c7b24f8 100644 |
--- a/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc |
+++ b/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc |
@@ -30,6 +30,17 @@ std::ostream& operator<<(std::ostream& os, const MachInst<T>& mi) { |
} |
+struct Shift { |
+ MachInst2 mi; |
+ AddressingMode mode; |
+}; |
+ |
+ |
+std::ostream& operator<<(std::ostream& os, const Shift& shift) { |
+ return os << shift.mi; |
+} |
+ |
+ |
// Helper to build Int32Constant or Int64Constant depending on the given |
// machine type. |
Node* BuildConstant(InstructionSelectorTest::StreamBuilder& m, MachineType type, |
@@ -139,15 +150,23 @@ static const MachInst2 kOvfAddSubInstructions[] = { |
// ARM64 shift instructions. |
-static const MachInst2 kShiftInstructions[] = { |
- {&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32, kMachInt32}, |
- {&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Lsl, kMachInt64}, |
- {&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32, kMachInt32}, |
- {&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Lsr, kMachInt64}, |
- {&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32, kMachInt32}, |
- {&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Asr, kMachInt64}, |
- {&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32}, |
- {&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64}}; |
+static const Shift kShiftInstructions[] = { |
+ {{&RawMachineAssembler::Word32Shl, "Word32Shl", kArm64Lsl32, kMachInt32}, |
+ kMode_Operand2_R_LSL_I}, |
+ {{&RawMachineAssembler::Word64Shl, "Word64Shl", kArm64Lsl, kMachInt64}, |
+ kMode_Operand2_R_LSL_I}, |
+ {{&RawMachineAssembler::Word32Shr, "Word32Shr", kArm64Lsr32, kMachInt32}, |
+ kMode_Operand2_R_LSR_I}, |
+ {{&RawMachineAssembler::Word64Shr, "Word64Shr", kArm64Lsr, kMachInt64}, |
+ kMode_Operand2_R_LSR_I}, |
+ {{&RawMachineAssembler::Word32Sar, "Word32Sar", kArm64Asr32, kMachInt32}, |
+ kMode_Operand2_R_ASR_I}, |
+ {{&RawMachineAssembler::Word64Sar, "Word64Sar", kArm64Asr, kMachInt64}, |
+ kMode_Operand2_R_ASR_I}, |
+ {{&RawMachineAssembler::Word32Ror, "Word32Ror", kArm64Ror32, kMachInt32}, |
+ kMode_Operand2_R_ROR_I}, |
+ {{&RawMachineAssembler::Word64Ror, "Word64Ror", kArm64Ror, kMachInt64}, |
+ kMode_Operand2_R_ROR_I}}; |
// ARM64 Mul/Div instructions. |
@@ -296,6 +315,46 @@ TEST_P(InstructionSelectorLogicalTest, Immediate) { |
} |
+TEST_P(InstructionSelectorLogicalTest, ShiftByImmediate) { |
+ const MachInst2 dpi = GetParam(); |
+ const MachineType type = dpi.machine_type; |
+ TRACED_FOREACH(Shift, shift, kShiftInstructions) { |
+ // Only test 64-bit shifted operands with 64-bit instructions. |
+ if (shift.mi.machine_type != type) continue; |
+ |
+ TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) { |
+ StreamBuilder m(this, type, type, type); |
+ m.Return((m.*dpi.constructor)( |
+ m.Parameter(0), |
+ (m.*shift.mi.constructor)(m.Parameter(1), |
+ BuildConstant(m, type, imm)))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ EXPECT_EQ(shift.mode, s[0]->addressing_mode()); |
+ EXPECT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2))); |
+ EXPECT_EQ(1U, s[0]->OutputCount()); |
+ } |
+ |
+ TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) { |
+ StreamBuilder m(this, type, type, type); |
+ m.Return((m.*dpi.constructor)( |
+ (m.*shift.mi.constructor)(m.Parameter(1), |
+ BuildConstant(m, type, imm)), |
+ m.Parameter(0))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.arch_opcode, s[0]->arch_opcode()); |
+ EXPECT_EQ(shift.mode, s[0]->addressing_mode()); |
+ EXPECT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2))); |
+ EXPECT_EQ(1U, s[0]->OutputCount()); |
+ } |
+ } |
+} |
+ |
+ |
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorLogicalTest, |
::testing::ValuesIn(kLogicalInstructions)); |
@@ -356,6 +415,37 @@ TEST_P(InstructionSelectorAddSubTest, NegImmediateOnRight) { |
} |
+TEST_P(InstructionSelectorAddSubTest, ShiftByImmediateOnRight) { |
+ const AddSub dpi = GetParam(); |
+ const MachineType type = dpi.mi.machine_type; |
+ TRACED_FOREACH(Shift, shift, kShiftInstructions) { |
+ // Only test 64-bit shifted operands with 64-bit instructions. |
+ if (shift.mi.machine_type != type) continue; |
+ |
+ if ((shift.mi.arch_opcode == kArm64Ror32) || |
+ (shift.mi.arch_opcode == kArm64Ror)) { |
+ // Not supported by add/sub instructions. |
+ continue; |
+ } |
+ |
+ TRACED_FORRANGE(int, imm, 0, ((type == kMachInt32) ? 31 : 63)) { |
+ StreamBuilder m(this, type, type, type); |
+ m.Return((m.*dpi.mi.constructor)( |
+ m.Parameter(0), |
+ (m.*shift.mi.constructor)(m.Parameter(1), |
+ BuildConstant(m, type, imm)))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(dpi.mi.arch_opcode, s[0]->arch_opcode()); |
+ EXPECT_EQ(shift.mode, s[0]->addressing_mode()); |
+ EXPECT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2))); |
+ EXPECT_EQ(1U, s[0]->OutputCount()); |
+ } |
+ } |
+} |
+ |
+ |
INSTANTIATE_TEST_CASE_P(InstructionSelectorTest, InstructionSelectorAddSubTest, |
::testing::ValuesIn(kAddSubInstructions)); |
@@ -455,6 +545,51 @@ TEST_F(InstructionSelectorTest, AddNegImmediateOnLeft) { |
} |
+TEST_F(InstructionSelectorTest, AddShiftByImmediateOnLeft) { |
+ // 32-bit add. |
+ TRACED_FOREACH(Shift, shift, kShiftInstructions) { |
+ // Only test relevant shifted operands. |
+ if (shift.mi.machine_type != kMachInt32) continue; |
+ if (shift.mi.arch_opcode == kArm64Ror32) continue; |
+ |
+ TRACED_FORRANGE(int, imm, 0, 31) { |
+ StreamBuilder m(this, kMachInt32, kMachInt32, kMachInt32); |
+ m.Return((m.Int32Add)( |
+ (m.*shift.mi.constructor)(m.Parameter(1), m.Int32Constant(imm)), |
+ m.Parameter(0))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArm64Add32, s[0]->arch_opcode()); |
+ EXPECT_EQ(shift.mode, s[0]->addressing_mode()); |
+ EXPECT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2))); |
+ EXPECT_EQ(1U, s[0]->OutputCount()); |
+ } |
+ } |
+ |
+ // 64-bit add. |
+ TRACED_FOREACH(Shift, shift, kShiftInstructions) { |
+ // Only test relevant shifted operands. |
+ if (shift.mi.machine_type != kMachInt64) continue; |
+ if (shift.mi.arch_opcode == kArm64Ror) continue; |
+ |
+ TRACED_FORRANGE(int, imm, 0, 63) { |
+ StreamBuilder m(this, kMachInt64, kMachInt64, kMachInt64); |
+ m.Return((m.Int64Add)( |
+ (m.*shift.mi.constructor)(m.Parameter(1), m.Int64Constant(imm)), |
+ m.Parameter(0))); |
+ Stream s = m.Build(); |
+ ASSERT_EQ(1U, s.size()); |
+ EXPECT_EQ(kArm64Add, s[0]->arch_opcode()); |
+ EXPECT_EQ(shift.mode, s[0]->addressing_mode()); |
+ EXPECT_EQ(3U, s[0]->InputCount()); |
+ EXPECT_EQ(imm, s.ToInt64(s[0]->InputAt(2))); |
+ EXPECT_EQ(1U, s[0]->OutputCount()); |
+ } |
+ } |
+} |
+ |
+ |
// ----------------------------------------------------------------------------- |
// Data processing controlled branches. |
@@ -818,32 +953,31 @@ TEST_F(InstructionSelectorTest, OvfBranchWithImmediateOnLeft) { |
// Shift instructions. |
-typedef InstructionSelectorTestWithParam<MachInst2> |
- InstructionSelectorShiftTest; |
+typedef InstructionSelectorTestWithParam<Shift> InstructionSelectorShiftTest; |
TEST_P(InstructionSelectorShiftTest, Parameter) { |
- const MachInst2 dpi = GetParam(); |
- const MachineType type = dpi.machine_type; |
+ const Shift shift = GetParam(); |
+ const MachineType type = shift.mi.machine_type; |
StreamBuilder m(this, type, type, type); |
- m.Return((m.*dpi.constructor)(m.Parameter(0), m.Parameter(1))); |
+ m.Return((m.*shift.mi.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(shift.mi.arch_opcode, s[0]->arch_opcode()); |
EXPECT_EQ(2U, s[0]->InputCount()); |
EXPECT_EQ(1U, s[0]->OutputCount()); |
} |
TEST_P(InstructionSelectorShiftTest, Immediate) { |
- const MachInst2 dpi = GetParam(); |
- const MachineType type = dpi.machine_type; |
+ const Shift shift = GetParam(); |
+ const MachineType type = shift.mi.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))); |
+ m.Return((m.*shift.mi.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(shift.mi.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))); |