diff options
Diffstat (limited to 'compiler/optimizing/codegen_test.cc')
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 93 |
1 files changed, 81 insertions, 12 deletions
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index 47e9fa4e2f..a7b64c9e3b 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -31,6 +31,7 @@ #include "prepare_for_register_allocation.h" #include "register_allocator.h" #include "ssa_liveness_analysis.h" +#include "utils.h" #include "gtest/gtest.h" @@ -56,24 +57,26 @@ class InternalCodeAllocator : public CodeAllocator { DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator); }; +template <typename Expected> static void Run(const InternalCodeAllocator& allocator, const CodeGenerator& codegen, bool has_result, - int32_t expected) { - typedef int32_t (*fptr)(); + Expected expected) { + typedef Expected (*fptr)(); CommonCompilerTest::MakeExecutable(allocator.GetMemory(), allocator.GetSize()); fptr f = reinterpret_cast<fptr>(allocator.GetMemory()); if (codegen.GetInstructionSet() == kThumb2) { // For thumb we need the bottom bit set. f = reinterpret_cast<fptr>(reinterpret_cast<uintptr_t>(f) + 1); } - int32_t result = f(); + Expected result = f(); if (has_result) { ASSERT_EQ(result, expected); } } -static void RunCodeBaseline(HGraph* graph, bool has_result, int32_t expected) { +template <typename Expected> +static void RunCodeBaseline(HGraph* graph, bool has_result, Expected expected) { InternalCodeAllocator allocator; x86::CodeGeneratorX86 codegenX86(graph); @@ -103,11 +106,12 @@ static void RunCodeBaseline(HGraph* graph, bool has_result, int32_t expected) { } } +template <typename Expected> static void RunCodeOptimized(CodeGenerator* codegen, HGraph* graph, std::function<void(HGraph*)> hook_before_codegen, bool has_result, - int32_t expected) { + Expected expected) { SsaLivenessAnalysis liveness(*graph, codegen); liveness.Analyze(); @@ -120,10 +124,11 @@ static void RunCodeOptimized(CodeGenerator* codegen, Run(allocator, *codegen, has_result, expected); } +template <typename Expected> static void RunCodeOptimized(HGraph* graph, std::function<void(HGraph*)> hook_before_codegen, bool has_result, - int32_t expected) { + Expected expected) { if (kRuntimeISA == kX86) { x86::CodeGeneratorX86 codegenX86(graph); RunCodeOptimized(&codegenX86, graph, hook_before_codegen, has_result, expected); @@ -148,6 +153,18 @@ static void TestCode(const uint16_t* data, bool has_result = false, int32_t expe RunCodeBaseline(graph, has_result, expected); } +static void TestCodeLong(const uint16_t* data, bool has_result, int64_t expected) { + ArenaPool pool; + ArenaAllocator arena(&pool); + HGraphBuilder builder(&arena, Primitive::kPrimLong); + const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); + HGraph* graph = builder.BuildGraph(*item); + ASSERT_NE(graph, nullptr); + // Remove suspend checks, they cannot be executed in this context. + RemoveSuspendChecks(graph); + RunCodeBaseline(graph, has_result, expected); +} + TEST(CodegenTest, ReturnVoid) { const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID); TestCode(data); @@ -272,8 +289,8 @@ TEST(CodegenTest, ReturnIf2) { #define NOT_INT_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \ TEST(CodegenTest, TEST_NAME) { \ const int32_t input = INPUT; \ - const uint16_t input_lo = input & 0x0000FFFF; \ - const uint16_t input_hi = input >> 16; \ + const uint16_t input_lo = Low16Bits(input); \ + const uint16_t input_hi = High16Bits(input); \ const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( \ Instruction::CONST | 0 << 8, input_lo, input_hi, \ Instruction::NOT_INT | 1 << 8 | 0 << 12 , \ @@ -286,13 +303,65 @@ NOT_INT_TEST(ReturnNotIntMinus2, -2, 1) NOT_INT_TEST(ReturnNotIntMinus1, -1, 0) NOT_INT_TEST(ReturnNotInt0, 0, -1) NOT_INT_TEST(ReturnNotInt1, 1, -2) -NOT_INT_TEST(ReturnNotIntINT_MIN, -2147483648, 2147483647) // (2^31) - 1 -NOT_INT_TEST(ReturnNotIntINT_MINPlus1, -2147483647, 2147483646) // (2^31) - 2 -NOT_INT_TEST(ReturnNotIntINT_MAXMinus1, 2147483646, -2147483647) // -(2^31) - 1 -NOT_INT_TEST(ReturnNotIntINT_MAX, 2147483647, -2147483648) // -(2^31) +NOT_INT_TEST(ReturnNotIntINT32_MIN, -2147483648, 2147483647) // (2^31) - 1 +NOT_INT_TEST(ReturnNotIntINT32_MINPlus1, -2147483647, 2147483646) // (2^31) - 2 +NOT_INT_TEST(ReturnNotIntINT32_MAXMinus1, 2147483646, -2147483647) // -(2^31) - 1 +NOT_INT_TEST(ReturnNotIntINT32_MAX, 2147483647, -2147483648) // -(2^31) #undef NOT_INT_TEST +// Exercise bit-wise (one's complement) not-long instruction. +#define NOT_LONG_TEST(TEST_NAME, INPUT, EXPECTED_OUTPUT) \ +TEST(CodegenTest, TEST_NAME) { \ + const int64_t input = INPUT; \ + const uint16_t word0 = Low16Bits(Low32Bits(input)); /* LSW. */ \ + const uint16_t word1 = High16Bits(Low32Bits(input)); \ + const uint16_t word2 = Low16Bits(High32Bits(input)); \ + const uint16_t word3 = High16Bits(High32Bits(input)); /* MSW. */ \ + const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM( \ + Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3, \ + Instruction::NOT_LONG | 2 << 8 | 0 << 12, \ + Instruction::RETURN_WIDE | 2 << 8); \ + \ + TestCodeLong(data, true, EXPECTED_OUTPUT); \ +} + +NOT_LONG_TEST(ReturnNotLongMinus2, INT64_C(-2), INT64_C(1)) +NOT_LONG_TEST(ReturnNotLongMinus1, INT64_C(-1), INT64_C(0)) +NOT_LONG_TEST(ReturnNotLong0, INT64_C(0), INT64_C(-1)) +NOT_LONG_TEST(ReturnNotLong1, INT64_C(1), INT64_C(-2)) + +NOT_LONG_TEST(ReturnNotLongINT32_MIN, + INT64_C(-2147483648), + INT64_C(2147483647)) // (2^31) - 1 +NOT_LONG_TEST(ReturnNotLongINT32_MINPlus1, + INT64_C(-2147483647), + INT64_C(2147483646)) // (2^31) - 2 +NOT_LONG_TEST(ReturnNotLongINT32_MAXMinus1, + INT64_C(2147483646), + INT64_C(-2147483647)) // -(2^31) - 1 +NOT_LONG_TEST(ReturnNotLongINT32_MAX, + INT64_C(2147483647), + INT64_C(-2147483648)) // -(2^31) + +// Note that the C++ compiler won't accept +// INT64_C(-9223372036854775808) (that is, INT64_MIN) as a valid +// int64_t literal, so we use INT64_C(-9223372036854775807)-1 instead. +NOT_LONG_TEST(ReturnNotINT64_MIN, + INT64_C(-9223372036854775807)-1, + INT64_C(9223372036854775807)); // (2^63) - 1 +NOT_LONG_TEST(ReturnNotINT64_MINPlus1, + INT64_C(-9223372036854775807), + INT64_C(9223372036854775806)); // (2^63) - 2 +NOT_LONG_TEST(ReturnNotLongINT64_MAXMinus1, + INT64_C(9223372036854775806), + INT64_C(-9223372036854775807)); // -(2^63) - 1 +NOT_LONG_TEST(ReturnNotLongINT64_MAX, + INT64_C(9223372036854775807), + INT64_C(-9223372036854775807)-1); // -(2^63) + +#undef NOT_LONG_TEST + TEST(CodegenTest, ReturnAdd1) { const uint16_t data[] = TWO_REGISTERS_CODE_ITEM( Instruction::CONST_4 | 3 << 12 | 0, |