Refactor the inliner.
In preparation for more polymorphic inlining, refactor the inliner
a bit.
Change-Id: Ie3fd6c1ef205f1089989c67a527e6f57ff3c8b5d
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 68e96fb..a5acab8 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -258,8 +258,9 @@
}
if (actual_method != nullptr) {
- return TryInline(invoke_instruction, actual_method);
+ return TryInlineAndReplace(invoke_instruction, actual_method, /* do_rtp */ true);
}
+
DCHECK(!invoke_instruction->IsInvokeStaticOrDirect());
// Check if we can use an inline cache.
@@ -344,7 +345,7 @@
HInstruction* cursor = invoke_instruction->GetPrevious();
HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
- if (!TryInline(invoke_instruction, resolved_method, /* do_rtp */ false)) {
+ if (!TryInlineAndReplace(invoke_instruction, resolved_method, /* do_rtp */ false)) {
return false;
}
@@ -431,7 +432,7 @@
HInstruction* cursor = invoke_instruction->GetPrevious();
HBasicBlock* bb_cursor = invoke_instruction->GetBlock();
- if (!TryInline(invoke_instruction, actual_method, /* do_rtp */ false)) {
+ if (!TryInlineAndReplace(invoke_instruction, actual_method, /* do_rtp */ false)) {
return false;
}
@@ -485,14 +486,29 @@
return true;
}
-bool HInliner::TryInline(HInvoke* invoke_instruction, ArtMethod* method, bool do_rtp) {
+bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction, ArtMethod* method, bool do_rtp) {
+ HInstruction* return_replacement = nullptr;
+ if (!TryBuildAndInline(invoke_instruction, method, &return_replacement)) {
+ return false;
+ }
+ if (return_replacement != nullptr) {
+ invoke_instruction->ReplaceWith(return_replacement);
+ }
+ invoke_instruction->GetBlock()->RemoveInstruction(invoke_instruction);
+ FixUpReturnReferenceType(invoke_instruction, method, return_replacement, do_rtp);
+ return true;
+}
+
+bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction,
+ ArtMethod* method,
+ HInstruction** return_replacement) {
const DexFile& caller_dex_file = *caller_compilation_unit_.GetDexFile();
// Check whether we're allowed to inline. The outermost compilation unit is the relevant
// dex file here (though the transitivity of an inline chain would allow checking the calller).
if (!compiler_driver_->MayInline(method->GetDexFile(),
outer_compilation_unit_.GetDexFile())) {
- if (TryPatternSubstitution(invoke_instruction, method, do_rtp)) {
+ if (TryPatternSubstitution(invoke_instruction, method, return_replacement)) {
VLOG(compiler) << "Successfully replaced pattern of invoke " << PrettyMethod(method);
MaybeRecordStat(kReplacedInvokeWithSimplePattern);
return true;
@@ -559,7 +575,7 @@
return false;
}
- if (!TryBuildAndInline(method, invoke_instruction, same_dex_file, do_rtp)) {
+ if (!TryBuildAndInlineHelper(invoke_instruction, method, same_dex_file, return_replacement)) {
return false;
}
@@ -586,27 +602,27 @@
// Try to recognize known simple patterns and replace invoke call with appropriate instructions.
bool HInliner::TryPatternSubstitution(HInvoke* invoke_instruction,
ArtMethod* resolved_method,
- bool do_rtp) {
+ HInstruction** return_replacement) {
InlineMethod inline_method;
if (!InlineMethodAnalyser::AnalyseMethodCode(resolved_method, &inline_method)) {
return false;
}
- HInstruction* return_replacement = nullptr;
switch (inline_method.opcode) {
case kInlineOpNop:
DCHECK_EQ(invoke_instruction->GetType(), Primitive::kPrimVoid);
+ *return_replacement = nullptr;
break;
case kInlineOpReturnArg:
- return_replacement = GetInvokeInputForArgVRegIndex(invoke_instruction,
- inline_method.d.return_data.arg);
+ *return_replacement = GetInvokeInputForArgVRegIndex(invoke_instruction,
+ inline_method.d.return_data.arg);
break;
case kInlineOpNonWideConst:
if (resolved_method->GetShorty()[0] == 'L') {
DCHECK_EQ(inline_method.d.data, 0u);
- return_replacement = graph_->GetNullConstant();
+ *return_replacement = graph_->GetNullConstant();
} else {
- return_replacement = graph_->GetIntConstant(static_cast<int32_t>(inline_method.d.data));
+ *return_replacement = graph_->GetIntConstant(static_cast<int32_t>(inline_method.d.data));
}
break;
case kInlineOpIGet: {
@@ -621,7 +637,7 @@
DCHECK_EQ(iget->GetFieldOffset().Uint32Value(), data.field_offset);
DCHECK_EQ(iget->IsVolatile() ? 1u : 0u, data.is_volatile);
invoke_instruction->GetBlock()->InsertInstructionBefore(iget, invoke_instruction);
- return_replacement = iget;
+ *return_replacement = iget;
break;
}
case kInlineOpIPut: {
@@ -639,7 +655,7 @@
invoke_instruction->GetBlock()->InsertInstructionBefore(iput, invoke_instruction);
if (data.return_arg_plus1 != 0u) {
size_t return_arg = data.return_arg_plus1 - 1u;
- return_replacement = GetInvokeInputForArgVRegIndex(invoke_instruction, return_arg);
+ *return_replacement = GetInvokeInputForArgVRegIndex(invoke_instruction, return_arg);
}
break;
}
@@ -694,19 +710,13 @@
HMemoryBarrier* barrier = new (graph_->GetArena()) HMemoryBarrier(kStoreStore, kNoDexPc);
invoke_instruction->GetBlock()->InsertInstructionBefore(barrier, invoke_instruction);
}
+ *return_replacement = nullptr;
break;
}
default:
LOG(FATAL) << "UNREACHABLE";
UNREACHABLE();
}
-
- if (return_replacement != nullptr) {
- invoke_instruction->ReplaceWith(return_replacement);
- }
- invoke_instruction->GetBlock()->RemoveInstruction(invoke_instruction);
-
- FixUpReturnReferenceType(resolved_method, invoke_instruction, return_replacement, do_rtp);
return true;
}
@@ -760,10 +770,10 @@
return iput;
}
-bool HInliner::TryBuildAndInline(ArtMethod* resolved_method,
- HInvoke* invoke_instruction,
- bool same_dex_file,
- bool do_rtp) {
+bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction,
+ ArtMethod* resolved_method,
+ bool same_dex_file,
+ HInstruction** return_replacement) {
ScopedObjectAccess soa(Thread::Current());
const DexFile::CodeItem* code_item = resolved_method->GetCodeItem();
const DexFile& callee_dex_file = *resolved_method->GetDexFile();
@@ -1016,16 +1026,12 @@
}
number_of_inlined_instructions_ += number_of_instructions;
- HInstruction* return_replacement = callee_graph->InlineInto(graph_, invoke_instruction);
- if (return_replacement != nullptr) {
- DCHECK_EQ(graph_, return_replacement->GetBlock()->GetGraph());
- }
- FixUpReturnReferenceType(resolved_method, invoke_instruction, return_replacement, do_rtp);
+ *return_replacement = callee_graph->InlineInto(graph_, invoke_instruction);
return true;
}
-void HInliner::FixUpReturnReferenceType(ArtMethod* resolved_method,
- HInvoke* invoke_instruction,
+void HInliner::FixUpReturnReferenceType(HInvoke* invoke_instruction,
+ ArtMethod* resolved_method,
HInstruction* return_replacement,
bool do_rtp) {
// Check the integrity of reference types and run another type propagation if needed.