Add support for not-long on ARM64 in the optimizing compiler.
Change-Id: I3e98ff411ba358d92774def18a12daccdc4f558f
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 47e9fa4..a7b64c9 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 @@
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 @@
}
}
+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 @@
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 @@
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 @@
#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(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,