diff options
-rw-r--r-- | compiler/Android.mk | 3 | ||||
-rw-r--r-- | compiler/optimizing/gvn.h | 6 | ||||
-rw-r--r-- | compiler/optimizing/instruction_simplifier_arm64.cc | 23 | ||||
-rw-r--r-- | compiler/optimizing/instruction_simplifier_arm64.h | 56 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler.cc | 32 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_compiler_stats.h | 2 | ||||
-rw-r--r-- | runtime/oat_file_assistant_test.cc | 103 |
7 files changed, 172 insertions, 53 deletions
diff --git a/compiler/Android.mk b/compiler/Android.mk index 7d368a2e80..8b56880ac0 100644 --- a/compiler/Android.mk +++ b/compiler/Android.mk @@ -62,8 +62,8 @@ LIBART_COMPILER_SRC_FILES := \ jni/quick/calling_convention.cc \ jni/quick/jni_compiler.cc \ optimizing/boolean_simplifier.cc \ - optimizing/builder.cc \ optimizing/bounds_check_elimination.cc \ + optimizing/builder.cc \ optimizing/code_generator.cc \ optimizing/code_generator_utils.cc \ optimizing/constant_folding.cc \ @@ -136,6 +136,7 @@ LIBART_COMPILER_SRC_FILES_arm64 := \ jni/quick/arm64/calling_convention_arm64.cc \ linker/arm64/relative_patcher_arm64.cc \ optimizing/code_generator_arm64.cc \ + optimizing/instruction_simplifier_arm64.cc \ optimizing/intrinsics_arm64.cc \ utils/arm64/assembler_arm64.cc \ utils/arm64/managed_register_arm64.cc \ diff --git a/compiler/optimizing/gvn.h b/compiler/optimizing/gvn.h index 14a503b910..4fdba26ebd 100644 --- a/compiler/optimizing/gvn.h +++ b/compiler/optimizing/gvn.h @@ -26,8 +26,10 @@ class SideEffectsAnalysis; class GVNOptimization : public HOptimization { public: - GVNOptimization(HGraph* graph, const SideEffectsAnalysis& side_effects) - : HOptimization(graph, kGlobalValueNumberingPassName), side_effects_(side_effects) {} + GVNOptimization(HGraph* graph, + const SideEffectsAnalysis& side_effects, + const char* pass_name = kGlobalValueNumberingPassName) + : HOptimization(graph, pass_name), side_effects_(side_effects) {} void Run() OVERRIDE; diff --git a/compiler/optimizing/instruction_simplifier_arm64.cc b/compiler/optimizing/instruction_simplifier_arm64.cc new file mode 100644 index 0000000000..4b2d36f443 --- /dev/null +++ b/compiler/optimizing/instruction_simplifier_arm64.cc @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "instruction_simplifier_arm64.h" + +namespace art { +namespace arm64 { + +} // namespace arm64 +} // namespace art diff --git a/compiler/optimizing/instruction_simplifier_arm64.h b/compiler/optimizing/instruction_simplifier_arm64.h new file mode 100644 index 0000000000..d7f4eaee80 --- /dev/null +++ b/compiler/optimizing/instruction_simplifier_arm64.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_ARM64_H_ +#define ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_ARM64_H_ + +#include "nodes.h" +#include "optimization.h" + +namespace art { +namespace arm64 { + +class InstructionSimplifierArm64Visitor : public HGraphVisitor { + public: + InstructionSimplifierArm64Visitor(HGraph* graph, OptimizingCompilerStats* stats) + : HGraphVisitor(graph), stats_(stats) {} + + private: + void RecordSimplification() { + if (stats_ != nullptr) { + stats_->RecordStat(kInstructionSimplificationsArch); + } + } + + OptimizingCompilerStats* stats_; +}; + + +class InstructionSimplifierArm64 : public HOptimization { + public: + InstructionSimplifierArm64(HGraph* graph, OptimizingCompilerStats* stats) + : HOptimization(graph, "instruction_simplifier_arm64", stats) {} + + void Run() OVERRIDE { + InstructionSimplifierArm64Visitor visitor(graph_, stats_); + visitor.VisitReversePostOrder(); + } +}; + +} // namespace arm64 +} // namespace art + +#endif // ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_ARM64_H_ diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 6a50b7d4a4..866e71705f 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -19,6 +19,10 @@ #include <fstream> #include <stdint.h> +#ifdef ART_ENABLE_CODEGEN_arm64 +#include "instruction_simplifier_arm64.h" +#endif + #include "art_method-inl.h" #include "base/arena_allocator.h" #include "base/dumpable.h" @@ -399,6 +403,32 @@ static void MaybeRunInliner(HGraph* graph, RunOptimizations(optimizations, arraysize(optimizations), pass_observer); } +static void RunArchOptimizations(InstructionSet instruction_set, + HGraph* graph, + OptimizingCompilerStats* stats, + PassObserver* pass_observer) { + ArenaAllocator* arena = graph->GetArena(); + switch (instruction_set) { +#ifdef ART_ENABLE_CODEGEN_arm64 + case kArm64: { + arm64::InstructionSimplifierArm64* simplifier = + new (arena) arm64::InstructionSimplifierArm64(graph, stats); + SideEffectsAnalysis* side_effects = new (arena) SideEffectsAnalysis(graph); + GVNOptimization* gvn = new (arena) GVNOptimization(graph, *side_effects, "GVN_after_arch"); + HOptimization* arm64_optimizations[] = { + simplifier, + side_effects, + gvn + }; + RunOptimizations(arm64_optimizations, arraysize(arm64_optimizations), pass_observer); + break; + } +#endif + default: + break; + } +} + static void RunOptimizations(HGraph* graph, CompilerDriver* driver, OptimizingCompilerStats* stats, @@ -460,6 +490,8 @@ static void RunOptimizations(HGraph* graph, }; RunOptimizations(optimizations2, arraysize(optimizations2), pass_observer); + + RunArchOptimizations(driver->GetInstructionSet(), graph, stats, pass_observer); } // The stack map we generate must be 4-byte aligned on ARM. Since existing diff --git a/compiler/optimizing/optimizing_compiler_stats.h b/compiler/optimizing/optimizing_compiler_stats.h index 53d052b2bc..da5cb578b8 100644 --- a/compiler/optimizing/optimizing_compiler_stats.h +++ b/compiler/optimizing/optimizing_compiler_stats.h @@ -32,6 +32,7 @@ enum MethodCompilationStat { kCompiledQuick, kInlinedInvoke, kInstructionSimplifications, + kInstructionSimplificationsArch, kNotCompiledBranchOutsideMethodCode, kNotCompiledCannotBuildSSA, kNotCompiledCantAccesType, @@ -101,6 +102,7 @@ class OptimizingCompilerStats { case kCompiledQuick : return "kCompiledQuick"; case kInlinedInvoke : return "kInlinedInvoke"; case kInstructionSimplifications: return "kInstructionSimplifications"; + case kInstructionSimplificationsArch: return "kInstructionSimplificationsArch"; case kNotCompiledBranchOutsideMethodCode: return "kNotCompiledBranchOutsideMethodCode"; case kNotCompiledCannotBuildSSA : return "kNotCompiledCannotBuildSSA"; case kNotCompiledCantAccesType : return "kNotCompiledCantAccesType"; diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index 03ad2d5ac8..20347a9063 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -38,28 +38,6 @@ namespace art { -// Some tests very occasionally fail: we expect to have an unrelocated non-pic -// odex file that is reported as needing relocation, but it is reported -// instead as being up to date (b/22599792). -// -// This function adds extra checks for diagnosing why the given oat file is -// reported up to date, when it should be non-pic needing relocation. -// These extra diagnostics checks should be removed once b/22599792 has been -// resolved. -static void DiagnoseFlakyTestFailure(const OatFile& oat_file) { - Runtime* runtime = Runtime::Current(); - const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace(); - ASSERT_TRUE(image_space != nullptr); - const ImageHeader& image_header = image_space->GetImageHeader(); - const OatHeader& oat_header = oat_file.GetOatHeader(); - EXPECT_FALSE(oat_file.IsPic()); - EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum()); - EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()), - oat_header.GetImageFileLocationOatDataBegin()); - EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta()); -} - - class OatFileAssistantTest : public CommonRuntimeTest { public: virtual void SetUp() { @@ -206,28 +184,65 @@ class OatFileAssistantTest : public CommonRuntimeTest { return odex_dir_; } - // Generate an odex file for the purposes of test. - // If pic is true, generates a PIC odex. + // Generate a non-PIC odex file for the purposes of test. // The generated odex file will be un-relocated. void GenerateOdexForTest(const std::string& dex_location, - const std::string& odex_location, - bool pic = false) { - // For this operation, we temporarily redirect the dalvik cache so dex2oat - // doesn't find the relocated image file. + const std::string& odex_location) { + // To generate an un-relocated odex file, we first compile a relocated + // version of the file, then manually call patchoat to make it look as if + // it is unrelocated. + std::string relocated_odex_location = odex_location + ".relocated"; + std::vector<std::string> args; + args.push_back("--dex-file=" + dex_location); + args.push_back("--oat-file=" + relocated_odex_location); + args.push_back("--include-patch-information"); + + // We need to use the quick compiler to generate non-PIC code, because + // the optimizing compiler always generates PIC. + args.push_back("--compiler-backend=Quick"); + + std::string error_msg; + ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg; + + // Use patchoat to unrelocate the relocated odex file. + Runtime* runtime = Runtime::Current(); + std::vector<std::string> argv; + argv.push_back(runtime->GetPatchoatExecutable()); + argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(kRuntimeISA))); + argv.push_back("--input-oat-file=" + relocated_odex_location); + argv.push_back("--output-oat-file=" + odex_location); + argv.push_back("--base-offset-delta=0x00008000"); + std::string command_line(Join(argv, ' ')); + ASSERT_TRUE(Exec(argv, &error_msg)) << error_msg; + + // Verify the odex file was generated as expected and really is + // unrelocated. + std::unique_ptr<OatFile> odex_file(OatFile::Open( + odex_location.c_str(), odex_location.c_str(), nullptr, nullptr, + false, dex_location.c_str(), &error_msg)); + ASSERT_TRUE(odex_file.get() != nullptr) << error_msg; + + const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace(); + ASSERT_TRUE(image_space != nullptr); + const ImageHeader& image_header = image_space->GetImageHeader(); + const OatHeader& oat_header = odex_file->GetOatHeader(); + EXPECT_FALSE(odex_file->IsPic()); + EXPECT_EQ(image_header.GetOatChecksum(), oat_header.GetImageFileLocationOatChecksum()); + EXPECT_NE(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()), + oat_header.GetImageFileLocationOatDataBegin()); + EXPECT_NE(image_header.GetPatchDelta(), oat_header.GetImagePatchDelta()); + } + + void GeneratePicOdexForTest(const std::string& dex_location, + const std::string& odex_location) { + // Temporarily redirect the dalvik cache so dex2oat doesn't find the + // relocated image file. std::string android_data_tmp = GetScratchDir() + "AndroidDataTmp"; setenv("ANDROID_DATA", android_data_tmp.c_str(), 1); std::vector<std::string> args; args.push_back("--dex-file=" + dex_location); args.push_back("--oat-file=" + odex_location); - if (pic) { - args.push_back("--compile-pic"); - } else { - args.push_back("--include-patch-information"); - - // We need to use the quick compiler to generate non-PIC code, because - // the optimizing compiler always generates PIC. - args.push_back("--compiler-backend=Quick"); - } + args.push_back("--compile-pic"); args.push_back("--runtime-arg"); args.push_back("-Xnorelocate"); std::string error_msg; @@ -239,15 +254,7 @@ class OatFileAssistantTest : public CommonRuntimeTest { odex_location.c_str(), odex_location.c_str(), nullptr, nullptr, false, dex_location.c_str(), &error_msg)); ASSERT_TRUE(odex_file.get() != nullptr) << error_msg; - - if (!pic) { - DiagnoseFlakyTestFailure(*odex_file); - } - } - - void GeneratePicOdexForTest(const std::string& dex_location, - const std::string& odex_location) { - GenerateOdexForTest(dex_location, odex_location, true); + EXPECT_TRUE(odex_file->IsPic()); } private: @@ -507,8 +514,6 @@ TEST_F(OatFileAssistantTest, DexOdexNoOat) { // We should still be able to get the non-executable odex file to run from. std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); ASSERT_TRUE(oat_file.get() != nullptr); - - DiagnoseFlakyTestFailure(*oat_file); } // Case: We have a stripped DEX file and an ODEX file, but no OAT file. @@ -750,8 +755,6 @@ TEST_F(OatFileAssistantTest, OdexOatOverlap) { std::vector<std::unique_ptr<const DexFile>> dex_files; dex_files = oat_file_assistant.LoadDexFiles(*oat_file, dex_location.c_str()); EXPECT_EQ(1u, dex_files.size()); - - DiagnoseFlakyTestFailure(*oat_file); } // Case: We have a DEX file and a PIC ODEX file, but no OAT file. |