Temporarily disable partial LSE.
Due to a bug in it. Add a regression test.
Bug: 197818595
Test: 828-partial-lse
Change-Id: I65da4f7ef09cd2a1f6c4b21799ecd7a42c1adac2
diff --git a/compiler/optimizing/load_store_elimination.h b/compiler/optimizing/load_store_elimination.h
index e73ef5e..6ad2eb2 100644
--- a/compiler/optimizing/load_store_elimination.h
+++ b/compiler/optimizing/load_store_elimination.h
@@ -27,7 +27,7 @@
public:
// Whether or not we should attempt partial Load-store-elimination which
// requires additional blocks and predicated instructions.
- static constexpr bool kEnablePartialLSE = true;
+ static constexpr bool kEnablePartialLSE = false;
// Controls whether to enable VLOG(compiler) logs explaining the transforms taking place.
static constexpr bool kVerboseLoggingMode = false;
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index 35f1dc2..a707a8a 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -3964,249 +3964,6 @@
return res;
}
- /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (before)
- /// CHECK-DAG: ParameterValue
- /// CHECK-DAG: NewInstance
- /// CHECK-DAG: InvokeStaticOrDirect
- /// CHECK-DAG: InvokeStaticOrDirect
- /// CHECK-DAG: InvokeStaticOrDirect
- /// CHECK-DAG: InstanceFieldSet
- /// CHECK-DAG: InstanceFieldSet
- /// CHECK-DAG: InstanceFieldSet
- /// CHECK-DAG: InstanceFieldGet
- /// CHECK-DAG: InstanceFieldGet
- //
- /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
- /// CHECK-DAG: ParameterValue
- /// CHECK-DAG: NewInstance
- /// CHECK-DAG: Phi
- //
- /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
- /// CHECK: InvokeStaticOrDirect
- /// CHECK: InvokeStaticOrDirect
- /// CHECK: InvokeStaticOrDirect
- //
- /// CHECK-NOT: InvokeStaticOrDirect
-
- /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet predicated:false
- /// CHECK-NOT: InstanceFieldSet predicated:false
- //
- /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet predicated:true
- /// CHECK-NOT: InstanceFieldSet predicated:true
- //
- /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldGet
- //
- /// CHECK-NOT: InstanceFieldGet
- //
- /// CHECK-START: int Main.$noinline$testPartialEscape2(TestClass, boolean) load_store_elimination (after)
- /// CHECK: PredicatedInstanceFieldGet
- //
- /// CHECK-NOT: PredicatedInstanceFieldGet
- private static int $noinline$testPartialEscape2(TestClass obj, boolean escape) {
- TestClass i = new SubTestClass();
- if ($noinline$getBoolean(escape)) {
- i.next = obj;
- $noinline$Escape(i);
- } else {
- i.next = obj;
- }
- $noinline$clobberObservables();
- // Predicated-get
- TestClass res = i.next;
- // Predicated-set
- i.next = null;
- return res.i;
- }
-
- /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (before)
- /// CHECK-NOT: Phi
- /// CHECK-NOT: PredicatedInstanceFieldGet
- //
- /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
- /// CHECK: Phi
- /// CHECK: Phi
- /// CHECK-NOT: Phi
- //
- /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet predicated:true
- /// CHECK-NOT: InstanceFieldSet predicated:true
- //
- /// CHECK-START: float Main.$noinline$testPartialEscape3_float(boolean) load_store_elimination (after)
- /// CHECK: PredicatedInstanceFieldGet
- /// CHECK-NOT: PredicatedInstanceFieldGet
- private static float $noinline$testPartialEscape3_float(boolean escape) {
- TestClass4 tc = new TestClass4();
- if ($noinline$getBoolean(escape)) {
- $noinline$Escape4(tc);
- } else {
- tc.floatField -= 1f;
- }
- // Partial escape
- $noinline$clobberObservables();
- // Predicated set
- tc.floatField *= 10;
- // Predicated get
- return tc.floatField;
- }
-
- /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (before)
- /// CHECK-NOT: Phi
- /// CHECK-NOT: PredicatedInstanceFieldGet
- //
- /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
- /// CHECK: Phi
- /// CHECK: Phi
- /// CHECK-NOT: Phi
- //
- /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet predicated:true
- /// CHECK-NOT: InstanceFieldSet predicated:true
- //
- /// CHECK-START: double Main.$noinline$testPartialEscape3_double(boolean) load_store_elimination (after)
- /// CHECK: PredicatedInstanceFieldGet
- /// CHECK-NOT: PredicatedInstanceFieldGet
- private static double $noinline$testPartialEscape3_double(boolean escape) {
- TestClass4 tc = new TestClass4();
- if ($noinline$getBoolean(escape)) {
- $noinline$Escape4(tc);
- } else {
- tc.doubleField -= 1d;
- }
- // Partial escape
- $noinline$clobberObservables();
- // Predicated set
- tc.doubleField *= 10;
- // Predicated get
- return tc.doubleField;
- }
-
- /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (before)
- /// CHECK-NOT: Phi
- /// CHECK-NOT: PredicatedInstanceFieldGet
- //
- /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
- /// CHECK: Phi
- /// CHECK: Phi
- /// CHECK-NOT: Phi
- //
- /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet predicated:true
- /// CHECK-NOT: InstanceFieldSet predicated:true
- //
- /// CHECK-START: short Main.$noinline$testPartialEscape3_short(boolean) load_store_elimination (after)
- /// CHECK: PredicatedInstanceFieldGet
- /// CHECK-NOT: PredicatedInstanceFieldGet
- private static short $noinline$testPartialEscape3_short(boolean escape) {
- TestClass4 tc = new TestClass4();
- if ($noinline$getBoolean(escape)) {
- $noinline$Escape4(tc);
- } else {
- tc.shortField -= 1;
- }
- // Partial escape
- $noinline$clobberObservables();
- // Predicated set
- tc.shortField *= 10;
- // Predicated get
- return tc.shortField;
- }
-
- /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (before)
- /// CHECK-NOT: Phi
- /// CHECK-NOT: PredicatedInstanceFieldGet
- //
- /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
- /// CHECK: Phi
- /// CHECK: Phi
- /// CHECK-NOT: Phi
- //
- /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet predicated:true
- /// CHECK-NOT: InstanceFieldSet predicated:true
- //
- /// CHECK-START: byte Main.$noinline$testPartialEscape3_byte(boolean) load_store_elimination (after)
- /// CHECK: PredicatedInstanceFieldGet
- /// CHECK-NOT: PredicatedInstanceFieldGet
- private static byte $noinline$testPartialEscape3_byte(boolean escape) {
- TestClass4 tc = new TestClass4();
- if ($noinline$getBoolean(escape)) {
- $noinline$Escape4(tc);
- } else {
- tc.byteField -= 1;
- }
- // Partial escape
- $noinline$clobberObservables();
- // Predicated set
- tc.byteField *= 10;
- // Predicated get
- return tc.byteField;
- }
-
- /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (before)
- /// CHECK-NOT: Phi
- /// CHECK-NOT: PredicatedInstanceFieldGet
- //
- /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
- /// CHECK: Phi
- /// CHECK: Phi
- /// CHECK-NOT: Phi
- //
- /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet predicated:true
- /// CHECK-NOT: InstanceFieldSet predicated:true
- //
- /// CHECK-START: int Main.$noinline$testPartialEscape3_int(boolean) load_store_elimination (after)
- /// CHECK: PredicatedInstanceFieldGet
- /// CHECK-NOT: PredicatedInstanceFieldGet
- private static int $noinline$testPartialEscape3_int(boolean escape) {
- TestClass4 tc = new TestClass4();
- if ($noinline$getBoolean(escape)) {
- $noinline$Escape4(tc);
- } else {
- tc.intField -= 1;
- }
- // Partial escape
- $noinline$clobberObservables();
- // Predicated set
- tc.intField *= 10;
- // Predicated get
- return tc.intField;
- }
-
- /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (before)
- /// CHECK-NOT: Phi
- /// CHECK-NOT: PredicatedInstanceFieldGet
- //
- /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
- /// CHECK: Phi
- /// CHECK: Phi
- /// CHECK-NOT: Phi
- //
- /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
- /// CHECK: InstanceFieldSet predicated:true
- /// CHECK-NOT: InstanceFieldSet predicated:true
- //
- /// CHECK-START: long Main.$noinline$testPartialEscape3_long(boolean) load_store_elimination (after)
- /// CHECK: PredicatedInstanceFieldGet
- /// CHECK-NOT: PredicatedInstanceFieldGet
- private static long $noinline$testPartialEscape3_long(boolean escape) {
- TestClass4 tc = new TestClass4();
- if ($noinline$getBoolean(escape)) {
- $noinline$Escape4(tc);
- } else {
- tc.longField -= 1;
- }
- // Partial escape
- $noinline$clobberObservables();
- // Predicated set
- tc.longField *= 10;
- // Predicated get
- return tc.longField;
- }
-
private static void $noinline$clobberObservables() {}
static void assertLongEquals(long result, long expected) {
@@ -4613,19 +4370,5 @@
assertLongEquals(testOverlapLoop(50), 7778742049l);
assertIntEquals($noinline$testPartialEscape1(new TestClass(), true), 1);
assertIntEquals($noinline$testPartialEscape1(new TestClass(), false), 0);
- assertIntEquals($noinline$testPartialEscape2(new TestClass(), true), 1);
- assertIntEquals($noinline$testPartialEscape2(new TestClass(), false), 0);
- assertDoubleEquals($noinline$testPartialEscape3_double(true), -20d);
- assertDoubleEquals($noinline$testPartialEscape3_double(false), -40d);
- assertFloatEquals($noinline$testPartialEscape3_float(true), -20f);
- assertFloatEquals($noinline$testPartialEscape3_float(false), -40f);
- assertIntEquals($noinline$testPartialEscape3_int(true), -20);
- assertIntEquals($noinline$testPartialEscape3_int(false), -40);
- assertIntEquals($noinline$testPartialEscape3_byte(true), -20);
- assertIntEquals($noinline$testPartialEscape3_byte(false), -40);
- assertIntEquals($noinline$testPartialEscape3_short(true), -20);
- assertIntEquals($noinline$testPartialEscape3_short(false), -40);
- assertLongEquals($noinline$testPartialEscape3_long(true), -20);
- assertLongEquals($noinline$testPartialEscape3_long(false), -40);
}
}
diff --git a/test/639-checker-code-sinking/src/Main.java b/test/639-checker-code-sinking/src/Main.java
index 28fa57c..91c3ec4 100644
--- a/test/639-checker-code-sinking/src/Main.java
+++ b/test/639-checker-code-sinking/src/Main.java
@@ -110,8 +110,6 @@
/// CHECK: <<Int42:i\d+>> IntConstant 42
/// CHECK: begin_block
/// CHECK: <<LoadClass:l\d+>> LoadClass class_name:Main
- /// CHECK: If
- /// CHECK: begin_block
/// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
/// CHECK: InstanceFieldSet [<<NewInstance>>,<<Int42>>]
/// CHECK: Throw
@@ -121,14 +119,14 @@
/// CHECK-NOT: NewInstance
/// CHECK: If
/// CHECK: begin_block
+ /// CHECK: <<Error:l\d+>> LoadClass class_name:java.lang.Error
+ /// CHECK-NOT: begin_block
/// CHECK: <<LoadClass:l\d+>> LoadClass class_name:Main
/// CHECK-NOT: begin_block
/// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
/// CHECK-NOT: begin_block
/// CHECK: InstanceFieldSet [<<NewInstance>>,<<Int42>>]
/// CHECK-NOT: begin_block
- /// CHECK: <<Error:l\d+>> LoadClass class_name:java.lang.Error
- /// CHECK-NOT: begin_block
/// CHECK: <<Throw:l\d+>> NewInstance [<<Error>>]
/// CHECK-NOT: begin_block
/// CHECK: Throw [<<Throw>>]
@@ -325,12 +323,7 @@
/// CHECK: <<Int42:i\d+>> IntConstant 42
/// CHECK: <<Int43:i\d+>> IntConstant 43
/// CHECK: <<LoadClass:l\d+>> LoadClass class_name:Main
- /// CHECK: If
- /// CHECK: begin_block
- // Moved to throw block by partial-LSE and DCE.
/// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
- // These were moved by partial LSE and order of sets is not observable and are
- // in an arbitrary order.
/// CHECK-DAG: InstanceFieldSet [<<NewInstance>>,<<Int42>>]
/// CHECK-DAG: InstanceFieldSet [<<NewInstance>>,<<Int43>>]
/// CHECK: Throw
@@ -342,14 +335,14 @@
/// CHECK-NOT: NewInstance
/// CHECK: If
/// CHECK: begin_block
+ /// CHECK: <<Error:l\d+>> LoadClass class_name:java.lang.Error
+ /// CHECK-NOT: begin_block
/// CHECK: <<LoadClass:l\d+>> LoadClass class_name:Main
/// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
/// CHECK-NOT: begin_block
/// CHECK-DAG: InstanceFieldSet [<<NewInstance>>,<<Int42>>]
/// CHECK-DAG: InstanceFieldSet [<<NewInstance>>,<<Int43>>]
/// CHECK-NOT: begin_block
- /// CHECK: <<Error:l\d+>> LoadClass class_name:java.lang.Error
- /// CHECK-NOT: begin_block
/// CHECK: NewInstance [<<Error>>]
/// CHECK: Throw
/// CHECK-NOT: InstanceFieldSet
diff --git a/test/828-partial-lse/expected-stderr.txt b/test/828-partial-lse/expected-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/828-partial-lse/expected-stderr.txt
diff --git a/test/828-partial-lse/expected-stdout.txt b/test/828-partial-lse/expected-stdout.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/828-partial-lse/expected-stdout.txt
diff --git a/test/828-partial-lse/info.txt b/test/828-partial-lse/info.txt
new file mode 100644
index 0000000..8d28cbd
--- /dev/null
+++ b/test/828-partial-lse/info.txt
@@ -0,0 +1,2 @@
+Regression test for the partial LSE pass, see
+https://issuetracker.google.com/197818595.
diff --git a/test/828-partial-lse/src/Main.java b/test/828-partial-lse/src/Main.java
new file mode 100644
index 0000000..2dde0ef
--- /dev/null
+++ b/test/828-partial-lse/src/Main.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+class Main {
+
+ public static void $noinline$testMain(Main m) {
+ expectEquals(0, m.myField);
+ }
+
+ public static void main(String[] args) {
+ $noinline$doTest(true);
+ $noinline$doTest(false);
+ }
+
+ public static void $noinline$doTest(boolean testValue) {
+ Main m = new Main();
+ // LSE will find that this store can be removed, as both branches override the value with a new
+ // one.
+ m.myField = 42;
+ if (testValue) {
+ // LSE will remove this store as well, as it's the value after the store of 42 is removed.
+ m.myField = 0;
+ // This makes sure `m` gets materialized. At this point, the bug is that the partial LSE
+ // optimization thinks the value incoming this block for `m.myField` is 42, however that
+ // store, as well as the store to 0, have been removed.
+ $noinline$testMain(m);
+ } else {
+ m.myField = 3;
+ expectEquals(3, m.myField);
+ }
+ }
+
+ public static void expectEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new Error("Expected " + expected + ", got " + actual);
+ }
+ }
+
+ int myField = 0;
+}