Fix StringBuilder append assumptions.
Do not rely on use ordering, it can be different because of
SimplifyReturnThis(); just use HBackwardInstructionIterator.
Instead of checking that we find a StringBuilder.toString(),
check that it is the invoke we're trying to simplify.
Add regression test 699-checker-string-append2.
Test: testrunner.py --host --jvm -t 699-checker-string-append2
Bug: 19575890
Bug: 146014745
Change-Id: I7b16f376c16ba5a4107e9718e0acf17d82280f54
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index d272bfa..17b5ad5 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -2489,6 +2489,10 @@
if (use.GetUser()->GetBlock() != block) {
return false;
}
+ // The append pattern uses the StringBuilder only as the first argument.
+ if (use.GetIndex() != 0u) {
+ return false;
+ }
}
// Collect args and check for unexpected uses.
@@ -2500,17 +2504,15 @@
uint32_t format = 0u;
uint32_t num_args = 0u;
HInstruction* args[StringBuilderAppend::kMaxArgs]; // Added in reverse order.
- for (const HUseListNode<HInstruction*>& use : sb->GetUses()) {
- // The append pattern uses the StringBuilder only as the first argument.
- if (use.GetIndex() != 0u) {
- return false;
+ 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`.
+ if (user->InputCount() == 0u || user->InputAt(0u) != sb) {
+ continue;
}
- // We see the uses in reverse order because they are inserted at the front
- // of the singly-linked list, so the StringBuilder.append() must come first.
- HInstruction* user = use.GetUser();
+ // We visit the uses in reverse order, so the StringBuilder.toString() must come first.
if (!seen_to_string) {
- if (user->IsInvokeVirtual() &&
- user->AsInvokeVirtual()->GetIntrinsic() == Intrinsics::kStringBuilderToString) {
+ if (user == invoke) {
seen_to_string = true;
continue;
} else {