summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/load_store_elimination.cc56
-rw-r--r--test/530-checker-lse/src/Main.java16
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;