diff options
author | 2024-11-14 15:09:41 +0000 | |
---|---|---|
committer | 2024-11-21 12:39:22 +0000 | |
commit | a21eb118c8c1e9d362b7465327f1fae8db48a572 (patch) | |
tree | e5542170e0de695c9dd491fa7b77a7deb73e28ae /compiler/optimizing/instruction_simplifier.cc | |
parent | 53d8174b0003eb22192aba21d54ca96947002151 (diff) |
Allow the inliner to devirtualize intrinsics
To do so update:
* TryReplaceStringBuilderAppend
* Code paths relevant to previously InvokeVirtual that are now
InvokeStaticOrDirect
* checker tests.
Bug: 369206455
Test: art/test/testrunner/testrunner.py --host --64 -b --optimizing
Change-Id: I4d40980e416f3130d3c344c5f07b7b331deb5c97
Diffstat (limited to 'compiler/optimizing/instruction_simplifier.cc')
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 931050855c..703f6c77e8 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -2976,13 +2976,8 @@ void InstructionSimplifierVisitor::SimplifyReturnThis(HInvoke* invoke) { // Helper method for StringBuffer escape analysis. static bool NoEscapeForStringBufferReference(HInstruction* reference, HInstruction* user) { - if (user->IsInvokeStaticOrDirect()) { - // Any constructor on StringBuffer is okay. - return user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr && - user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() && - user->InputAt(0) == reference; - } else if (user->IsInvokeVirtual()) { - switch (user->AsInvokeVirtual()->GetIntrinsic()) { + if (user->IsInvoke()) { + switch (user->AsInvoke()->GetIntrinsic()) { case Intrinsics::kStringBufferLength: case Intrinsics::kStringBufferToString: DCHECK_EQ(user->InputAt(0), reference); @@ -2996,6 +2991,14 @@ static bool NoEscapeForStringBufferReference(HInstruction* reference, HInstructi break; } } + + if (user->IsInvokeStaticOrDirect()) { + // Any constructor on StringBuffer is okay. + return user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr && + user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() && + user->InputAt(0) == reference; + } + return false; } @@ -3051,13 +3054,24 @@ static bool TryReplaceStringBuilderAppend(CodeGenerator* codegen, HInvoke* invok return false; } } - // Then we should see the arguments. - if (user->IsInvokeVirtual()) { - HInvokeVirtual* as_invoke_virtual = user->AsInvokeVirtual(); + + // Pattern match seeing arguments, then constructor, then constructor fence. + if (user->IsInvokeStaticOrDirect() && + user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr && + user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() && + user->AsInvokeStaticOrDirect()->GetNumberOfArguments() == 1u) { + // After arguments, we should see the constructor. + // We accept only the constructor with no extra arguments. + DCHECK(!seen_constructor); + DCHECK(!seen_constructor_fence); + seen_constructor = true; + } else if (user->IsInvoke()) { + // The arguments. + HInvoke* as_invoke = user->AsInvoke(); DCHECK(!seen_constructor); DCHECK(!seen_constructor_fence); StringBuilderAppend::Argument arg; - switch (as_invoke_virtual->GetIntrinsic()) { + switch (as_invoke->GetIntrinsic()) { case Intrinsics::kStringBuilderAppendObject: // TODO: Unimplemented, needs to call String.valueOf(). return false; @@ -3089,7 +3103,7 @@ static bool TryReplaceStringBuilderAppend(CodeGenerator* codegen, HInvoke* invok has_fp_args = true; break; case Intrinsics::kStringBuilderAppendCharSequence: { - ReferenceTypeInfo rti = user->AsInvokeVirtual()->InputAt(1)->GetReferenceTypeInfo(); + ReferenceTypeInfo rti = as_invoke->InputAt(1)->GetReferenceTypeInfo(); if (!rti.IsValid()) { return false; } @@ -3112,23 +3126,14 @@ static bool TryReplaceStringBuilderAppend(CodeGenerator* codegen, HInvoke* invok } } // Uses of the append return value should have been replaced with the first input. - DCHECK(!as_invoke_virtual->HasUses()); - DCHECK(!as_invoke_virtual->HasEnvironmentUses()); + DCHECK(!as_invoke->HasUses()); + DCHECK(!as_invoke->HasEnvironmentUses()); if (num_args == StringBuilderAppend::kMaxArgs) { return false; } format = (format << StringBuilderAppend::kBitsPerArg) | static_cast<uint32_t>(arg); - args[num_args] = as_invoke_virtual->InputAt(1u); + args[num_args] = as_invoke->InputAt(1u); ++num_args; - } else if (user->IsInvokeStaticOrDirect() && - user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr && - user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() && - user->AsInvokeStaticOrDirect()->GetNumberOfArguments() == 1u) { - // After arguments, we should see the constructor. - // We accept only the constructor with no extra arguments. - DCHECK(!seen_constructor); - DCHECK(!seen_constructor_fence); - seen_constructor = true; } else if (user->IsConstructorFence()) { // The last use we see is the constructor fence. DCHECK(seen_constructor); |