diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2014-10-08 21:07:48 +0100 |
---|---|---|
committer | Nicolas Geoffray <ngeoffray@google.com> | 2014-10-09 15:21:57 +0100 |
commit | 360231a056e796c36ffe62348507e904dc9efb9b (patch) | |
tree | a62ff73c11eaa6694649c98e4c2d872e89149b0c /compiler/optimizing/codegen_test.cc | |
parent | 2072c465cfff077da257bdf14f1f1b2690c946c8 (diff) | |
download | art-360231a056e796c36ffe62348507e904dc9efb9b.tar.gz art-360231a056e796c36ffe62348507e904dc9efb9b.tar.bz2 art-360231a056e796c36ffe62348507e904dc9efb9b.zip |
Fix code generation of materialized conditions.
Move the logic for knowing if a condition needs to be materialized
in an optimization pass (so that the information does not change
as a side effect of another optimization).
Also clean-up arm and x86_64 codegen:
- arm: ldr and str are for power-users when a constant is
in play. We should use LoadFromOffset and StoreToOffset.
- x86_64: fix misuses of movq instead of movl.
Change-Id: I01a03b91803624be2281a344a13ad5efbf4f3ef3
Diffstat (limited to 'compiler/optimizing/codegen_test.cc')
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 113 |
1 files changed, 103 insertions, 10 deletions
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index 7161eed9f9..3037f1c2e8 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <functional> + #include "builder.h" #include "code_generator_arm.h" #include "code_generator_x86.h" @@ -24,6 +26,9 @@ #include "instruction_set.h" #include "nodes.h" #include "optimizing_unit_test.h" +#include "prepare_for_register_allocation.h" +#include "register_allocator.h" +#include "ssa_liveness_analysis.h" #include "gtest/gtest.h" @@ -62,19 +67,11 @@ static void Run(const InternalCodeAllocator& allocator, } int32_t result = f(); if (has_result) { - CHECK_EQ(result, expected); + ASSERT_EQ(result, expected); } } -static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) { - ArenaPool pool; - ArenaAllocator arena(&pool); - HGraphBuilder builder(&arena); - const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); - HGraph* graph = builder.BuildGraph(*item); - // Remove suspend checks, they cannot be executed in this context. - RemoveSuspendChecks(graph); - ASSERT_NE(graph, nullptr); +static void RunCodeBaseline(HGraph* graph, bool has_result, int32_t expected) { InternalCodeAllocator allocator; x86::CodeGeneratorX86 codegenX86(graph); @@ -98,6 +95,51 @@ static void TestCode(const uint16_t* data, bool has_result = false, int32_t expe } } +static void RunCodeOptimized(CodeGenerator* codegen, + HGraph* graph, + std::function<void(HGraph*)> hook_before_codegen, + bool has_result, + int32_t expected) { + SsaLivenessAnalysis liveness(*graph, codegen); + liveness.Analyze(); + + RegisterAllocator register_allocator(graph->GetArena(), codegen, liveness); + register_allocator.AllocateRegisters(); + hook_before_codegen(graph); + + InternalCodeAllocator allocator; + codegen->CompileOptimized(&allocator); + Run(allocator, *codegen, has_result, expected); +} + +static void RunCodeOptimized(HGraph* graph, + std::function<void(HGraph*)> hook_before_codegen, + bool has_result, + int32_t expected) { + if (kRuntimeISA == kX86) { + x86::CodeGeneratorX86 codegenX86(graph); + RunCodeOptimized(&codegenX86, graph, hook_before_codegen, has_result, expected); + } else if (kRuntimeISA == kArm || kRuntimeISA == kThumb2) { + arm::CodeGeneratorARM codegenARM(graph); + RunCodeOptimized(&codegenARM, graph, hook_before_codegen, has_result, expected); + } else if (kRuntimeISA == kX86_64) { + x86_64::CodeGeneratorX86_64 codegenX86_64(graph); + RunCodeOptimized(&codegenX86_64, graph, hook_before_codegen, has_result, expected); + } +} + +static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) { + ArenaPool pool; + ArenaAllocator arena(&pool); + HGraphBuilder builder(&arena); + const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); + HGraph* graph = builder.BuildGraph(*item); + // Remove suspend checks, they cannot be executed in this context. + RemoveSuspendChecks(graph); + ASSERT_NE(graph, nullptr); + RunCodeBaseline(graph, has_result, expected); +} + TEST(CodegenTest, ReturnVoid) { const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(Instruction::RETURN_VOID); TestCode(data); @@ -256,4 +298,55 @@ TEST(CodegenTest, ReturnAdd4) { TestCode(data, true, 7); } +TEST(CodegenTest, NonMaterializedCondition) { + ArenaPool pool; + ArenaAllocator allocator(&pool); + + HGraph* graph = new (&allocator) HGraph(&allocator); + HBasicBlock* entry = new (&allocator) HBasicBlock(graph); + graph->AddBlock(entry); + graph->SetEntryBlock(entry); + entry->AddInstruction(new (&allocator) HGoto()); + + HBasicBlock* first_block = new (&allocator) HBasicBlock(graph); + graph->AddBlock(first_block); + entry->AddSuccessor(first_block); + HIntConstant* constant0 = new (&allocator) HIntConstant(0); + entry->AddInstruction(constant0); + HIntConstant* constant1 = new (&allocator) HIntConstant(1); + entry->AddInstruction(constant1); + HEqual* equal = new (&allocator) HEqual(constant0, constant0); + first_block->AddInstruction(equal); + first_block->AddInstruction(new (&allocator) HIf(equal)); + + HBasicBlock* then = new (&allocator) HBasicBlock(graph); + HBasicBlock* else_ = new (&allocator) HBasicBlock(graph); + HBasicBlock* exit = new (&allocator) HBasicBlock(graph); + + graph->AddBlock(then); + graph->AddBlock(else_); + graph->AddBlock(exit); + first_block->AddSuccessor(then); + first_block->AddSuccessor(else_); + then->AddSuccessor(exit); + else_->AddSuccessor(exit); + + exit->AddInstruction(new (&allocator) HExit()); + then->AddInstruction(new (&allocator) HReturn(constant0)); + else_->AddInstruction(new (&allocator) HReturn(constant1)); + + ASSERT_TRUE(equal->NeedsMaterialization()); + graph->BuildDominatorTree(); + PrepareForRegisterAllocation(graph).Run(); + ASSERT_FALSE(equal->NeedsMaterialization()); + + auto hook_before_codegen = [](HGraph* graph) { + HBasicBlock* block = graph->GetEntryBlock()->GetSuccessors().Get(0); + HParallelMove* move = new (graph->GetArena()) HParallelMove(graph->GetArena()); + block->InsertInstructionBefore(move, block->GetLastInstruction()); + }; + + RunCodeOptimized(graph, hook_before_codegen, true, 0); +} + } // namespace art |