Switch on opcode in lens code rewriter

Bug: 150269949
Change-Id: I23790772b813f72d5ab3c018799f00e937b61c57
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index 9346936..7daa4a1 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -7,6 +7,27 @@
 import static com.android.tools.r8.graph.UseRegistry.MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
 import static com.android.tools.r8.ir.code.Invoke.Type.STATIC;
 import static com.android.tools.r8.ir.code.Invoke.Type.VIRTUAL;
+import static com.android.tools.r8.ir.code.Opcodes.CHECK_CAST;
+import static com.android.tools.r8.ir.code.Opcodes.CONST_CLASS;
+import static com.android.tools.r8.ir.code.Opcodes.CONST_METHOD_HANDLE;
+import static com.android.tools.r8.ir.code.Opcodes.INIT_CLASS;
+import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_GET;
+import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_OF;
+import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_PUT;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_CUSTOM;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_DIRECT;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_INTERFACE;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_MULTI_NEW_ARRAY;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_NEW_ARRAY;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_POLYMORPHIC;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_STATIC;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_SUPER;
+import static com.android.tools.r8.ir.code.Opcodes.INVOKE_VIRTUAL;
+import static com.android.tools.r8.ir.code.Opcodes.MOVE_EXCEPTION;
+import static com.android.tools.r8.ir.code.Opcodes.NEW_ARRAY_EMPTY;
+import static com.android.tools.r8.ir.code.Opcodes.NEW_INSTANCE;
+import static com.android.tools.r8.ir.code.Opcodes.STATIC_GET;
+import static com.android.tools.r8.ir.code.Opcodes.STATIC_PUT;
 
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
@@ -114,290 +135,370 @@
       InstructionListIterator iterator = block.listIterator(code);
       while (iterator.hasNext()) {
         Instruction current = iterator.next();
-        if (current.isInvokeCustom()) {
-          InvokeCustom invokeCustom = current.asInvokeCustom();
-          DexCallSite callSite = invokeCustom.getCallSite();
-          DexCallSite newCallSite = rewriteCallSite(callSite, method);
-          if (newCallSite != callSite) {
-            Value newOutValue = makeOutValue(invokeCustom, code);
-            InvokeCustom newInvokeCustom =
-                new InvokeCustom(newCallSite, newOutValue, invokeCustom.inValues());
-            iterator.replaceCurrentInstruction(newInvokeCustom);
-            if (newOutValue != null && newOutValue.getType() != invokeCustom.getOutType()) {
-              affectedPhis.addAll(newOutValue.uniquePhiUsers());
-            }
-          }
-        } else if (current.isConstMethodHandle()) {
-          DexMethodHandle handle = current.asConstMethodHandle().getValue();
-          DexMethodHandle newHandle = rewriteDexMethodHandle(
-              handle, method, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
-          if (newHandle != handle) {
-            Value newOutValue = makeOutValue(current, code);
-            iterator.replaceCurrentInstruction(new ConstMethodHandle(newOutValue, newHandle));
-            if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
-              affectedPhis.addAll(newOutValue.uniquePhiUsers());
-            }
-          }
-        } else if (current.isInitClass()) {
-          InitClass initClass = current.asInitClass();
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(
-                  initClass.getClassValue(), (t, v) -> new InitClass(v, t));
-        } else if (current.isInvokeMethod()) {
-          InvokeMethod invoke = current.asInvokeMethod();
-          DexMethod invokedMethod = invoke.getInvokedMethod();
-          DexType invokedHolder = invokedMethod.holder;
-          if (invokedHolder.isArrayType()) {
-            DexType baseType = invokedHolder.toBaseType(factory);
-            new InstructionReplacer(code, current, iterator, affectedPhis)
-                .replaceInstructionIfTypeChanged(
-                    baseType,
-                    (t, v) -> {
-                      DexType mappedHolder = invokedHolder.replaceBaseType(t, factory);
-                      // Just reuse proto and name, as no methods on array types cant be renamed nor
-                      // change signature.
-                      DexMethod actualTarget =
-                          factory.createMethod(
-                              mappedHolder, invokedMethod.proto, invokedMethod.name);
-                      return Invoke.create(VIRTUAL, actualTarget, null, v, invoke.inValues());
-                    });
-            continue;
-          }
-          if (!invokedHolder.isClassType()) {
-            assert false;
-            continue;
-          }
-          if (invoke.isInvokeDirect()) {
-            checkInvokeDirect(method.method, invoke.asInvokeDirect());
-          }
-          GraphLenseLookupResult lenseLookup =
-              graphLense.lookupMethod(invokedMethod, method.method, invoke.getType());
-          DexMethod actualTarget = lenseLookup.getMethod();
-          Invoke.Type actualInvokeType = lenseLookup.getType();
-          if (actualTarget != invokedMethod || invoke.getType() != actualInvokeType) {
-            RewrittenPrototypeDescription prototypeChanges =
-                graphLense.lookupPrototypeChanges(actualTarget);
-
-            List<Value> newInValues;
-            ArgumentInfoCollection argumentInfoCollection =
-                prototypeChanges.getArgumentInfoCollection();
-            if (argumentInfoCollection.isEmpty()) {
-              newInValues = invoke.inValues();
-            } else {
-              if (argumentInfoCollection.hasRemovedArguments()) {
-                if (Log.ENABLED) {
-                  Log.info(
-                      getClass(),
-                      "Invoked method "
-                          + invokedMethod.toSourceString()
-                          + " with "
-                          + argumentInfoCollection.numberOfRemovedArguments()
-                          + " arguments removed");
-                }
-              }
-              newInValues = new ArrayList<>(actualTarget.proto.parameters.size());
-              for (int i = 0; i < invoke.inValues().size(); i++) {
-                ArgumentInfo argumentInfo = argumentInfoCollection.getArgumentInfo(i);
-                if (argumentInfo.isRewrittenTypeInfo()) {
-                  RewrittenTypeInfo argInfo = argumentInfo.asRewrittenTypeInfo();
-                  Value rewrittenValue =
-                      rewriteValueIfDefault(
-                          code,
-                          iterator,
-                          argInfo.getOldType(),
-                          argInfo.getNewType(),
-                          invoke.inValues().get(i));
-                  newInValues.add(rewrittenValue);
-                } else if (!argumentInfo.isRemovedArgumentInfo()) {
-                  newInValues.add(invoke.inValues().get(i));
+        switch (current.opcode()) {
+          case INVOKE_CUSTOM:
+            {
+              InvokeCustom invokeCustom = current.asInvokeCustom();
+              DexCallSite callSite = invokeCustom.getCallSite();
+              DexCallSite newCallSite = rewriteCallSite(callSite, method);
+              if (newCallSite != callSite) {
+                Value newOutValue = makeOutValue(invokeCustom, code);
+                InvokeCustom newInvokeCustom =
+                    new InvokeCustom(newCallSite, newOutValue, invokeCustom.inValues());
+                iterator.replaceCurrentInstruction(newInvokeCustom);
+                if (newOutValue != null && newOutValue.getType() != invokeCustom.getOutType()) {
+                  affectedPhis.addAll(newOutValue.uniquePhiUsers());
                 }
               }
             }
+            break;
 
-            ConstInstruction constantReturnMaterializingInstruction = null;
-            if (prototypeChanges.hasBeenChangedToReturnVoid(appView) && invoke.outValue() != null) {
-              constantReturnMaterializingInstruction =
-                  prototypeChanges.getConstantReturn(code, invoke.getPosition());
-              if (invoke.outValue().hasLocalInfo()) {
-                constantReturnMaterializingInstruction
-                    .outValue()
-                    .setLocalInfo(invoke.outValue().getLocalInfo());
-              }
-              invoke.outValue().replaceUsers(constantReturnMaterializingInstruction.outValue());
-              if (graphLense.lookupType(invoke.getReturnType()) != invoke.getReturnType()) {
-                affectedPhis.addAll(
-                    constantReturnMaterializingInstruction.outValue().uniquePhiUsers());
+          case CONST_METHOD_HANDLE:
+            {
+              DexMethodHandle handle = current.asConstMethodHandle().getValue();
+              DexMethodHandle newHandle =
+                  rewriteDexMethodHandle(handle, method, NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
+              if (newHandle != handle) {
+                Value newOutValue = makeOutValue(current, code);
+                iterator.replaceCurrentInstruction(new ConstMethodHandle(newOutValue, newHandle));
+                if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
+                  affectedPhis.addAll(newOutValue.uniquePhiUsers());
+                }
               }
             }
+            break;
 
-            Value newOutValue =
-                prototypeChanges.hasBeenChangedToReturnVoid(appView)
-                    ? null
-                    : makeOutValue(invoke, code);
-
-            if (prototypeChanges.hasExtraNullParameter()) {
-              iterator.previous();
-              Value extraNullValue = iterator.insertConstNullInstruction(code, appView.options());
-              iterator.next();
-              newInValues.add(extraNullValue);
+          case INIT_CLASS:
+            {
+              InitClass initClass = current.asInitClass();
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(
+                      initClass.getClassValue(), (t, v) -> new InitClass(v, t));
             }
+            break;
 
-            assert newInValues.size()
-                == actualTarget.proto.parameters.size() + (actualInvokeType == STATIC ? 0 : 1);
+          case INVOKE_DIRECT:
+          case INVOKE_INTERFACE:
+          case INVOKE_POLYMORPHIC:
+          case INVOKE_STATIC:
+          case INVOKE_SUPER:
+          case INVOKE_VIRTUAL:
+            {
+              InvokeMethod invoke = current.asInvokeMethod();
+              DexMethod invokedMethod = invoke.getInvokedMethod();
+              DexType invokedHolder = invokedMethod.holder;
+              if (invokedHolder.isArrayType()) {
+                DexType baseType = invokedHolder.toBaseType(factory);
+                new InstructionReplacer(code, current, iterator, affectedPhis)
+                    .replaceInstructionIfTypeChanged(
+                        baseType,
+                        (t, v) -> {
+                          DexType mappedHolder = invokedHolder.replaceBaseType(t, factory);
+                          // Just reuse proto and name, as no methods on array types cant be renamed
+                          // nor change signature.
+                          DexMethod actualTarget =
+                              factory.createMethod(
+                                  mappedHolder, invokedMethod.proto, invokedMethod.name);
+                          return Invoke.create(VIRTUAL, actualTarget, null, v, invoke.inValues());
+                        });
+                continue;
+              }
+              if (!invokedHolder.isClassType()) {
+                assert false;
+                continue;
+              }
+              if (invoke.isInvokeDirect()) {
+                checkInvokeDirect(method.method, invoke.asInvokeDirect());
+              }
+              GraphLenseLookupResult lenseLookup =
+                  graphLense.lookupMethod(invokedMethod, method.method, invoke.getType());
+              DexMethod actualTarget = lenseLookup.getMethod();
+              Invoke.Type actualInvokeType = lenseLookup.getType();
+              if (actualTarget != invokedMethod || invoke.getType() != actualInvokeType) {
+                RewrittenPrototypeDescription prototypeChanges =
+                    graphLense.lookupPrototypeChanges(actualTarget);
 
-            Invoke newInvoke =
-                Invoke.create(actualInvokeType, actualTarget, null, newOutValue, newInValues);
-            iterator.replaceCurrentInstruction(newInvoke);
-            if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
-              affectedPhis.addAll(newOutValue.uniquePhiUsers());
-            }
+                List<Value> newInValues;
+                ArgumentInfoCollection argumentInfoCollection =
+                    prototypeChanges.getArgumentInfoCollection();
+                if (argumentInfoCollection.isEmpty()) {
+                  newInValues = invoke.inValues();
+                } else {
+                  if (argumentInfoCollection.hasRemovedArguments()) {
+                    if (Log.ENABLED) {
+                      Log.info(
+                          getClass(),
+                          "Invoked method "
+                              + invokedMethod.toSourceString()
+                              + " with "
+                              + argumentInfoCollection.numberOfRemovedArguments()
+                              + " arguments removed");
+                    }
+                  }
+                  newInValues = new ArrayList<>(actualTarget.proto.parameters.size());
+                  for (int i = 0; i < invoke.inValues().size(); i++) {
+                    ArgumentInfo argumentInfo = argumentInfoCollection.getArgumentInfo(i);
+                    if (argumentInfo.isRewrittenTypeInfo()) {
+                      RewrittenTypeInfo argInfo = argumentInfo.asRewrittenTypeInfo();
+                      Value rewrittenValue =
+                          rewriteValueIfDefault(
+                              code,
+                              iterator,
+                              argInfo.getOldType(),
+                              argInfo.getNewType(),
+                              invoke.inValues().get(i));
+                      newInValues.add(rewrittenValue);
+                    } else if (!argumentInfo.isRemovedArgumentInfo()) {
+                      newInValues.add(invoke.inValues().get(i));
+                    }
+                  }
+                }
 
-            if (constantReturnMaterializingInstruction != null) {
-              if (block.hasCatchHandlers()) {
-                // Split the block to ensure no instructions after throwing instructions.
-                iterator
-                    .split(code, blocks)
-                    .listIterator(code)
-                    .add(constantReturnMaterializingInstruction);
-              } else {
-                iterator.add(constantReturnMaterializingInstruction);
+                ConstInstruction constantReturnMaterializingInstruction = null;
+                if (prototypeChanges.hasBeenChangedToReturnVoid(appView)
+                    && invoke.outValue() != null) {
+                  constantReturnMaterializingInstruction =
+                      prototypeChanges.getConstantReturn(code, invoke.getPosition());
+                  if (invoke.outValue().hasLocalInfo()) {
+                    constantReturnMaterializingInstruction
+                        .outValue()
+                        .setLocalInfo(invoke.outValue().getLocalInfo());
+                  }
+                  invoke.outValue().replaceUsers(constantReturnMaterializingInstruction.outValue());
+                  if (graphLense.lookupType(invoke.getReturnType()) != invoke.getReturnType()) {
+                    affectedPhis.addAll(
+                        constantReturnMaterializingInstruction.outValue().uniquePhiUsers());
+                  }
+                }
+
+                Value newOutValue =
+                    prototypeChanges.hasBeenChangedToReturnVoid(appView)
+                        ? null
+                        : makeOutValue(invoke, code);
+
+                if (prototypeChanges.hasExtraNullParameter()) {
+                  iterator.previous();
+                  Value extraNullValue =
+                      iterator.insertConstNullInstruction(code, appView.options());
+                  iterator.next();
+                  newInValues.add(extraNullValue);
+                }
+
+                assert newInValues.size()
+                    == actualTarget.proto.parameters.size() + (actualInvokeType == STATIC ? 0 : 1);
+
+                Invoke newInvoke =
+                    Invoke.create(actualInvokeType, actualTarget, null, newOutValue, newInValues);
+                iterator.replaceCurrentInstruction(newInvoke);
+                if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
+                  affectedPhis.addAll(newOutValue.uniquePhiUsers());
+                }
+
+                if (constantReturnMaterializingInstruction != null) {
+                  if (block.hasCatchHandlers()) {
+                    // Split the block to ensure no instructions after throwing instructions.
+                    iterator
+                        .split(code, blocks)
+                        .listIterator(code)
+                        .add(constantReturnMaterializingInstruction);
+                  } else {
+                    iterator.add(constantReturnMaterializingInstruction);
+                  }
+                }
+
+                DexType actualReturnType = actualTarget.proto.returnType;
+                DexType expectedReturnType = graphLense.lookupType(invokedMethod.proto.returnType);
+                if (newInvoke.outValue() != null && actualReturnType != expectedReturnType) {
+                  throw new Unreachable(
+                      "Unexpected need to insert a cast. Possibly related to resolving"
+                          + " b/79143143.\n"
+                          + invokedMethod
+                          + " type changed from "
+                          + expectedReturnType
+                          + " to "
+                          + actualReturnType);
+                }
               }
             }
+            break;
 
-            DexType actualReturnType = actualTarget.proto.returnType;
-            DexType expectedReturnType = graphLense.lookupType(invokedMethod.proto.returnType);
-            if (newInvoke.outValue() != null && actualReturnType != expectedReturnType) {
-              throw new Unreachable(
-                  "Unexpected need to insert a cast. Possibly related to resolving b/79143143.\n"
-                      + invokedMethod
-                      + " type changed from " + expectedReturnType
-                      + " to " + actualReturnType);
+          case INSTANCE_GET:
+            {
+              InstanceGet instanceGet = current.asInstanceGet();
+              DexField field = instanceGet.getField();
+              DexField actualField = graphLense.lookupField(field);
+              DexMethod replacementMethod =
+                  graphLense.lookupGetFieldForMethod(actualField, method.method);
+              if (replacementMethod != null) {
+                Value newOutValue = makeOutValue(current, code);
+                iterator.replaceCurrentInstruction(
+                    new InvokeStatic(replacementMethod, newOutValue, current.inValues()));
+                if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
+                  affectedPhis.addAll(current.outValue().uniquePhiUsers());
+                }
+              } else if (actualField != field) {
+                Value newOutValue = makeOutValue(instanceGet, code);
+                iterator.replaceCurrentInstruction(
+                    new InstanceGet(newOutValue, instanceGet.object(), actualField));
+                if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
+                  affectedPhis.addAll(newOutValue.uniquePhiUsers());
+                }
+              }
             }
-          }
-        } else if (current.isInstanceGet()) {
-          InstanceGet instanceGet = current.asInstanceGet();
-          DexField field = instanceGet.getField();
-          DexField actualField = graphLense.lookupField(field);
-          DexMethod replacementMethod =
-              graphLense.lookupGetFieldForMethod(actualField, method.method);
-          if (replacementMethod != null) {
-            Value newOutValue = makeOutValue(current, code);
-            iterator.replaceCurrentInstruction(
-                new InvokeStatic(replacementMethod, newOutValue, current.inValues()));
-            if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
-              affectedPhis.addAll(current.outValue().uniquePhiUsers());
+            break;
+
+          case INSTANCE_PUT:
+            {
+              InstancePut instancePut = current.asInstancePut();
+              DexField field = instancePut.getField();
+              DexField actualField = graphLense.lookupField(field);
+              DexMethod replacementMethod =
+                  graphLense.lookupPutFieldForMethod(actualField, method.method);
+              if (replacementMethod != null) {
+                iterator.replaceCurrentInstruction(
+                    new InvokeStatic(replacementMethod, null, current.inValues()));
+              } else if (actualField != field) {
+                Value rewrittenValue =
+                    rewriteValueIfDefault(
+                        code, iterator, field.type, actualField.type, instancePut.value());
+                InstancePut newInstancePut =
+                    InstancePut.createPotentiallyInvalid(
+                        actualField, instancePut.object(), rewrittenValue);
+                iterator.replaceCurrentInstruction(newInstancePut);
+              }
             }
-          } else if (actualField != field) {
-            Value newOutValue = makeOutValue(instanceGet, code);
-            iterator.replaceCurrentInstruction(
-                new InstanceGet(newOutValue, instanceGet.object(), actualField));
-            if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
-              affectedPhis.addAll(newOutValue.uniquePhiUsers());
+            break;
+
+          case STATIC_GET:
+            {
+              StaticGet staticGet = current.asStaticGet();
+              DexField field = staticGet.getField();
+              DexField actualField = graphLense.lookupField(field);
+              DexMethod replacementMethod =
+                  graphLense.lookupGetFieldForMethod(actualField, method.method);
+              if (replacementMethod != null) {
+                Value newOutValue = makeOutValue(current, code);
+                iterator.replaceCurrentInstruction(
+                    new InvokeStatic(replacementMethod, newOutValue, current.inValues()));
+                if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
+                  affectedPhis.addAll(newOutValue.uniquePhiUsers());
+                }
+              } else if (actualField != field) {
+                Value newOutValue = makeOutValue(staticGet, code);
+                iterator.replaceCurrentInstruction(new StaticGet(newOutValue, actualField));
+                if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
+                  affectedPhis.addAll(newOutValue.uniquePhiUsers());
+                }
+              }
             }
-          }
-        } else if (current.isInstancePut()) {
-          InstancePut instancePut = current.asInstancePut();
-          DexField field = instancePut.getField();
-          DexField actualField = graphLense.lookupField(field);
-          DexMethod replacementMethod =
-              graphLense.lookupPutFieldForMethod(actualField, method.method);
-          if (replacementMethod != null) {
-            iterator.replaceCurrentInstruction(
-                new InvokeStatic(replacementMethod, null, current.inValues()));
-          } else if (actualField != field) {
-            Value rewrittenValue =
-                rewriteValueIfDefault(
-                    code, iterator, field.type, actualField.type, instancePut.value());
-            InstancePut newInstancePut =
-                InstancePut.createPotentiallyInvalid(
-                    actualField, instancePut.object(), rewrittenValue);
-            iterator.replaceCurrentInstruction(newInstancePut);
-          }
-        } else if (current.isStaticGet()) {
-          StaticGet staticGet = current.asStaticGet();
-          DexField field = staticGet.getField();
-          DexField actualField = graphLense.lookupField(field);
-          DexMethod replacementMethod =
-              graphLense.lookupGetFieldForMethod(actualField, method.method);
-          if (replacementMethod != null) {
-            Value newOutValue = makeOutValue(current, code);
-            iterator.replaceCurrentInstruction(
-                new InvokeStatic(replacementMethod, newOutValue, current.inValues()));
-            if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
-              affectedPhis.addAll(newOutValue.uniquePhiUsers());
+            break;
+
+          case STATIC_PUT:
+            {
+              StaticPut staticPut = current.asStaticPut();
+              DexField field = staticPut.getField();
+              DexField actualField = graphLense.lookupField(field);
+              DexMethod replacementMethod =
+                  graphLense.lookupPutFieldForMethod(actualField, method.method);
+              if (replacementMethod != null) {
+                iterator.replaceCurrentInstruction(
+                    new InvokeStatic(replacementMethod, current.outValue(), current.inValues()));
+              } else if (actualField != field) {
+                Value rewrittenValue =
+                    rewriteValueIfDefault(
+                        code, iterator, field.type, actualField.type, staticPut.value());
+                StaticPut newStaticPut = new StaticPut(rewrittenValue, actualField);
+                iterator.replaceCurrentInstruction(newStaticPut);
+              }
             }
-          } else if (actualField != field) {
-            Value newOutValue = makeOutValue(staticGet, code);
-            iterator.replaceCurrentInstruction(new StaticGet(newOutValue, actualField));
-            if (newOutValue != null && newOutValue.getType() != current.getOutType()) {
-              affectedPhis.addAll(newOutValue.uniquePhiUsers());
+            break;
+
+          case CHECK_CAST:
+            {
+              CheckCast checkCast = current.asCheckCast();
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(
+                      checkCast.getType(), (t, v) -> new CheckCast(v, checkCast.object(), t));
             }
-          }
-        } else if (current.isStaticPut()) {
-          StaticPut staticPut = current.asStaticPut();
-          DexField field = staticPut.getField();
-          DexField actualField = graphLense.lookupField(field);
-          DexMethod replacementMethod =
-              graphLense.lookupPutFieldForMethod(actualField, method.method);
-          if (replacementMethod != null) {
-            iterator.replaceCurrentInstruction(
-                new InvokeStatic(replacementMethod, current.outValue(), current.inValues()));
-          } else if (actualField != field) {
-            Value rewrittenValue =
-                rewriteValueIfDefault(
-                    code, iterator, field.type, actualField.type, staticPut.value());
-            StaticPut newStaticPut = new StaticPut(rewrittenValue, actualField);
-            iterator.replaceCurrentInstruction(newStaticPut);
-          }
-        } else if (current.isCheckCast()) {
-          CheckCast checkCast = current.asCheckCast();
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(
-                  checkCast.getType(), (t, v) -> new CheckCast(v, checkCast.object(), t));
-        } else if (current.isConstClass()) {
-          ConstClass constClass = current.asConstClass();
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(
-                  constClass.getValue(), (t, v) -> new ConstClass(v, t));
-        } else if (current.isInstanceOf()) {
-          InstanceOf instanceOf = current.asInstanceOf();
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(
-                  instanceOf.type(), (t, v) -> new InstanceOf(v, instanceOf.value(), t));
-        } else if (current.isInvokeMultiNewArray()) {
-          InvokeMultiNewArray multiNewArray = current.asInvokeMultiNewArray();
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(
-                  multiNewArray.getArrayType(),
-                  (t, v) -> new InvokeMultiNewArray(t, v, multiNewArray.inValues()));
-        } else if (current.isInvokeNewArray()) {
-          InvokeNewArray newArray = current.asInvokeNewArray();
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(
-                  newArray.getArrayType(), (t, v) -> new InvokeNewArray(t, v, newArray.inValues()));
-        } else if (current.isMoveException()) {
-          MoveException moveException = current.asMoveException();
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(
-                  moveException.getExceptionType(),
-                  (t, v) -> new MoveException(v, t, appView.options()));
-        } else if (current.isNewArrayEmpty()) {
-          NewArrayEmpty newArrayEmpty = current.asNewArrayEmpty();
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(
-                  newArrayEmpty.type, (t, v) -> new NewArrayEmpty(v, newArrayEmpty.size(), t));
-        } else if (current.isNewInstance()) {
-          DexType type = current.asNewInstance().clazz;
-          new InstructionReplacer(code, current, iterator, affectedPhis)
-              .replaceInstructionIfTypeChanged(type, NewInstance::new);
-        } else if (current.outValue() != null) {
-          // For all other instructions, substitute any changed type.
-          TypeElement type = current.getOutType();
-          TypeElement substituted = type.fixupClassTypeReferences(graphLense::lookupType, appView);
-          if (substituted != type) {
-            current.outValue().setType(substituted);
-            affectedPhis.addAll(current.outValue().uniquePhiUsers());
-          }
+            break;
+
+          case CONST_CLASS:
+            {
+              ConstClass constClass = current.asConstClass();
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(
+                      constClass.getValue(), (t, v) -> new ConstClass(v, t));
+            }
+            break;
+
+          case INSTANCE_OF:
+            {
+              InstanceOf instanceOf = current.asInstanceOf();
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(
+                      instanceOf.type(), (t, v) -> new InstanceOf(v, instanceOf.value(), t));
+            }
+            break;
+
+          case INVOKE_MULTI_NEW_ARRAY:
+            {
+              InvokeMultiNewArray multiNewArray = current.asInvokeMultiNewArray();
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(
+                      multiNewArray.getArrayType(),
+                      (t, v) -> new InvokeMultiNewArray(t, v, multiNewArray.inValues()));
+            }
+            break;
+
+          case INVOKE_NEW_ARRAY:
+            {
+              InvokeNewArray newArray = current.asInvokeNewArray();
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(
+                      newArray.getArrayType(),
+                      (t, v) -> new InvokeNewArray(t, v, newArray.inValues()));
+            }
+            break;
+
+          case MOVE_EXCEPTION:
+            {
+              MoveException moveException = current.asMoveException();
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(
+                      moveException.getExceptionType(),
+                      (t, v) -> new MoveException(v, t, appView.options()));
+            }
+            break;
+
+          case NEW_ARRAY_EMPTY:
+            {
+              NewArrayEmpty newArrayEmpty = current.asNewArrayEmpty();
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(
+                      newArrayEmpty.type, (t, v) -> new NewArrayEmpty(v, newArrayEmpty.size(), t));
+            }
+            break;
+
+          case NEW_INSTANCE:
+            {
+              DexType type = current.asNewInstance().clazz;
+              new InstructionReplacer(code, current, iterator, affectedPhis)
+                  .replaceInstructionIfTypeChanged(type, NewInstance::new);
+            }
+            break;
+
+          default:
+            if (current.hasOutValue()) {
+              // For all other instructions, substitute any changed type.
+              TypeElement type = current.getOutType();
+              TypeElement substituted =
+                  type.fixupClassTypeReferences(graphLense::lookupType, appView);
+              if (substituted != type) {
+                current.outValue().setType(substituted);
+                affectedPhis.addAll(current.outValue().uniquePhiUsers());
+              }
+            }
+            break;
         }
       }
     }