blob: 433a4cd34301bbae1ead3e1d496e871140cb1076 [file] [log] [blame]
/*
* Copyright (C) 2022 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 TestClass {
TestClass() {}
int i;
int j;
volatile int vi;
}
public class Main {
public static void main(String[] args) {
// Volatile accesses.
assertEquals($noinline$testVolatileAccessesMustBeKept(new TestClass()), 3);
// Volatile loads - Different fields shouldn't alias.
assertEquals($noinline$testVolatileLoadDifferentFields(new TestClass(), new TestClass()), 3);
assertEquals(
$noinline$testVolatileLoadDifferentFieldsBlocking(new TestClass(), new TestClass()),
3);
// Volatile loads - Redundant store.
assertEquals($noinline$testVolatileLoadRedundantStore(new TestClass()), 2);
assertEquals($noinline$testVolatileLoadRedundantStoreBlocking(new TestClass()), 2);
assertEquals($noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
// Volatile loads - Set and merge values.
assertEquals($noinline$testVolatileLoadSetAndMergeValues(new TestClass(), true), 1);
assertEquals($noinline$testVolatileLoadSetAndMergeValues(new TestClass(), false), 2);
assertEquals($noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), true), 1);
assertEquals($noinline$testVolatileLoadSetAndMergeValuesBlocking(new TestClass(), false), 2);
// Volatile stores - Different fields shouldn't alias.
assertEquals($noinline$testVolatileStoreDifferentFields(new TestClass(), new TestClass()), 3);
assertEquals(
$noinline$testVolatileStoreDifferentFieldsBlocking(new TestClass(), new TestClass()),
3);
// Volatile stores - Redundant store.
assertEquals($noinline$testVolatileStoreRedundantStore(new TestClass()), 2);
assertEquals($noinline$testVolatileStoreRedundantStoreBlocking(new TestClass()), 2);
assertEquals($noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
// Volatile stores - Set and merge values.
assertEquals($noinline$testVolatileStoreSetAndMergeValues(new TestClass(), true), 1);
assertEquals($noinline$testVolatileStoreSetAndMergeValues(new TestClass(), false), 2);
assertEquals($noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), true), 1);
assertEquals($noinline$testVolatileStoreSetAndMergeValuesNotBlocking(new TestClass(), false), 2);
// Monitor Operations - Different fields shouldn't alias.
assertEquals(
$noinline$testMonitorOperationDifferentFields(new TestClass(), new TestClass()), 3);
assertEquals($noinline$testMonitorOperationDifferentFieldsBlocking(
new TestClass(), new TestClass()),
3);
// Monitor Operations - Redundant store.
assertEquals($noinline$testMonitorOperationRedundantStore(new TestClass()), 2);
assertEquals($noinline$testMonitorOperationRedundantStoreBlocking(new TestClass()), 2);
assertEquals(
$noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(new TestClass()), 2);
assertEquals($noinline$testMonitorOperationRedundantStoreBlockingExit(new TestClass()), 2);
// Monitor Operations - Set and merge values.
assertEquals($noinline$testMonitorOperationSetAndMergeValues(new TestClass(), true), 1);
assertEquals($noinline$testMonitorOperationSetAndMergeValues(new TestClass(), false), 2);
assertEquals(
$noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), true), 1);
assertEquals(
$noinline$testMonitorOperationSetAndMergeValuesBlocking(new TestClass(), false), 2);
}
public static void assertEquals(int expected, int result) {
if (expected != result) {
throw new Error("Expected: " + expected + ", found: " + result);
}
}
/// CHECK-START: int Main.$noinline$testVolatileAccessesMustBeKept(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileAccessesMustBeKept(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
static int $noinline$testVolatileAccessesMustBeKept(TestClass obj1) {
int result;
obj1.vi = 3;
// Redundant load that has to be kept.
result = obj1.vi;
result = obj1.vi;
// Redundant store that has to be kept.
obj1.vi = 3;
result = obj1.vi;
return result;
}
/// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet field_name:TestClass.i
/// CHECK: InstanceFieldGet field_name:TestClass.j
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFields(TestClass, TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFields(TestClass, TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet field_name:TestClass.i
/// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFields(TestClass, TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet field_name:TestClass.j
// Unrelated volatile loads shouldn't block LSE.
static int $noinline$testVolatileLoadDifferentFields(TestClass obj1, TestClass obj2) {
int unused = obj1.vi;
obj1.i = 1;
obj2.j = 2;
int result = obj1.i + obj2.j;
unused = obj1.vi;
return result;
}
/// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsBlocking(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileLoadDifferentFieldsBlocking(TestClass, TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
// A volatile load blocks load elimination.
static int $noinline$testVolatileLoadDifferentFieldsBlocking(TestClass obj1, TestClass obj2) {
obj1.i = 1;
obj2.j = 2;
int unused = obj1.vi;
return obj1.i + obj2.j;
}
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStore(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK: InstanceFieldGet field_name:TestClass.j
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStore(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStore(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK-NOT: InstanceFieldSet field_name:TestClass.j
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStore(TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet field_name:TestClass.j
static int $noinline$testVolatileLoadRedundantStore(TestClass obj) {
int unused = obj.vi;
obj.j = 1;
obj.j = 2;
return obj.j;
}
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreBlocking(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreBlocking(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreBlocking(TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet field_name:TestClass.j
static int $noinline$testVolatileLoadRedundantStoreBlocking(TestClass obj) {
// This store must be kept due to the volatile load.
obj.j = 1;
int unused = obj.vi;
obj.j = 2;
return obj.j;
}
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK-NOT: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
static int $noinline$testVolatileLoadRedundantStoreBlockingOnlyLoad(TestClass obj) {
// This store can be safely removed.
obj.j = 1;
obj.j = 2;
int unused = obj.vi;
// This load remains due to the volatile load in the middle.
return obj.j;
}
/// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValues(TestClass, boolean) load_store_elimination (before)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldGet field_name:TestClass.i
/// CHECK-DAG: InstanceFieldGet field_name:TestClass.vi
/// CHECK-DAG: InstanceFieldGet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldGet field_name:TestClass.vi
/// CHECK-DAG: InstanceFieldGet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK: Phi
/// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet field_name:TestClass.i
static int $noinline$testVolatileLoadSetAndMergeValues(TestClass obj, boolean b) {
if (b) {
int unused = obj.vi;
obj.i = 1;
} else {
int unused = obj.vi;
obj.i = 2;
}
return obj.i;
}
/// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (before)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldGet field_name:TestClass.i
/// CHECK-DAG: InstanceFieldGet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (after)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldGet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (after)
/// CHECK-NOT: Phi
/// CHECK-START: int Main.$noinline$testVolatileLoadSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (after)
/// CHECK: InstanceFieldGet
static int $noinline$testVolatileLoadSetAndMergeValuesBlocking(TestClass obj, boolean b) {
if (b) {
obj.i = 1;
} else {
obj.i = 2;
}
int unused = obj.vi;
return obj.i;
}
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet field_name:TestClass.i
/// CHECK: InstanceFieldGet field_name:TestClass.j
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFields(TestClass, TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFields(TestClass, TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet field_name:TestClass.i
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFields(TestClass, TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet field_name:TestClass.j
// Unrelated volatile stores shouldn't block LSE.
static int $noinline$testVolatileStoreDifferentFields(TestClass obj1, TestClass obj2) {
obj1.vi = 123;
obj1.i = 1;
obj2.j = 2;
int result = obj1.i + obj2.j;
obj1.vi = 123;
return result;
}
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsBlocking(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsBlocking(TestClass, TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testVolatileStoreDifferentFieldsBlocking(TestClass, TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
// A volatile store doesn't block load elimination, as it doesn't clobber existing values.
static int $noinline$testVolatileStoreDifferentFieldsBlocking(TestClass obj1, TestClass obj2) {
obj1.i = 1;
obj2.j = 2;
obj1.vi = 123;
return obj1.i + obj2.j;
}
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStore(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStore(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK-NOT: InstanceFieldSet field_name:TestClass.j
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStore(TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testVolatileStoreRedundantStore(TestClass obj) {
obj.vi = 123;
obj.j = 1;
obj.j = 2;
return obj.j;
}
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreBlocking(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreBlocking(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreBlocking(TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testVolatileStoreRedundantStoreBlocking(TestClass obj) {
// This store must be kept due to the volatile store.
obj.j = 1;
obj.vi = 123;
obj.j = 2;
return obj.j;
}
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet field_name:TestClass.j
/// CHECK-NOT: InstanceFieldSet field_name:TestClass.j
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet field_name:TestClass.vi
/// CHECK-START: int Main.$noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testVolatileStoreRedundantStoreBlockingOnlyLoad(TestClass obj) {
// This store can be safely removed.
obj.j = 1;
obj.j = 2;
obj.vi = 123;
// This load can also be safely eliminated as the volatile store doesn't clobber values.
return obj.j;
}
/// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValues(TestClass, boolean) load_store_elimination (before)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK: Phi
/// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testVolatileStoreSetAndMergeValues(TestClass obj, boolean b) {
if (b) {
obj.vi = 123;
obj.i = 1;
} else {
obj.vi = 123;
obj.i = 2;
}
return obj.i;
}
/// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesNotBlocking(TestClass, boolean) load_store_elimination (before)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValuesNotBlocking(TestClass, boolean) load_store_elimination (after)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK: Phi
/// CHECK-START: int Main.$noinline$testVolatileStoreSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testVolatileStoreSetAndMergeValuesNotBlocking(TestClass obj, boolean b) {
if (b) {
obj.i = 1;
} else {
obj.i = 2;
}
// This volatile store doesn't block the load elimination
obj.vi = 123;
return obj.i;
}
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFields(TestClass, TestClass) load_store_elimination (before)
/// CHECK: MonitorOperation kind:enter
/// CHECK: MonitorOperation kind:exit
/// CHECK: MonitorOperation kind:enter
/// CHECK: MonitorOperation kind:exit
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFields(TestClass, TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFields(TestClass, TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
// Unrelated monitor operations shouldn't block LSE.
static int $noinline$testMonitorOperationDifferentFields(TestClass obj1, TestClass obj2) {
Main m = new Main();
synchronized (m) {}
obj1.i = 1;
obj2.j = 2;
int result = obj1.i + obj2.j;
synchronized (m) {}
return result;
}
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsBlocking(TestClass, TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsBlocking(TestClass, TestClass) load_store_elimination (before)
/// CHECK: MonitorOperation kind:enter
/// CHECK: MonitorOperation kind:exit
/// CHECK-START: int Main.$noinline$testMonitorOperationDifferentFieldsBlocking(TestClass, TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK: InstanceFieldGet
// A synchronized operation blocks loads.
static int $noinline$testMonitorOperationDifferentFieldsBlocking(TestClass obj1, TestClass obj2) {
Main m = new Main();
obj1.i = 1;
obj2.j = 2;
synchronized (m) {
return obj1.i + obj2.j;
}
}
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStore(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStore(TestClass) load_store_elimination (before)
/// CHECK: MonitorOperation kind:enter
/// CHECK: MonitorOperation kind:exit
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStore(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK-NOT: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStore(TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStore(TestClass obj) {
Main m = new Main();
synchronized (m) {
obj.j = 1;
obj.j = 2;
}
return obj.j;
}
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlocking(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlocking(TestClass) load_store_elimination (before)
/// CHECK: MonitorOperation kind:enter
/// CHECK: MonitorOperation kind:exit
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlocking(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlocking(TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlocking(TestClass obj) {
Main m = new Main();
// This store must be kept due to the monitor operation.
obj.j = 1;
synchronized (m) {}
obj.j = 2;
return obj.j;
}
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (before)
/// CHECK: MonitorOperation kind:enter
/// CHECK: MonitorOperation kind:exit
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK-NOT: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlockingOnlyLoad(TestClass obj) {
Main m = new Main();
// This store can be safely removed.
obj.j = 1;
obj.j = 2;
synchronized (m) {}
// This load remains due to the monitor operation.
return obj.j;
}
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlockingExit(TestClass) load_store_elimination (before)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlockingExit(TestClass) load_store_elimination (before)
/// CHECK: MonitorOperation kind:enter
/// CHECK: MonitorOperation kind:exit
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlockingExit(TestClass) load_store_elimination (after)
/// CHECK: InstanceFieldSet
/// CHECK: InstanceFieldSet
/// CHECK-NOT: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testMonitorOperationRedundantStoreBlockingExit(TestClass) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationRedundantStoreBlockingExit(TestClass obj) {
Main m = new Main();
synchronized (m) {
// This store can be removed.
obj.j = 0;
// This store must be kept due to the monitor exit operation.
obj.j = 1;
}
obj.j = 2;
return obj.j;
}
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValues(TestClass, boolean) load_store_elimination (before)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValues(TestClass, boolean) load_store_elimination (before)
/// CHECK-DAG: MonitorOperation kind:enter
/// CHECK-DAG: MonitorOperation kind:exit
/// CHECK-DAG: MonitorOperation kind:enter
/// CHECK-DAG: MonitorOperation kind:exit
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK: Phi
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValues(TestClass, boolean) load_store_elimination (after)
/// CHECK-NOT: InstanceFieldGet
static int $noinline$testMonitorOperationSetAndMergeValues(TestClass obj, boolean b) {
Main m = new Main();
if (b) {
synchronized (m) {}
obj.i = 1;
} else {
synchronized (m) {}
obj.i = 2;
}
return obj.i;
}
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (before)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldGet
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (after)
/// CHECK-DAG: InstanceFieldSet
/// CHECK-DAG: InstanceFieldSet
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (before)
/// CHECK-DAG: MonitorOperation kind:enter
/// CHECK-DAG: MonitorOperation kind:exit
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (after)
/// CHECK-NOT: Phi
/// CHECK-START: int Main.$noinline$testMonitorOperationSetAndMergeValuesBlocking(TestClass, boolean) load_store_elimination (after)
/// CHECK: InstanceFieldGet
static int $noinline$testMonitorOperationSetAndMergeValuesBlocking(TestClass obj, boolean b) {
Main m = new Main();
if (b) {
obj.i = 1;
} else {
obj.i = 2;
}
synchronized (m) {}
return obj.i;
}
}