From 2c76e068cb49b6bd687510f887e2c1058678eccb Mon Sep 17 00:00:00 2001 From: Scott Wakeling Date: Wed, 31 Aug 2016 09:48:54 +0100 Subject: [PATCH] Allow for testing alternative code generators in codegen_test.cc This will be used in a later patch to test a new VIXL32-based backend in parallel with the existing code_generator_arm. Test: gtest-codegen_test on host and target Change-Id: I0316da0430fa6da0a7c668315f531888d18e7eb3 --- compiler/optimizing/codegen_test.cc | 227 +++++++++++++++++++++--------------- compiler/optimizing/nodes.h | 3 + 2 files changed, 135 insertions(+), 95 deletions(-) diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index d00a7867e..d9347f604 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -74,6 +74,24 @@ namespace art { +typedef CodeGenerator* (*CreateCodegenFn)(HGraph*, const CompilerOptions&); + +class CodegenTargetConfig { + public: + CodegenTargetConfig(InstructionSet isa, CreateCodegenFn create_codegen) + : isa_(isa), create_codegen_(create_codegen) { + } + InstructionSet GetInstructionSet() const { return isa_; } + CodeGenerator* CreateCodeGenerator(HGraph* graph, const CompilerOptions& compiler_options) { + return create_codegen_(graph, compiler_options); + } + + private: + CodegenTargetConfig() {} + InstructionSet isa_; + CreateCodegenFn create_codegen_; +}; + #ifdef ART_ENABLE_CODEGEN_arm // Provide our own codegen, that ensures the C calling conventions // are preserved. Currently, ART and C do not match as R4 is caller-save @@ -222,12 +240,7 @@ static void Run(const InternalCodeAllocator& allocator, VerifyGeneratedCode(target_isa, f, has_result, expected); } -template -static void RunCode(CodeGenerator* codegen, - HGraph* graph, - std::function hook_before_codegen, - bool has_result, - Expected expected) { +static void ValidateGraph(HGraph* graph) { GraphChecker graph_checker(graph); graph_checker.Run(); if (!graph_checker.IsValid()) { @@ -236,92 +249,129 @@ static void RunCode(CodeGenerator* codegen, } } ASSERT_TRUE(graph_checker.IsValid()); +} +template +static void RunCodeNoCheck(CodeGenerator* codegen, + HGraph* graph, + std::function hook_before_codegen, + bool has_result, + Expected expected) { SsaLivenessAnalysis liveness(graph, codegen); - PrepareForRegisterAllocation(graph).Run(); liveness.Analyze(); RegisterAllocator::Create(graph->GetArena(), codegen, liveness)->AllocateRegisters(); hook_before_codegen(graph); - InternalCodeAllocator allocator; codegen->Compile(&allocator); Run(allocator, *codegen, has_result, expected); } template -static void RunCode(InstructionSet target_isa, +static void RunCode(CodeGenerator* codegen, + HGraph* graph, + std::function hook_before_codegen, + bool has_result, + Expected expected) { + ValidateGraph(graph); + RunCodeNoCheck(codegen, graph, hook_before_codegen, has_result, expected); +} + +template +static void RunCode(CodegenTargetConfig target_config, HGraph* graph, std::function hook_before_codegen, bool has_result, Expected expected) { CompilerOptions compiler_options; + CodeGenerator* codegen = target_config.CreateCodeGenerator(graph, compiler_options); + RunCode(codegen, graph, hook_before_codegen, has_result, expected); +} + #ifdef ART_ENABLE_CODEGEN_arm - if (target_isa == kArm || target_isa == kThumb2) { - std::unique_ptr features_arm( - ArmInstructionSetFeatures::FromCppDefines()); - TestCodeGeneratorARM codegenARM(graph, *features_arm.get(), compiler_options); - RunCode(&codegenARM, graph, hook_before_codegen, has_result, expected); - } +CodeGenerator* create_codegen_arm(HGraph* graph, const CompilerOptions& compiler_options) { + std::unique_ptr features_arm( + ArmInstructionSetFeatures::FromCppDefines()); + return new (graph->GetArena()) TestCodeGeneratorARM(graph, + *features_arm.get(), + compiler_options); +} #endif + #ifdef ART_ENABLE_CODEGEN_arm64 - if (target_isa == kArm64) { - std::unique_ptr features_arm64( - Arm64InstructionSetFeatures::FromCppDefines()); - arm64::CodeGeneratorARM64 codegenARM64(graph, *features_arm64.get(), compiler_options); - RunCode(&codegenARM64, graph, hook_before_codegen, has_result, expected); - } +CodeGenerator* create_codegen_arm64(HGraph* graph, const CompilerOptions& compiler_options) { + std::unique_ptr features_arm64( + Arm64InstructionSetFeatures::FromCppDefines()); + return new (graph->GetArena()) arm64::CodeGeneratorARM64(graph, + *features_arm64.get(), + compiler_options); +} #endif + #ifdef ART_ENABLE_CODEGEN_x86 - if (target_isa == kX86) { - std::unique_ptr features_x86( - X86InstructionSetFeatures::FromCppDefines()); - TestCodeGeneratorX86 codegenX86(graph, *features_x86.get(), compiler_options); - RunCode(&codegenX86, graph, hook_before_codegen, has_result, expected); - } +CodeGenerator* create_codegen_x86(HGraph* graph, const CompilerOptions& compiler_options) { + std::unique_ptr features_x86( + X86InstructionSetFeatures::FromCppDefines()); + return new (graph->GetArena()) TestCodeGeneratorX86(graph, *features_x86.get(), compiler_options); +} #endif + #ifdef ART_ENABLE_CODEGEN_x86_64 - if (target_isa == kX86_64) { - std::unique_ptr features_x86_64( - X86_64InstructionSetFeatures::FromCppDefines()); - x86_64::CodeGeneratorX86_64 codegenX86_64(graph, *features_x86_64.get(), compiler_options); - RunCode(&codegenX86_64, graph, hook_before_codegen, has_result, expected); - } +CodeGenerator* create_codegen_x86_64(HGraph* graph, const CompilerOptions& compiler_options) { + std::unique_ptr features_x86_64( + X86_64InstructionSetFeatures::FromCppDefines()); + return new (graph->GetArena()) + x86_64::CodeGeneratorX86_64(graph, *features_x86_64.get(), compiler_options); +} #endif + #ifdef ART_ENABLE_CODEGEN_mips - if (target_isa == kMips) { - std::unique_ptr features_mips( - MipsInstructionSetFeatures::FromCppDefines()); - mips::CodeGeneratorMIPS codegenMIPS(graph, *features_mips.get(), compiler_options); - RunCode(&codegenMIPS, graph, hook_before_codegen, has_result, expected); - } +CodeGenerator* create_codegen_mips(HGraph* graph, const CompilerOptions& compiler_options) { + std::unique_ptr features_mips( + MipsInstructionSetFeatures::FromCppDefines()); + return new (graph->GetArena()) + mips::CodeGeneratorMIPS(graph, *features_mips.get(), compiler_options); +} #endif + #ifdef ART_ENABLE_CODEGEN_mips64 - if (target_isa == kMips64) { - std::unique_ptr features_mips64( - Mips64InstructionSetFeatures::FromCppDefines()); - mips64::CodeGeneratorMIPS64 codegenMIPS64(graph, *features_mips64.get(), compiler_options); - RunCode(&codegenMIPS64, graph, hook_before_codegen, has_result, expected); - } -#endif +CodeGenerator* create_codegen_mips64(HGraph* graph, const CompilerOptions& compiler_options) { + std::unique_ptr features_mips64( + Mips64InstructionSetFeatures::FromCppDefines()); + return new (graph->GetArena()) + mips64::CodeGeneratorMIPS64(graph, *features_mips64.get(), compiler_options); } +#endif -static ::std::vector GetTargetISAs() { - ::std::vector v; - // Add all ISAs that are executable on hardware or on simulator. - const ::std::vector executable_isa_candidates = { - kArm, - kArm64, - kThumb2, - kX86, - kX86_64, - kMips, - kMips64 +// Return all combinations of ISA and code generator that are executable on +// hardware, or on simulator, and that we'd like to test. +static ::std::vector GetTargetConfigs() { + ::std::vector v; + ::std::vector test_config_candidates = { +#ifdef ART_ENABLE_CODEGEN_arm + CodegenTargetConfig(kArm, create_codegen_arm), + CodegenTargetConfig(kThumb2, create_codegen_arm), +#endif +#ifdef ART_ENABLE_CODEGEN_arm64 + CodegenTargetConfig(kArm64, create_codegen_arm64), +#endif +#ifdef ART_ENABLE_CODEGEN_x86 + CodegenTargetConfig(kX86, create_codegen_x86), +#endif +#ifdef ART_ENABLE_CODEGEN_x86_64 + CodegenTargetConfig(kX86_64, create_codegen_x86_64), +#endif +#ifdef ART_ENABLE_CODEGEN_mips + CodegenTargetConfig(kMips, create_codegen_mips), +#endif +#ifdef ART_ENABLE_CODEGEN_mips64 + CodegenTargetConfig(kMips64, create_codegen_mips64) +#endif }; - for (auto target_isa : executable_isa_candidates) { - if (CanExecute(target_isa)) { - v.push_back(target_isa); + for (auto test_config : test_config_candidates) { + if (CanExecute(test_config.GetInstructionSet())) { + v.push_back(test_config); } } @@ -331,26 +381,26 @@ static ::std::vector GetTargetISAs() { static void TestCode(const uint16_t* data, bool has_result = false, int32_t expected = 0) { - for (InstructionSet target_isa : GetTargetISAs()) { + for (CodegenTargetConfig target_config : GetTargetConfigs()) { ArenaPool pool; ArenaAllocator arena(&pool); HGraph* graph = CreateCFG(&arena, data); // Remove suspend checks, they cannot be executed in this context. RemoveSuspendChecks(graph); - RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected); + RunCode(target_config, graph, [](HGraph*) {}, has_result, expected); } } static void TestCodeLong(const uint16_t* data, bool has_result, int64_t expected) { - for (InstructionSet target_isa : GetTargetISAs()) { + for (CodegenTargetConfig target_config : GetTargetConfigs()) { ArenaPool pool; ArenaAllocator arena(&pool); HGraph* graph = CreateCFG(&arena, data, Primitive::kPrimLong); // Remove suspend checks, they cannot be executed in this context. RemoveSuspendChecks(graph); - RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected); + RunCode(target_config, graph, [](HGraph*) {}, has_result, expected); } } @@ -667,7 +717,7 @@ TEST_F(CodegenTest, ReturnMulIntLit16) { } TEST_F(CodegenTest, NonMaterializedCondition) { - for (InstructionSet target_isa : GetTargetISAs()) { + for (CodegenTargetConfig target_config : GetTargetConfigs()) { ArenaPool pool; ArenaAllocator allocator(&pool); @@ -715,12 +765,12 @@ TEST_F(CodegenTest, NonMaterializedCondition) { block->InsertInstructionBefore(move, block->GetLastInstruction()); }; - RunCode(target_isa, graph, hook_before_codegen, true, 0); + RunCode(target_config, graph, hook_before_codegen, true, 0); } } TEST_F(CodegenTest, MaterializedCondition1) { - for (InstructionSet target_isa : GetTargetISAs()) { + for (CodegenTargetConfig target_config : GetTargetConfigs()) { // Check that condition are materialized correctly. A materialized condition // should yield `1` if it evaluated to true, and `0` otherwise. // We force the materialization of comparisons for different combinations of @@ -762,13 +812,13 @@ TEST_F(CodegenTest, MaterializedCondition1) { HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena()); block->InsertInstructionBefore(move, block->GetLastInstruction()); }; - RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]); + RunCode(target_config, graph, hook_before_codegen, true, lhs[i] < rhs[i]); } } } TEST_F(CodegenTest, MaterializedCondition2) { - for (InstructionSet target_isa : GetTargetISAs()) { + for (CodegenTargetConfig target_config : GetTargetConfigs()) { // Check that HIf correctly interprets a materialized condition. // We force the materialization of comparisons for different combinations of // inputs. An HIf takes the materialized combination as input and returns a @@ -830,7 +880,7 @@ TEST_F(CodegenTest, MaterializedCondition2) { HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena()); block->InsertInstructionBefore(move, block->GetLastInstruction()); }; - RunCode(target_isa, graph, hook_before_codegen, true, lhs[i] < rhs[i]); + RunCode(target_config, graph, hook_before_codegen, true, lhs[i] < rhs[i]); } } } @@ -859,7 +909,7 @@ static void TestComparison(IfCondition condition, int64_t i, int64_t j, Primitive::Type type, - const InstructionSet target_isa) { + const CodegenTargetConfig target_config) { ArenaPool pool; ArenaAllocator allocator(&pool); HGraph* graph = CreateGraph(&allocator); @@ -941,23 +991,16 @@ static void TestComparison(IfCondition condition, block->AddInstruction(new (&allocator) HReturn(comparison)); graph->BuildDominatorTree(); - RunCode(target_isa, graph, [](HGraph*) {}, true, expected_result); + RunCode(target_config, graph, [](HGraph*) {}, true, expected_result); } TEST_F(CodegenTest, ComparisonsInt) { - for (InstructionSet target_isa : GetTargetISAs()) { + for (CodegenTargetConfig target_config : GetTargetConfigs()) { for (int64_t i = -1; i <= 1; i++) { for (int64_t j = -1; j <= 1; j++) { - TestComparison(kCondEQ, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondNE, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondLT, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondLE, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondGT, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondGE, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondB, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondBE, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondA, i, j, Primitive::kPrimInt, target_isa); - TestComparison(kCondAE, i, j, Primitive::kPrimInt, target_isa); + for (int cond = kCondFirst; cond <= kCondLast; cond++) { + TestComparison(static_cast(cond), i, j, Primitive::kPrimInt, target_config); + } } } } @@ -969,23 +1012,17 @@ TEST_F(CodegenTest, ComparisonsLong) { return; } - for (InstructionSet target_isa : GetTargetISAs()) { - if (target_isa == kMips || target_isa == kMips64) { + for (CodegenTargetConfig target_config : GetTargetConfigs()) { + if ((target_config.GetInstructionSet() == kMips) || + (target_config.GetInstructionSet() == kMips64)) { continue; } for (int64_t i = -1; i <= 1; i++) { for (int64_t j = -1; j <= 1; j++) { - TestComparison(kCondEQ, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondNE, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondLT, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondLE, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondGT, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondGE, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondB, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondBE, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondA, i, j, Primitive::kPrimLong, target_isa); - TestComparison(kCondAE, i, j, Primitive::kPrimLong, target_isa); + for (int cond = kCondFirst; cond <= kCondLast; cond++) { + TestComparison(static_cast(cond), i, j, Primitive::kPrimLong, target_config); + } } } } diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 19e499ba8..61f4572fe 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -109,6 +109,9 @@ enum IfCondition { kCondBE, // <= kCondA, // > kCondAE, // >= + // First and last aliases. + kCondFirst = kCondEQ, + kCondLast = kCondAE, }; enum GraphAnalysisResult { -- 2.11.0