Revert "Initial support for member value propagation for instance fields" This reverts commit ae1775c7857a04331a8f483bb26bb971ae534ad2. Reason for revert: Possibly causes a runtime regression. Change-Id: I165a513ec8885989a346c7531e4c73f04c04fea3
diff --git a/src/main/java/com/android/tools/r8/graph/DexClass.java b/src/main/java/com/android/tools/r8/graph/DexClass.java index 0acef70..988bf75 100644 --- a/src/main/java/com/android/tools/r8/graph/DexClass.java +++ b/src/main/java/com/android/tools/r8/graph/DexClass.java
@@ -560,11 +560,6 @@ return lookupTarget(directMethods, method); } - /** Find direct method in this class matching {@param predicate}. */ - public DexEncodedMethod lookupDirectMethod(Predicate<DexEncodedMethod> predicate) { - return PredicateUtils.findFirst(directMethods, predicate); - } - /** Find virtual method in this class matching {@param method}. */ public DexEncodedMethod lookupVirtualMethod(DexMethod method) { return lookupTarget(virtualMethods, method);
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java index 35f6661..2c86c7b 100644 --- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java +++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/FieldValueAnalysis.java
@@ -25,12 +25,12 @@ import com.android.tools.r8.ir.code.BasicBlock; import com.android.tools.r8.ir.code.DominatorTree; import com.android.tools.r8.ir.code.DominatorTree.Assumption; -import com.android.tools.r8.ir.code.FieldInstruction; import com.android.tools.r8.ir.code.IRCode; import com.android.tools.r8.ir.code.Instruction; import com.android.tools.r8.ir.code.InstructionIterator; import com.android.tools.r8.ir.code.InvokeDirect; import com.android.tools.r8.ir.code.NewInstance; +import com.android.tools.r8.ir.code.StaticPut; import com.android.tools.r8.ir.code.Value; import com.android.tools.r8.ir.optimize.info.OptimizationFeedback; import com.android.tools.r8.shaking.AppInfoWithLiveness; @@ -56,11 +56,9 @@ AppView<AppInfoWithLiveness> appView, IRCode code, OptimizationFeedback feedback, - DexProgramClass clazz, DexEncodedMethod method) { - assert clazz.type == method.method.holder; this.appView = appView; - this.clazz = clazz; + this.clazz = appView.definitionFor(method.method.holder).asProgramClass(); this.code = code; this.feedback = feedback; this.method = method; @@ -69,26 +67,11 @@ public static void run( AppView<?> appView, IRCode code, OptimizationFeedback feedback, DexEncodedMethod method) { - if (!appView.enableWholeProgramOptimizations()) { - return; + if (appView.enableWholeProgramOptimizations() && method.isClassInitializer()) { + assert appView.appInfo().hasLiveness(); + new FieldValueAnalysis(appView.withLiveness(), code, feedback, method) + .computeFieldOptimizationInfo(); } - assert appView.appInfo().hasLiveness(); - if (!method.isInitializer()) { - return; - } - DexProgramClass clazz = appView.definitionFor(method.method.holder).asProgramClass(); - if (method.isInstanceInitializer()) { - DexEncodedMethod otherInstanceInitializer = - clazz.lookupDirectMethod(other -> other.isInstanceInitializer() && other != method); - if (otherInstanceInitializer != null) { - // Conservatively bail out. - // TODO(b/125282093): Handle multiple instance initializers on the same class. - return; - } - } - - new FieldValueAnalysis(appView.withLiveness(), code, feedback, clazz, method) - .computeFieldOptimizationInfo(); } private Map<BasicBlock, AbstractFieldSet> getOrCreateFieldsMaybeReadBeforeBlockInclusive() { @@ -103,50 +86,54 @@ AppInfoWithLiveness appInfo = appView.appInfo(); DominatorTree dominatorTree = null; - DexType context = method.method.holder; + if (method.isClassInitializer()) { + DexType context = method.method.holder; - // Find all the static-put instructions that assign a field in the enclosing class which is - // guaranteed to be assigned only in the current initializer. - boolean isStraightLineCode = true; - Map<DexEncodedField, LinkedList<FieldInstruction>> putsPerField = new IdentityHashMap<>(); - for (Instruction instruction : code.instructions()) { - if (instruction.isFieldPut()) { - FieldInstruction fieldPut = instruction.asFieldInstruction(); - DexField field = fieldPut.getField(); - DexEncodedField encodedField = appInfo.resolveField(field); - if (encodedField != null - && encodedField.field.holder == context - && appInfo.isFieldOnlyWrittenInMethod(encodedField, method)) { - putsPerField.computeIfAbsent(encodedField, ignore -> new LinkedList<>()).add(fieldPut); + // Find all the static-put instructions that assign a field in the enclosing class which is + // guaranteed to be assigned only in the current initializer. + boolean isStraightLineCode = true; + Map<DexEncodedField, LinkedList<StaticPut>> staticPutsPerField = new IdentityHashMap<>(); + for (Instruction instruction : code.instructions()) { + if (instruction.isStaticPut()) { + StaticPut staticPut = instruction.asStaticPut(); + DexField field = staticPut.getField(); + DexEncodedField encodedField = appInfo.resolveField(field); + if (encodedField != null + && encodedField.field.holder == context + && appInfo.isStaticFieldWrittenOnlyInEnclosingStaticInitializer(encodedField)) { + staticPutsPerField + .computeIfAbsent(encodedField, ignore -> new LinkedList<>()) + .add(staticPut); + } + } + if (instruction.isJumpInstruction()) { + if (!instruction.isGoto() && !instruction.isReturn()) { + isStraightLineCode = false; + } } } - if (instruction.isJumpInstruction()) { - if (!instruction.isGoto() && !instruction.isReturn()) { - isStraightLineCode = false; - } - } - } - List<BasicBlock> normalExitBlocks = code.computeNormalExitBlocks(); - for (Entry<DexEncodedField, LinkedList<FieldInstruction>> entry : putsPerField.entrySet()) { - DexEncodedField encodedField = entry.getKey(); - LinkedList<FieldInstruction> fieldPuts = entry.getValue(); - if (fieldPuts.size() > 1) { - continue; - } - FieldInstruction fieldPut = fieldPuts.getFirst(); - if (!isStraightLineCode) { - if (dominatorTree == null) { - dominatorTree = new DominatorTree(code, Assumption.NO_UNREACHABLE_BLOCKS); - } - if (!dominatorTree.dominatesAllOf(fieldPut.getBlock(), normalExitBlocks)) { + List<BasicBlock> normalExitBlocks = code.computeNormalExitBlocks(); + for (Entry<DexEncodedField, LinkedList<StaticPut>> entry : staticPutsPerField.entrySet()) { + DexEncodedField encodedField = entry.getKey(); + LinkedList<StaticPut> staticPuts = entry.getValue(); + if (staticPuts.size() > 1) { continue; } + StaticPut staticPut = staticPuts.getFirst(); + if (!isStraightLineCode) { + if (dominatorTree == null) { + dominatorTree = new DominatorTree(code, Assumption.NO_UNREACHABLE_BLOCKS); + } + if (!dominatorTree.dominatesAllOf(staticPut.getBlock(), normalExitBlocks)) { + continue; + } + } + if (fieldMaybeReadBeforeInstruction(encodedField, staticPut)) { + continue; + } + updateFieldOptimizationInfo(encodedField, staticPut.value()); } - if (fieldMaybeReadBeforeInstruction(encodedField, fieldPut)) { - continue; - } - updateFieldOptimizationInfo(encodedField, fieldPut.value()); } }
diff --git a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java index 319cbaf..f5b0de8 100644 --- a/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java +++ b/src/main/java/com/android/tools/r8/shaking/AppInfoWithLiveness.java
@@ -758,24 +758,20 @@ return false; } - public boolean isFieldOnlyWrittenInMethod(DexEncodedField field, DexEncodedMethod method) { - assert checkIfObsolete(); - assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written"; - if (!isPinned(field.field)) { - FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(field.field); - return fieldAccessInfo != null - && fieldAccessInfo.isWritten() - && !fieldAccessInfo.isWrittenOutside(method); - } - return false; - } - public boolean isStaticFieldWrittenOnlyInEnclosingStaticInitializer(DexEncodedField field) { assert checkIfObsolete(); assert isFieldWritten(field) : "Expected field `" + field.toSourceString() + "` to be written"; - DexEncodedMethod staticInitializer = - definitionFor(field.field.holder).asProgramClass().getClassInitializer(); - return staticInitializer != null && isFieldOnlyWrittenInMethod(field, staticInitializer); + if (!isPinned(field.field)) { + DexEncodedMethod staticInitializer = + definitionFor(field.field.holder).asProgramClass().getClassInitializer(); + if (staticInitializer != null) { + FieldAccessInfo fieldAccessInfo = fieldAccessInfoCollection.get(field.field); + return fieldAccessInfo != null + && fieldAccessInfo.isWritten() + && !fieldAccessInfo.isWrittenOutside(staticInitializer); + } + } + return false; } public boolean mayPropagateValueFor(DexReference reference) {
diff --git a/src/test/examples/shaking18/Options.java b/src/test/examples/shaking18/Options.java index 7012340..edb9d774 100644 --- a/src/test/examples/shaking18/Options.java +++ b/src/test/examples/shaking18/Options.java
@@ -4,7 +4,9 @@ package shaking18; public class Options { - public boolean alwaysFalse = false; + // TODO(b/138913138): member value propagation can behave same with and without initialization. + // public boolean alwaysFalse = false; + public boolean alwaysFalse; public boolean dummy = false; public Options() {}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldValuePropagationTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldValuePropagationTest.java deleted file mode 100644 index a3d644f..0000000 --- a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldValuePropagationTest.java +++ /dev/null
@@ -1,136 +0,0 @@ -// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -package com.android.tools.r8.ir.optimize.membervaluepropagation; - -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import com.android.tools.r8.NeverClassInline; -import com.android.tools.r8.NeverInline; -import com.android.tools.r8.TestBase; -import com.android.tools.r8.TestParameters; -import com.android.tools.r8.TestParametersCollection; -import com.android.tools.r8.utils.StringUtils; -import com.android.tools.r8.utils.codeinspector.ClassSubject; -import com.android.tools.r8.utils.codeinspector.CodeInspector; -import com.android.tools.r8.utils.codeinspector.InstructionSubject; -import com.android.tools.r8.utils.codeinspector.MethodSubject; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -@RunWith(Parameterized.class) -public class InstanceFieldValuePropagationTest extends TestBase { - - private final TestParameters parameters; - - @Parameterized.Parameters(name = "{0}") - public static TestParametersCollection data() { - return getTestParameters().withAllRuntimesAndApiLevels().build(); - } - - public InstanceFieldValuePropagationTest(TestParameters parameters) { - this.parameters = parameters; - } - - @Test - public void test() throws Exception { - testForR8(parameters.getBackend()) - .addInnerClasses(InstanceFieldValuePropagationTest.class) - .addKeepMainRule(TestClass.class) - .enableClassInliningAnnotations() - .enableInliningAnnotations() - .setMinApi(parameters.getApiLevel()) - .compile() - .inspect(this::inspect) - .run(parameters.getRuntime(), TestClass.class) - .assertSuccessWithOutput( - StringUtils.times(StringUtils.lines("A", "42", "Hello world!"), 2)); - } - - private void inspect(CodeInspector inspector) { - ClassSubject testClassSubject = inspector.clazz(TestClass.class); - assertThat(testClassSubject, isPresent()); - - // Verify that all instance-get instructions in testDefinitelyNotNull() has been removed by - // member value propagation. - MethodSubject testDefinitelyNotNullMethodSubject = - testClassSubject.uniqueMethodWithName("testDefinitelyNotNull"); - assertThat(testDefinitelyNotNullMethodSubject, isPresent()); - assertTrue( - testDefinitelyNotNullMethodSubject - .streamInstructions() - .noneMatch(InstructionSubject::isInstanceGet)); - // TODO(b/125282093): Should be able to remove the new-instance instruction since the instance - // ends up being unused. - assertTrue( - testDefinitelyNotNullMethodSubject - .streamInstructions() - .anyMatch(InstructionSubject::isNewInstance)); - - // Verify that all instance-get instructions in testMaybeNull() has been removed by member value - // propagation. - MethodSubject testMaybeNullMethodSubject = - testClassSubject.uniqueMethodWithName("testMaybeNull"); - assertThat(testMaybeNullMethodSubject, isPresent()); - // TODO(b/125282093): Should synthesize a null-check and still propagate the field values even - // when the receiver is nullable. - assertTrue( - testMaybeNullMethodSubject - .streamInstructions() - .anyMatch(InstructionSubject::isInstanceGet)); - // TODO(b/125282093): Should be able to remove the new-instance instruction since the instance - // ends up being unused. - assertTrue( - testMaybeNullMethodSubject - .streamInstructions() - .anyMatch(InstructionSubject::isNewInstance)); - - ClassSubject aClassSubject = inspector.clazz(A.class); - assertThat(aClassSubject, isPresent()); - // TODO(b/125282093): Need to remove the instance-put instructions in A.<init>(). This can not - // be done safely by the time we process A.<init>(), so some kind of post-processing is needed. - assertEquals(3, aClassSubject.allInstanceFields().size()); - } - - static class TestClass { - - public static void main(String[] args) { - testDefinitelyNotNull(); - testMaybeNull(); - } - - @NeverInline - static void testDefinitelyNotNull() { - A a = new A(); - System.out.println(a.e); - System.out.println(a.i); - System.out.println(a.s); - } - - @NeverInline - static void testMaybeNull() { - A a = System.currentTimeMillis() >= 0 ? new A() : null; - System.out.println(a.e); - System.out.println(a.i); - System.out.println(a.s); - } - } - - @NeverClassInline - static class A { - - MyEnum e = MyEnum.A; - int i = 42; - String s = "Hello world!"; - } - - enum MyEnum { - A, - B - } -}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldValuePropagationWithMultipleInstanceInitializersTest.java b/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldValuePropagationWithMultipleInstanceInitializersTest.java deleted file mode 100644 index d2b739e..0000000 --- a/src/test/java/com/android/tools/r8/ir/optimize/membervaluepropagation/InstanceFieldValuePropagationWithMultipleInstanceInitializersTest.java +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -package com.android.tools.r8.ir.optimize.membervaluepropagation; - -import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assert.assertTrue; - -import com.android.tools.r8.NeverClassInline; -import com.android.tools.r8.TestBase; -import com.android.tools.r8.TestParameters; -import com.android.tools.r8.TestParametersCollection; -import com.android.tools.r8.utils.codeinspector.ClassSubject; -import com.android.tools.r8.utils.codeinspector.CodeInspector; -import com.android.tools.r8.utils.codeinspector.InstructionSubject; -import com.android.tools.r8.utils.codeinspector.MethodSubject; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; - -@RunWith(Parameterized.class) -public class InstanceFieldValuePropagationWithMultipleInstanceInitializersTest extends TestBase { - - private final TestParameters parameters; - - @Parameterized.Parameters(name = "{0}") - public static TestParametersCollection data() { - return getTestParameters().withAllRuntimesAndApiLevels().build(); - } - - public InstanceFieldValuePropagationWithMultipleInstanceInitializersTest( - TestParameters parameters) { - this.parameters = parameters; - } - - @Test - public void test() throws Exception { - testForR8(parameters.getBackend()) - .addInnerClasses(InstanceFieldValuePropagationWithMultipleInstanceInitializersTest.class) - .addKeepMainRule(TestClass.class) - .setMinApi(parameters.getApiLevel()) - .compile() - .inspect(this::inspect) - .run(parameters.getRuntime(), TestClass.class) - .assertSuccessWithOutputLines("Hello world!"); - } - - private void inspect(CodeInspector inspector) { - ClassSubject testClassSubject = inspector.clazz(TestClass.class); - assertThat(testClassSubject, isPresent()); - - // Verify that the instance-get instruction in main() is still present in main(), since the - // value of `a.greeting` depends on the constructor being used. - MethodSubject mainMethodSubject = testClassSubject.mainMethod(); - assertThat(mainMethodSubject, isPresent()); - assertTrue(mainMethodSubject.streamInstructions().anyMatch(InstructionSubject::isInstanceGet)); - - // Verify that the `greeting` field is still present. - ClassSubject aClassSubject = inspector.clazz(A.class); - assertThat(aClassSubject, isPresent()); - assertThat(aClassSubject.uniqueFieldWithName("greeting"), isPresent()); - } - - static class TestClass { - - public static void main(String[] args) { - A a = System.currentTimeMillis() >= 0 ? new A() : new A(new Object()); - System.out.println(a.greeting); - } - } - - @NeverClassInline - static class A { - - String greeting; - - A() { - this.greeting = "Hello world!"; - } - - A(Object unused) { - this.greeting = ":-("; - } - } -}
diff --git a/src/test/java/com/android/tools/r8/rewrite/enums/EnumOptimizationTest.java b/src/test/java/com/android/tools/r8/rewrite/enums/EnumOptimizationTest.java index 9da1f4a..5d110e4 100644 --- a/src/test/java/com/android/tools/r8/rewrite/enums/EnumOptimizationTest.java +++ b/src/test/java/com/android/tools/r8/rewrite/enums/EnumOptimizationTest.java
@@ -82,7 +82,6 @@ assertOrdinalReplacedWithConst(clazz.uniqueMethodWithName("inlined"), 1); assertOrdinalReplacedWithConst(clazz.uniqueMethodWithName("inSwitch"), 11); assertOrdinalReplacedWithConst(clazz.uniqueMethodWithName("differentTypeStaticField"), 1); - assertOrdinalReplacedWithConst(clazz.uniqueMethodWithName("nonStaticGet"), 1); } else { assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("simple")); assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("local")); @@ -90,12 +89,12 @@ assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("inlined")); assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("inSwitch")); assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("differentTypeStaticField")); - assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("nonStaticGet")); } assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("libraryType")); assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("nonValueStaticField")); assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("phi")); + assertOrdinalWasNotReplaced(clazz.uniqueMethodWithName("nonStaticGet")); } @Test @@ -126,14 +125,12 @@ assertNameReplacedWithConst(clazz.uniqueMethodWithName("multipleUsages"), expectedConst); assertNameReplacedWithConst(clazz.uniqueMethodWithName("inlined"), "TWO"); assertNameReplacedWithConst(clazz.uniqueMethodWithName("differentTypeStaticField"), "DOWN"); - assertNameReplacedWithConst(clazz.uniqueMethodWithName("nonStaticGet"), "TWO"); } else { assertNameWasNotReplaced(clazz.uniqueMethodWithName("simple")); assertNameWasNotReplaced(clazz.uniqueMethodWithName("local")); assertNameWasNotReplaced(clazz.uniqueMethodWithName("multipleUsages")); assertNameWasNotReplaced(clazz.uniqueMethodWithName("inlined")); assertNameWasNotReplaced(clazz.uniqueMethodWithName("differentTypeStaticField")); - assertNameWasNotReplaced(clazz.uniqueMethodWithName("nonStaticGet")); } // TODO(jakew) this should be allowed! @@ -141,6 +138,7 @@ assertNameWasNotReplaced(clazz.uniqueMethodWithName("nonValueStaticField")); assertNameWasNotReplaced(clazz.uniqueMethodWithName("phi")); + assertNameWasNotReplaced(clazz.uniqueMethodWithName("nonStaticGet")); } @Test @@ -180,7 +178,6 @@ assertToStringReplacedWithConst(clazz.uniqueMethodWithName("nonValueStaticField"), "TWO"); assertToStringReplacedWithConst( clazz.uniqueMethodWithName("differentTypeStaticField"), "DOWN"); - assertToStringReplacedWithConst(clazz.uniqueMethodWithName("nonStaticGet"), "TWO"); } else { assertToStringWasNotReplaced(clazz.uniqueMethodWithName("noToString")); assertToStringWasNotReplaced(clazz.uniqueMethodWithName("local")); @@ -188,11 +185,11 @@ assertToStringWasNotReplaced(clazz.uniqueMethodWithName("inlined")); assertToStringWasNotReplaced(clazz.uniqueMethodWithName("nonValueStaticField")); assertToStringWasNotReplaced(clazz.uniqueMethodWithName("differentTypeStaticField")); - assertToStringWasNotReplaced(clazz.uniqueMethodWithName("nonStaticGet")); } assertToStringWasNotReplaced(clazz.uniqueMethodWithName("libraryType")); assertToStringWasNotReplaced(clazz.uniqueMethodWithName("phi")); + assertToStringWasNotReplaced(clazz.uniqueMethodWithName("nonStaticGet")); } private static void assertOrdinalReplacedWithConst(MethodSubject method, int expectedConst) {
diff --git a/src/test/java/com/android/tools/r8/shaking/EffectivelyFinalInstanceFieldsTest.java b/src/test/java/com/android/tools/r8/shaking/EffectivelyFinalInstanceFieldsTest.java index 92d16ae..ea96ead 100644 --- a/src/test/java/com/android/tools/r8/shaking/EffectivelyFinalInstanceFieldsTest.java +++ b/src/test/java/com/android/tools/r8/shaking/EffectivelyFinalInstanceFieldsTest.java
@@ -56,50 +56,43 @@ .enableMergeAnnotations() .setMinApi(parameters.getRuntime()) .compile() - .inspect( - codeInspector -> { - ClassSubject main = codeInspector.clazz(MAIN); - assertThat(main, isPresent()); + .inspect(codeInspector -> { + ClassSubject main = codeInspector.clazz(MAIN); + assertThat(main, isPresent()); - MethodSubject mainMethod = main.mainMethod(); - assertThat(mainMethod, isPresent()); + MethodSubject mainMethod = main.mainMethod(); + assertThat(mainMethod, isPresent()); - assertTrue( - mainMethod - .streamInstructions() - .noneMatch(i -> i.isConstString("Dead code: 1", JumboStringMode.ALLOW))); - assertTrue( - mainMethod - .streamInstructions() - .noneMatch(i -> i.isConstString("Dead code: 2", JumboStringMode.ALLOW))); - // TODO(b/138913138): not trivial; assigned only once in <init> - assertFalse( - mainMethod - .streamInstructions() - .noneMatch(i -> i.isConstString("Dead code: 3", JumboStringMode.ALLOW))); - assertTrue( - mainMethod - .streamInstructions() - .noneMatch(i -> i.isConstString("Dead code: 4", JumboStringMode.ALLOW))); - assertTrue( - mainMethod - .streamInstructions() - .noneMatch(i -> i.isConstString("Dead code: 5", JumboStringMode.ALLOW))); - // TODO(b/138913138): not trivial; assigned multiple times, but within a certain - // range. - assertFalse( - mainMethod - .streamInstructions() - .noneMatch(i -> i.isConstString("Dead code: 6", JumboStringMode.ALLOW))); - assertTrue( - mainMethod - .streamInstructions() - .noneMatch(i -> i.isConstString("Dead code: 7", JumboStringMode.ALLOW))); - assertTrue( - mainMethod - .streamInstructions() - .noneMatch(i -> i.isConstString("Dead code: 8", JumboStringMode.ALLOW))); - }) + assertTrue( + mainMethod.streamInstructions().noneMatch( + i -> i.isConstString("Dead code: 1", JumboStringMode.ALLOW))); + // TODO(b/138913138): effectively final, and default value is set. + assertFalse( + mainMethod.streamInstructions().noneMatch( + i -> i.isConstString("Dead code: 2", JumboStringMode.ALLOW))); + // TODO(b/138913138): not trivial; assigned only once in <init> + assertFalse( + mainMethod.streamInstructions().noneMatch( + i -> i.isConstString("Dead code: 3", JumboStringMode.ALLOW))); + assertTrue( + mainMethod.streamInstructions().noneMatch( + i -> i.isConstString("Dead code: 4", JumboStringMode.ALLOW))); + // TODO(b/138913138): effectively final, and default value is set. + assertFalse( + mainMethod.streamInstructions().noneMatch( + i -> i.isConstString("Dead code: 5", JumboStringMode.ALLOW))); + // TODO(b/138913138): not trivial; assigned multiple times, but within a certain range. + assertFalse( + mainMethod.streamInstructions().noneMatch( + i -> i.isConstString("Dead code: 6", JumboStringMode.ALLOW))); + assertTrue( + mainMethod.streamInstructions().noneMatch( + i -> i.isConstString("Dead code: 7", JumboStringMode.ALLOW))); + // TODO(b/138913138): effectively final, and default value is set. + assertFalse( + mainMethod.streamInstructions().noneMatch( + i -> i.isConstString("Dead code: 8", JumboStringMode.ALLOW))); + }) .run(parameters.getRuntime(), MAIN) .assertSuccessWithOutputLines("The end"); }