diff options
author | 2017-11-21 16:31:53 -0800 | |
---|---|---|
committer | 2017-11-24 17:06:40 -0800 | |
commit | f0010dd946b17490d2f792d845ea4f304a0bea28 (patch) | |
tree | e68b071ef742766090d722129c8c1d04ba2f90b0 /compiler/optimizing | |
parent | 6f99acac2e1d60dfb1ed45ce69ec5a542847687e (diff) |
Apply individual intrinsic recognition during inliner.
Rationale:
Inliner could introduce new method calls, in particular
it could change invoke-interface to invoke-virtual,
which could expose new intrinsics. This situation
happens, for example, in Kotlin generated code where
String operations first go through the CharSequence
interface. Rather than running a full new phase,
we just recognize intrinsics when interface calls
are replaced by virtual calls.
This optimization boosts KotlinMicroItems by 100%
Test: test-art-host test-art-target
Change-Id: Ibd0519283d67ed6997b056e34b4eafdd49fcbc2d
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/inliner.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.cc | 42 | ||||
-rw-r--r-- | compiler/optimizing/intrinsics.h | 5 |
3 files changed, 37 insertions, 17 deletions
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 3f4a3d8b8e..1eb1f2e46b 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -1258,6 +1258,13 @@ bool HInliner::TryInlineAndReplace(HInvoke* invoke_instruction, new_invoke->SetReferenceTypeInfo(invoke_instruction->GetReferenceTypeInfo()); } return_replacement = new_invoke; + // Directly check if the new virtual can be recognized as an intrinsic. + // This way, we avoid running a full recognition pass just to detect + // these relative rare cases. + bool wrong_invoke_type = false; + if (IntrinsicsRecognizer::Recognize(new_invoke, &wrong_invoke_type)) { + MaybeRecordStat(stats_, kIntrinsicRecognized); + } } else { // TODO: Consider sharpening an invoke virtual once it is not dependent on the // compiler driver. diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index dfae534555..210607f88b 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -144,6 +144,23 @@ static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke) { } } +bool IntrinsicsRecognizer::Recognize(HInvoke* invoke, /*out*/ bool* wrong_invoke_type) { + ArtMethod* art_method = invoke->GetResolvedMethod(); + if (art_method != nullptr && art_method->IsIntrinsic()) { + Intrinsics intrinsic = static_cast<Intrinsics>(art_method->GetIntrinsic()); + if (CheckInvokeType(intrinsic, invoke)) { + invoke->SetIntrinsic(intrinsic, + NeedsEnvironmentOrCache(intrinsic), + GetSideEffects(intrinsic), + GetExceptions(intrinsic)); + return true; + } else { + *wrong_invoke_type = true; + } + } + return false; +} + void IntrinsicsRecognizer::Run() { ScopedObjectAccess soa(Thread::Current()); for (HBasicBlock* block : graph_->GetReversePostOrder()) { @@ -151,23 +168,14 @@ void IntrinsicsRecognizer::Run() { inst_it.Advance()) { HInstruction* inst = inst_it.Current(); if (inst->IsInvoke()) { - HInvoke* invoke = inst->AsInvoke(); - ArtMethod* art_method = invoke->GetResolvedMethod(); - if (art_method != nullptr && art_method->IsIntrinsic()) { - Intrinsics intrinsic = static_cast<Intrinsics>(art_method->GetIntrinsic()); - if (!CheckInvokeType(intrinsic, invoke)) { - LOG(WARNING) << "Found an intrinsic with unexpected invoke type: " - << static_cast<uint32_t>(intrinsic) << " for " - << art_method->PrettyMethod() - << invoke->DebugName(); - } else { - invoke->SetIntrinsic(intrinsic, - NeedsEnvironmentOrCache(intrinsic), - GetSideEffects(intrinsic), - GetExceptions(intrinsic)); - MaybeRecordStat(stats_, - MethodCompilationStat::kIntrinsicRecognized); - } + bool wrong_invoke_type = false; + if (Recognize(inst->AsInvoke(), &wrong_invoke_type)) { + MaybeRecordStat(stats_, MethodCompilationStat::kIntrinsicRecognized); + } else if (wrong_invoke_type) { + LOG(WARNING) + << "Found an intrinsic with unexpected invoke type: " + << inst->AsInvoke()->GetResolvedMethod()->PrettyMethod() << " " + << inst->DebugName(); } } } diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h index 818d7f63a3..8088ab25a7 100644 --- a/compiler/optimizing/intrinsics.h +++ b/compiler/optimizing/intrinsics.h @@ -44,6 +44,11 @@ class IntrinsicsRecognizer : public HOptimization { void Run() OVERRIDE; + // Static helper that recognizes intrinsic call. Returns true on success. + // If it fails due to invoke type mismatch, wrong_invoke_type is set. + // Useful to recognize intrinsics on invidual calls outside this full pass. + static bool Recognize(HInvoke* invoke, /*out*/ bool* wrong_invoke_type); + static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition"; private: |