Harmonize CodeRewriterPass construction and calls

Bug: b/284304606
Change-Id: I38992f4b20f0214603ff46ea6dc632f4b05b5832
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
index d3c692e..9ecd2a9 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/GeneratedMessageLiteBuilderShrinker.java
@@ -346,7 +346,6 @@
   public void inlineCallsToDynamicMethod(
       ProgramMethod method,
       IRCode code,
-      EnumValueOptimizer enumValueOptimizer,
       OptimizationFeedback feedback,
       MethodProcessor methodProcessor,
       Inliner inliner) {
@@ -359,9 +358,7 @@
 
     // Run the enum optimization to optimize all Enum.ordinal() invocations. This is required to
     // get rid of the enum switch in dynamicMethod().
-    if (enumValueOptimizer != null) {
-      enumValueOptimizer.run(code, Timing.empty());
-    }
+    new EnumValueOptimizer(appView).run(code, Timing.empty());
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 58d4834..9329ef3 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -126,8 +126,6 @@
   private final ClassInliner classInliner;
   protected final InternalOptions options;
   public final CodeRewriter codeRewriter;
-  public final CommonSubexpressionElimination commonSubexpressionElimination;
-  private final SplitBranch splitBranch;
   public AssertionErrorTwoArgsConstructorRewriter assertionErrorTwoArgsConstructorRewriter;
   public final MemberValuePropagation<?> memberValuePropagation;
   private final LensCodeRewriter lensCodeRewriter;
@@ -138,8 +136,6 @@
   private final StringSwitchRemover stringSwitchRemover;
   private final TypeChecker typeChecker;
   protected ServiceLoaderRewriter serviceLoaderRewriter;
-  private final EnumValueOptimizer enumValueOptimizer;
-  private final BinopRewriter binopRewriter;
   protected final EnumUnboxer enumUnboxer;
   protected InstanceInitializerOutliner instanceInitializerOutliner;
   protected final RemoveVerificationErrorForUnknownReturnedValues
@@ -178,8 +174,6 @@
     this.appView = appView;
     this.options = appView.options();
     this.codeRewriter = new CodeRewriter(appView);
-    this.commonSubexpressionElimination = new CommonSubexpressionElimination(appView);
-    this.splitBranch = new SplitBranch(appView);
     this.assertionErrorTwoArgsConstructorRewriter =
         appView.options().desugarState.isOn()
             ? new AssertionErrorTwoArgsConstructorRewriter(appView)
@@ -229,8 +223,6 @@
       this.stringSwitchRemover = null;
       this.serviceLoaderRewriter = null;
       this.methodOptimizationInfoCollector = null;
-      this.enumValueOptimizer = null;
-      this.binopRewriter = null;
       this.enumUnboxer = EnumUnboxer.empty();
       this.assumeInserter = null;
       this.instanceInitializerOutliner = null;
@@ -291,12 +283,6 @@
           options.enableServiceLoaderRewriting
               ? new ServiceLoaderRewriter(appViewWithLiveness, appView.apiLevelCompute())
               : null;
-      this.enumValueOptimizer =
-          options.enableEnumValueOptimization ? new EnumValueOptimizer(appViewWithLiveness) : null;
-      this.binopRewriter =
-          options.testing.enableBinopOptimization && !options.debug
-              ? new BinopRewriter(appView)
-              : null;
     } else {
       AppView<AppInfo> appViewWithoutClassHierarchy = appView.withoutClassHierarchy();
       this.assumeInserter = null;
@@ -316,8 +302,6 @@
       this.typeChecker = null;
       this.serviceLoaderRewriter = null;
       this.methodOptimizationInfoCollector = null;
-      this.enumValueOptimizer = null;
-      this.binopRewriter = null;
       this.enumUnboxer = EnumUnboxer.empty();
     }
     this.stringSwitchRemover =
@@ -663,13 +647,10 @@
       previous = printMethod(code, "IR after member-value propagation (SSA)", previous);
     }
 
-    if (enumValueOptimizer != null) {
-      assert appView.enableWholeProgramOptimizations();
-      timing.begin("Remove switch maps");
-      enumValueOptimizer.removeSwitchMaps(code);
-      timing.end();
-      previous = printMethod(code, "IR after enum-value optimization (SSA)", previous);
-    }
+    timing.begin("Remove switch maps");
+    new EnumValueOptimizer(appView).removeSwitchMaps(code);
+    timing.end();
+    previous = printMethod(code, "IR after enum-switch optimization (SSA)", previous);
 
     if (instanceInitializerOutliner != null) {
       instanceInitializerOutliner.rewriteInstanceInitializers(
@@ -759,30 +740,24 @@
 
     assert code.verifyTypes(appView);
 
-    new TrivialCheckCastAndInstanceOfRemover(appView)
-        .run(code, methodProcessor, methodProcessingContext, timing);
-
-    if (enumValueOptimizer != null) {
-      assert appView.enableWholeProgramOptimizations();
-      enumValueOptimizer.run(code, timing);
-    }
-
-    new KnownArrayLengthRewriter(appView).run(code, timing);
-    new NaturalIntLoopRemover(appView).run(code, timing);
     if (assertionErrorTwoArgsConstructorRewriter != null) {
       timing.begin("Rewrite AssertionError");
       assertionErrorTwoArgsConstructorRewriter.rewrite(
           code, methodProcessor, methodProcessingContext);
       timing.end();
     }
-    commonSubexpressionElimination.run(code, timing);
+
+    new TrivialCheckCastAndInstanceOfRemover(appView)
+        .run(code, methodProcessor, methodProcessingContext, timing);
+    new EnumValueOptimizer(appView).run(code, timing);
+    new KnownArrayLengthRewriter(appView).run(code, timing);
+    new NaturalIntLoopRemover(appView).run(code, timing);
+    new CommonSubexpressionElimination(appView).run(code, timing);
     new ArrayConstructionSimplifier(appView).run(code, timing);
     new MoveResultRewriter(appView).run(code, timing);
-    if (options.enableStringConcatenationOptimization && !isDebugMode) {
-      new StringBuilderAppendOptimizer(appView).run(code, timing);
-    }
+    new StringBuilderAppendOptimizer(appView).run(code, timing);
     new SparseConditionalConstantPropagation(appView, code).run(code, timing);
-    new ThrowCatchOptimizer(appView, isDebugMode).run(code, timing);
+    new ThrowCatchOptimizer(appView).run(code, timing);
     if (new BranchSimplifier(appView)
         .run(code, timing)
         .asControlFlowSimplificationResult()
@@ -790,20 +765,14 @@
       new TrivialCheckCastAndInstanceOfRemover(appView)
           .run(code, methodProcessor, methodProcessingContext, timing);
     }
-    splitBranch.run(code, timing);
+    new SplitBranch(appView).run(code, timing);
     new RedundantConstNumberRemover(appView).run(code, timing);
     if (RedundantFieldLoadAndStoreElimination.shouldRun(appView, code)) {
       timing.begin("Remove field loads");
       new RedundantFieldLoadAndStoreElimination(appView, code).run();
       timing.end();
     }
-    if (binopRewriter != null) {
-      binopRewriter.run(code, timing);
-    }
-
-    if (options.testing.invertConditionals) {
-      invertConditionalsForTesting(code);
-    }
+    new BinopRewriter(appView).run(code, timing);
 
     timing.begin("Optimize class initializers");
     ClassInitializerDefaultsResult classInitializerDefaultsResult =
@@ -817,6 +786,10 @@
     deadCodeRemover.run(code, timing);
     assert code.isConsistentSSA(appView);
 
+    if (options.testing.invertConditionals) {
+      invertConditionalsForTesting(code);
+    }
+
     previous = printMethod(code, "IR after dead code removal (SSA)", previous);
 
     assert code.verifyTypes(appView);
@@ -831,7 +804,6 @@
       classInliner.processMethodCode(
           appView.withLiveness(),
           stringOptimizer,
-          enumValueOptimizer,
           code.context(),
           code,
           feedback,
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/BinopRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/BinopRewriter.java
index f684ff5..a84c292 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/BinopRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/BinopRewriter.java
@@ -245,7 +245,7 @@
 
   @Override
   protected boolean shouldRewriteCode(IRCode code) {
-    return true;
+    return options.testing.enableBinopOptimization && !isDebugMode(code.context());
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/BranchSimplifier.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/BranchSimplifier.java
index 44c9ddd..a239404 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/BranchSimplifier.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/BranchSimplifier.java
@@ -80,6 +80,11 @@
   }
 
   @Override
+  protected CodeRewriterResult noChange() {
+    return NO_CHANGE;
+  }
+
+  @Override
   protected CodeRewriterResult rewriteCode(IRCode code) {
     ControlFlowSimplificationResult switchResult = rewriteSwitch(code);
     ControlFlowSimplificationResult ifResult = simplifyIf(code);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
index aba955c..5f1705f 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/CodeRewriterPass.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.conversion.MethodProcessor;
 import com.android.tools.r8.ir.conversion.passes.result.CodeRewriterResult;
@@ -58,6 +59,10 @@
     return CodeRewriterResult.NO_CHANGE;
   }
 
+  protected boolean isDebugMode(ProgramMethod context) {
+    return options.debug || context.getOrComputeReachabilitySensitive(appView);
+  }
+
   protected abstract String getTimingId();
 
   protected CodeRewriterResult rewriteCode(IRCode code) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/ThrowCatchOptimizer.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/ThrowCatchOptimizer.java
index 85cd30e..fd79613 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/ThrowCatchOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/ThrowCatchOptimizer.java
@@ -43,16 +43,8 @@
 
 public class ThrowCatchOptimizer extends CodeRewriterPass<AppInfo> {
 
-  private final boolean rewriteThrowNull;
-
-  public ThrowCatchOptimizer(AppView<?> appView, boolean isDebug) {
-    super(appView);
-    this.rewriteThrowNull = !isDebug;
-  }
-
   public ThrowCatchOptimizer(AppView<?> appView) {
     super(appView);
-    this.rewriteThrowNull = false;
   }
 
   @Override
@@ -68,7 +60,7 @@
   @Override
   protected CodeRewriterResult rewriteCode(IRCode code) {
     optimizeAlwaysThrowingInstructions(code);
-    if (rewriteThrowNull) {
+    if (!isDebugMode(code.context())) {
       rewriteThrowNullPointerException(code);
     }
     return CodeRewriterResult.NONE;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
index b46d0a5..19b2d81 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/classinliner/ClassInliner.java
@@ -25,7 +25,6 @@
 import com.android.tools.r8.ir.optimize.Inliner;
 import com.android.tools.r8.ir.optimize.InliningOracle;
 import com.android.tools.r8.ir.optimize.classinliner.InlineCandidateProcessor.IllegalClassInlinerStateException;
-import com.android.tools.r8.ir.optimize.enums.EnumValueOptimizer;
 import com.android.tools.r8.ir.optimize.info.OptimizationFeedback;
 import com.android.tools.r8.ir.optimize.inliner.InliningIRProvider;
 import com.android.tools.r8.ir.optimize.string.StringOptimizer;
@@ -129,7 +128,6 @@
   public final void processMethodCode(
       AppView<AppInfoWithLiveness> appView,
       StringOptimizer stringOptimizer,
-      EnumValueOptimizer enumValueOptimizer,
       ProgramMethod method,
       IRCode code,
       OptimizationFeedback feedback,
@@ -242,7 +240,7 @@
       appView.withGeneratedMessageLiteBuilderShrinker(
           shrinker ->
               shrinker.inlineCallsToDynamicMethod(
-                  method, code, enumValueOptimizer, feedback, methodProcessor, inliner));
+                  method, code, feedback, methodProcessor, inliner));
     }
 
     if (anyInlinedMethods) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
index 46ed560..13d062b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumValueOptimizer.java
@@ -51,7 +51,7 @@
 
 public class EnumValueOptimizer extends CodeRewriterPass<AppInfoWithLiveness> {
 
-  public EnumValueOptimizer(AppView<AppInfoWithLiveness> appView) {
+  public EnumValueOptimizer(AppView<?> appView) {
     super(appView);
   }
 
@@ -62,12 +62,16 @@
 
   @Override
   protected CodeRewriterResult rewriteCode(IRCode code) {
+    assert appView.enableWholeProgramOptimizations();
     rewriteConstantEnumMethodCalls(code);
     return CodeRewriterResult.NONE;
   }
 
   @Override
   protected boolean shouldRewriteCode(IRCode code) {
+    if (!options.enableEnumValueOptimization || !appView.hasLiveness()) {
+      return false;
+    }
     return code.metadata().mayHaveInvokeMethodWithReceiver();
   }
 
@@ -215,6 +219,10 @@
    * </blockquote>
    */
   public void removeSwitchMaps(IRCode code) {
+    if (!options.enableEnumValueOptimization || !appView.hasLiveness()) {
+      return;
+    }
+    assert appView.enableWholeProgramOptimizations();
     Set<Value> affectedValues = Sets.newIdentityHashSet();
     boolean mayHaveIntroducedUnreachableBlocks = false;
     for (BasicBlock block : code.blocks) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
index 2ff8ec9..5ed16f7 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringBuilderAppendOptimizer.java
@@ -95,8 +95,10 @@
 
   @Override
   protected boolean shouldRewriteCode(IRCode code) {
-    return code.metadata().mayHaveNewInstance()
-        || code.metadata().mayHaveInvokeMethodWithReceiver();
+    return options.enableStringConcatenationOptimization
+        && !isDebugMode(code.context())
+        && (code.metadata().mayHaveNewInstance()
+            || code.metadata().mayHaveInvokeMethodWithReceiver());
   }
 
   @Override