From 4dc09e7261dede72d916059d1f751a48cd08dbb5 Mon Sep 17 00:00:00 2001 From: Aart Bik Date: Fri, 11 May 2018 14:40:31 -0700 Subject: LSE improvement: better singleton array optimization Rationale: In a recent LSA/LSE refactoring, we removed the "exceptional" situation on mismatched arrays from the load-elimination branch for merged values. As a direct result, we can relax the condition on removing stores for singleton arrays into return blocks a bit, as done in this CL (and shown with some tests). Test: test-art-host,target Bug: b/77906240 Change-Id: I32c89057168730f82d1d7c41155a9ff71b126204 --- compiler/optimizing/load_store_elimination.cc | 9 +++++++-- compiler/optimizing/nodes.cc | 5 +++++ compiler/optimizing/nodes.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) (limited to 'compiler') diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index 35e64f75b9..28ac94273c 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -458,8 +458,13 @@ class LSEVisitor : public HGraphDelegateVisitor { } if (from_all_predecessors) { if (ref_info->IsSingletonAndRemovable() && - block->IsSingleReturnOrReturnVoidAllowingPhis()) { - // Values in the singleton are not needed anymore. + (block->IsSingleReturnOrReturnVoidAllowingPhis() || + (block->EndsWithReturn() && (merged_value != kUnknownHeapValue || + merged_store_value != kUnknownHeapValue)))) { + // Values in the singleton are not needed anymore: + // (1) if this block consists of a sole return, or + // (2) if this block returns and a usable merged value is obtained + // (loads prior to the return will always use that value). } else if (!IsStore(merged_value)) { // We don't track merged value as a store anymore. We have to // hold the stores in predecessors live here. diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 5f2833e9a6..7f78dc257e 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -1951,6 +1951,11 @@ bool HBasicBlock::EndsWithControlFlowInstruction() const { return !GetInstructions().IsEmpty() && GetLastInstruction()->IsControlFlow(); } +bool HBasicBlock::EndsWithReturn() const { + return !GetInstructions().IsEmpty() && + (GetLastInstruction()->IsReturn() || GetLastInstruction()->IsReturnVoid()); +} + bool HBasicBlock::EndsWithIf() const { return !GetInstructions().IsEmpty() && GetLastInstruction()->IsIf(); } diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index e786502dee..09d9c57a33 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1285,6 +1285,7 @@ class HBasicBlock : public ArenaObject { void SetLifetimeEnd(size_t end) { lifetime_end_ = end; } bool EndsWithControlFlowInstruction() const; + bool EndsWithReturn() const; bool EndsWithIf() const; bool EndsWithTryBoundary() const; bool HasSinglePhi() const; -- cgit v1.2.3-59-g8ed1b