diff options
| -rw-r--r-- | compiler/optimizing/load_store_elimination.cc | 56 | ||||
| -rw-r--r-- | test/530-checker-lse/src/Main.java | 16 |
2 files changed, 60 insertions, 12 deletions
diff --git a/compiler/optimizing/load_store_elimination.cc b/compiler/optimizing/load_store_elimination.cc index b91e9e6868..5b2cbf783d 100644 --- a/compiler/optimizing/load_store_elimination.cc +++ b/compiler/optimizing/load_store_elimination.cc @@ -663,27 +663,59 @@ class LSEVisitor : public HGraphVisitor { if (predecessors.size() == 0) { return; } + ArenaVector<HInstruction*>& heap_values = heap_values_for_[block->GetBlockId()]; for (size_t i = 0; i < heap_values.size(); i++) { - HInstruction* pred0_value = heap_values_for_[predecessors[0]->GetBlockId()][i]; - heap_values[i] = pred0_value; - if (pred0_value != kUnknownHeapValue) { - for (size_t j = 1; j < predecessors.size(); j++) { - HInstruction* pred_value = heap_values_for_[predecessors[j]->GetBlockId()][i]; - if (pred_value != pred0_value) { - heap_values[i] = kUnknownHeapValue; - break; - } + HInstruction* merged_value = nullptr; + // Whether merged_value is a result that's merged from all predecessors. + bool from_all_predecessors = true; + ReferenceInfo* ref_info = heap_location_collector_.GetHeapLocation(i)->GetReferenceInfo(); + HInstruction* singleton_ref = nullptr; + if (ref_info->IsSingletonAndNotReturned()) { + // We do more analysis of liveness when merging heap values for such + // cases since stores into such references may potentially be eliminated. + singleton_ref = ref_info->GetReference(); + } + + for (HBasicBlock* predecessor : predecessors) { + HInstruction* pred_value = heap_values_for_[predecessor->GetBlockId()][i]; + if ((singleton_ref != nullptr) && + !singleton_ref->GetBlock()->Dominates(predecessor)) { + // singleton_ref is not live in this predecessor. Skip this predecessor since + // it does not really have the location. + DCHECK_EQ(pred_value, kUnknownHeapValue); + from_all_predecessors = false; + continue; + } + if (merged_value == nullptr) { + // First seen heap value. + merged_value = pred_value; + } else if (pred_value != merged_value) { + // There are conflicting values. + merged_value = kUnknownHeapValue; + break; } } - if (heap_values[i] == kUnknownHeapValue) { + if (merged_value == kUnknownHeapValue) { + // There are conflicting heap values from different predecessors. // Keep the last store in each predecessor since future loads cannot be eliminated. - for (size_t j = 0; j < predecessors.size(); j++) { - ArenaVector<HInstruction*>& pred_values = heap_values_for_[predecessors[j]->GetBlockId()]; + for (HBasicBlock* predecessor : predecessors) { + ArenaVector<HInstruction*>& pred_values = heap_values_for_[predecessor->GetBlockId()]; KeepIfIsStore(pred_values[i]); } } + + if ((merged_value == nullptr) || !from_all_predecessors) { + DCHECK(singleton_ref != nullptr); + DCHECK((singleton_ref->GetBlock() == block) || + !singleton_ref->GetBlock()->Dominates(block)); + // singleton_ref is not defined before block or defined only in some of its + // predecessors, so block doesn't really have the location at its entry. + heap_values[i] = kUnknownHeapValue; + } else { + heap_values[i] = merged_value; + } } } diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java index 6b0dedfe9d..a61b9a0c06 100644 --- a/test/530-checker-lse/src/Main.java +++ b/test/530-checker-lse/src/Main.java @@ -744,6 +744,20 @@ public class Main { return 1.0f; } + /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (before) + /// CHECK: NewInstance + + /// CHECK-START: double Main.getCircleArea(double, boolean) load_store_elimination (after) + /// CHECK-NOT: NewInstance + + private static double getCircleArea(double radius, boolean b) { + double area = 0d; + if (b) { + area = new Circle(radius).getArea(); + } + return area; + } + static void assertIntEquals(int result, int expected) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); @@ -808,6 +822,8 @@ public class Main { assertIntEquals(sumWithinRange(array, 1, 5), 11); assertFloatEquals(testAllocationEliminationWithLoops(), 1.0f); assertFloatEquals(mF, 0f); + assertDoubleEquals(Math.PI * Math.PI * Math.PI, getCircleArea(Math.PI, true)); + assertDoubleEquals(0d, getCircleArea(Math.PI, false)); } static boolean sFlag; |