summaryrefslogtreecommitdiff
path: root/compiler/optimizing/instruction_simplifier.cc
diff options
context:
space:
mode:
author Santiago Aboy Solanes <solanes@google.com> 2021-11-01 09:02:09 +0000
committer Treehugger Robot <treehugger-gerrit@google.com> 2021-11-01 10:45:06 +0000
commite43aa3f55fd01ce0887059b309a41b6441521e7c (patch)
tree7ba4ef9adfbb77e6baa1891c3fabd783fb03d580 /compiler/optimizing/instruction_simplifier.cc
parent808d8cc8114e0c5ee3116639fe9d31be5a70403a (diff)
Revert^2 "Inline across dex files for bootclaspath's methods"
This reverts commit 8cb989f1019c4fa30845bf2deb5bc996ed4e8966, so we are re-enabling commit d690f8ae8f8e2675bc52089a83ac18c749f8e6d2. Reason for revert: Failing test was fixed here https://android-review.googlesource.com/c/platform/art/+/1873567 Bug: 154012332 Test: ART tests Change-Id: If159b29583e35abcfe753f30483f83990208b1b9
Diffstat (limited to 'compiler/optimizing/instruction_simplifier.cc')
-rw-r--r--compiler/optimizing/instruction_simplifier.cc45
1 files changed, 38 insertions, 7 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 91b2e8bdc6..3f1f3b0f8d 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -2645,12 +2645,15 @@ static bool TryReplaceStringBuilderAppend(HInvoke* invoke) {
// Collect args and check for unexpected uses.
// We expect one call to a constructor with no arguments, one constructor fence (unless
// eliminated), some number of append calls and one call to StringBuilder.toString().
+ bool constructor_inlined = false;
bool seen_constructor = false;
bool seen_constructor_fence = false;
bool seen_to_string = false;
uint32_t format = 0u;
uint32_t num_args = 0u;
HInstruction* args[StringBuilderAppend::kMaxArgs]; // Added in reverse order.
+ // When inlining, `maybe_new_array` tracks an environment use that we want to allow.
+ HInstruction* maybe_new_array = nullptr;
for (HBackwardInstructionIterator iter(block->GetInstructions()); !iter.Done(); iter.Advance()) {
HInstruction* user = iter.Current();
// Instructions of interest apply to `sb`, skip those that do not involve `sb`.
@@ -2731,13 +2734,25 @@ static bool TryReplaceStringBuilderAppend(HInvoke* invoke) {
format = (format << StringBuilderAppend::kBitsPerArg) | static_cast<uint32_t>(arg);
args[num_args] = as_invoke_virtual->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);
+ } else if (!seen_constructor) {
+ // At this point, we should see the constructor. However, we might have inlined it so we have
+ // to take care of both cases. We accept only the constructor with no extra arguments. This
+ // means that if we inline it, we have to check it is setting its field to a new array.
+ if (user->IsInvokeStaticOrDirect() &&
+ user->AsInvokeStaticOrDirect()->GetResolvedMethod() != nullptr &&
+ user->AsInvokeStaticOrDirect()->GetResolvedMethod()->IsConstructor() &&
+ user->AsInvokeStaticOrDirect()->GetNumberOfArguments() == 1u) {
+ constructor_inlined = false;
+ } else if (user->IsInstanceFieldSet() &&
+ user->AsInstanceFieldSet()->GetFieldType() == DataType::Type::kReference &&
+ user->AsInstanceFieldSet()->InputAt(0) == sb &&
+ user->AsInstanceFieldSet()->GetValue()->IsNewArray()) {
+ maybe_new_array = user->AsInstanceFieldSet()->GetValue();
+ constructor_inlined = true;
+ } else {
+ // We were expecting a constructor but we haven't seen it. Abort optimization.
+ return false;
+ }
DCHECK(!seen_constructor_fence);
seen_constructor = true;
} else if (user->IsConstructorFence()) {
@@ -2763,6 +2778,10 @@ static bool TryReplaceStringBuilderAppend(HInvoke* invoke) {
// Accept only calls on the StringBuilder (which shall all be removed).
// TODO: Carve-out for const-string? Or rely on environment pruning (to be implemented)?
if (holder->InputCount() == 0 || holder->InputAt(0) != sb) {
+ // When inlining the constructor, we have a NewArray as an environment use.
+ if (constructor_inlined && holder == maybe_new_array) {
+ continue;
+ }
return false;
}
}
@@ -2796,6 +2815,18 @@ static bool TryReplaceStringBuilderAppend(HInvoke* invoke) {
while (sb->HasNonEnvironmentUses()) {
block->RemoveInstruction(sb->GetUses().front().GetUser());
}
+ if (constructor_inlined) {
+ // We need to remove the inlined constructor instructions. That also removes all remaining
+ // environment uses.
+ DCHECK(sb->HasEnvironmentUses());
+ DCHECK(maybe_new_array != nullptr);
+ DCHECK(maybe_new_array->IsNewArray());
+ DCHECK(maybe_new_array->HasNonEnvironmentUses());
+ HInstruction* fence = maybe_new_array->GetUses().front().GetUser();
+ DCHECK(fence->IsConstructorFence());
+ block->RemoveInstruction(fence);
+ block->RemoveInstruction(maybe_new_array);
+ }
DCHECK(!sb->HasEnvironmentUses());
block->RemoveInstruction(sb);
return true;