Eliminate dead LoadClass when pruning ClinitCheck.
Prebuilt sizes for aosp_taimen-userdebug:
- before:
arm/boot*.oat: 19192012
arm64/boot*.oat: 22603096
- after:
arm/boot*.oat: 19150692 (-40KiB, -0.22%)
arm64/boot*.oat: 22565976 (-36KiB, -0.16%)
Test: Add checker statements to 478-checker-clinit-check-pruning
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 35772576
Change-Id: I2485e832e77b68357f3bc0268afa8bd6a87083d5
diff --git a/compiler/optimizing/prepare_for_register_allocation.cc b/compiler/optimizing/prepare_for_register_allocation.cc
index fbdbf9d..8c4615d 100644
--- a/compiler/optimizing/prepare_for_register_allocation.cc
+++ b/compiler/optimizing/prepare_for_register_allocation.cc
@@ -160,8 +160,8 @@
if (implicit_clinit != nullptr) {
// Remove the check from the graph. It has been merged into the invoke or new-instance.
check->GetBlock()->RemoveInstruction(check);
- // Check if we can merge the load class as well.
- if (can_merge_with_load_class && !load_class->HasUses()) {
+ // Check if we can merge the load class as well, or whether the LoadClass is now dead.
+ if ((can_merge_with_load_class || !load_class->CanThrow()) && !load_class->HasUses()) {
load_class->GetBlock()->RemoveInstruction(load_class);
}
} else if (can_merge_with_load_class &&
diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java
index b1bc51e..5b9ebc8 100644
--- a/test/478-checker-clinit-check-pruning/src/Main.java
+++ b/test/478-checker-clinit-check-pruning/src/Main.java
@@ -225,6 +225,19 @@
/// CHECK-DAG: ClinitCheck
/// CHECK-DAG: InvokeStaticOrDirect
+ // The following checks ensure the clinit check and load class
+ // instructions added by the builder are pruned by the
+ // PrepareForRegisterAllocation. As the control flow graph is not
+ // dumped after (nor before) this step, we check the CFG as it is
+ // before the next pass (liveness analysis) instead.
+
+ /// CHECK-START: void Main$ClassWithClinit4Instance.invokeStaticNotInlined() liveness (before)
+ /// CHECK: InvokeStaticOrDirect clinit_check:implicit
+
+ /// CHECK-START: void Main$ClassWithClinit4Instance.invokeStaticNotInlined() liveness (before)
+ /// CHECK-NOT: LoadClass
+ /// CHECK-NOT: ClinitCheck
+
static class ClassWithClinit4Instance {
void invokeStaticNotInlined() {
// ClinitCheck required.