summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/Android.mk3
-rw-r--r--compiler/optimizing/gvn.h6
-rw-r--r--compiler/optimizing/instruction_simplifier_arm64.cc23
-rw-r--r--compiler/optimizing/instruction_simplifier_arm64.h56
-rw-r--r--compiler/optimizing/optimizing_compiler.cc32
-rw-r--r--compiler/optimizing/optimizing_compiler_stats.h2
-rw-r--r--runtime/oat_file_assistant_test.cc103
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.