ART: Enable basic optimizations for try/catch
Generating code for try/catch methods requires having run at least the
instruction simplifier to remove redundant suspend checks. This patch
enables the first group of optimizations when try/catch is present.
Enabled optimizations:
1) IntrinsicsRecognizer
Does not modify the graph, only sets HInvoke::intrinsic_.
2) ConstantFolding
Does not deal with throwing instructions.
3) InstructionSimplifier
May remove a throwing instruction (e.g. LoadClass in VisitCheckCast),
or may turn a throwing instruction into a non-throwing one (ArraySet).
Their corresponding catch phi inputs are not removed but correctness
is preserved.
4) ReferenceTypePropagation
Does not modify the graph, only sets type properties. Typing of
LoadException from catch handler information was added.
5) DeadCodeElimination
Removing individual instructions is fine (same as 3). Removal of dead
blocks was disabled for try/catch.
Change-Id: I2722c3229eb8aaf326391e07f522dbf5186774b8
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 866e717..bd40c9f 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -359,11 +359,6 @@
|| instruction_set == kX86_64;
}
-static bool CanOptimize(const DexFile::CodeItem& code_item) {
- // TODO: We currently cannot optimize methods with try/catch.
- return code_item.tries_size_ == 0;
-}
-
static void RunOptimizations(HOptimization* optimizations[],
size_t length,
PassObserver* pass_observer) {
@@ -470,6 +465,13 @@
RunOptimizations(optimizations1, arraysize(optimizations1), pass_observer);
+ if (graph->HasTryCatch()) {
+ // TODO: Update the optimizations below to work correctly under try/catch
+ // semantics. The optimizations above suffice for running codegen
+ // in the meanwhile.
+ return;
+ }
+
MaybeRunInliner(graph, driver, stats, dex_compilation_unit, pass_observer, handles);
HOptimization* optimizations2[] = {
@@ -529,6 +531,10 @@
RunOptimizations(graph, compiler_driver, compilation_stats_.get(),
dex_compilation_unit, pass_observer, &handles);
+ if (graph->HasTryCatch()) {
+ return nullptr;
+ }
+
AllocateRegisters(graph, codegen, pass_observer);
CodeVectorAllocator allocator;
@@ -717,7 +723,6 @@
}
}
- bool can_optimize = CanOptimize(*code_item);
bool can_allocate_registers = RegisterAllocator::CanAllocateRegistersFor(*graph, instruction_set);
// `run_optimizations_` is set explicitly (either through a compiler filter
@@ -738,16 +743,12 @@
}
}
- if (can_optimize) {
- return CompileOptimized(graph,
- codegen.get(),
- compiler_driver,
- dex_compilation_unit,
- &pass_observer);
- }
- }
-
- if (shouldOptimize && can_allocate_registers) {
+ return CompileOptimized(graph,
+ codegen.get(),
+ compiler_driver,
+ dex_compilation_unit,
+ &pass_observer);
+ } else if (shouldOptimize && can_allocate_registers) {
LOG(FATAL) << "Could not allocate registers in optimizing compiler";
UNREACHABLE();
} else if (can_use_baseline) {
@@ -755,8 +756,6 @@
if (!run_optimizations_) {
MaybeRecordStat(MethodCompilationStat::kNotOptimizedDisabled);
- } else if (!can_optimize) {
- MaybeRecordStat(MethodCompilationStat::kNotOptimizedTryCatch);
} else if (!can_allocate_registers) {
MaybeRecordStat(MethodCompilationStat::kNotOptimizedRegisterAllocator);
}