diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index c098fb8..d5d0558 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -807,7 +807,9 @@
 
   public static R8Command.Builder prepareR8CommandBuilder(
       AndroidApp app, ProgramConsumer programConsumer) {
-    return R8Command.builder(app).setProgramConsumer(programConsumer);
+    return R8Command.builder(app)
+        .setProgramConsumer(programConsumer)
+        .setProguardMapConsumer(StringConsumer.emptyConsumer());
   }
 
   public static AndroidApp runR8(AndroidApp app) throws IOException {
diff --git a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ProguardCompatabilityTestBase.java b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ProguardCompatabilityTestBase.java
index e29ceae..10c64e3 100644
--- a/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ProguardCompatabilityTestBase.java
+++ b/src/test/java/com/android/tools/r8/shaking/forceproguardcompatibility/ProguardCompatabilityTestBase.java
@@ -20,10 +20,12 @@
 import com.android.tools.r8.utils.DexInspector;
 import com.android.tools.r8.utils.DexInspector.ClassSubject;
 import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.InternalOptions;
 import com.google.common.collect.ImmutableList;
 import java.io.File;
 import java.nio.file.Path;
 import java.util.List;
+import java.util.function.Consumer;
 
 public class ProguardCompatabilityTestBase extends TestBase {
 
@@ -87,11 +89,18 @@
     throw new IllegalArgumentException("Unknown shrinker: " + mode);
   }
 
-  protected AndroidApp runR8Raw(List<Class> programClasses, String proguardConfig) throws Exception {
+  protected AndroidApp runR8Raw(List<Class> programClasses, String proguardConfig)
+      throws Exception {
+    return runR8Raw(programClasses, proguardConfig, null);
+  }
+
+  protected AndroidApp runR8Raw(
+      List<Class> programClasses, String proguardConfig, Consumer<InternalOptions> configure)
+      throws Exception {
     AndroidApp app = readClassesAndAndriodJar(programClasses);
     R8Command.Builder builder = ToolHelper.prepareR8CommandBuilder(app);
     builder.addProguardConfiguration(ImmutableList.of(proguardConfig), Origin.unknown());
-    return ToolHelper.runR8(builder.build());
+    return ToolHelper.runR8(builder.build(), configure);
   }
 
   protected DexInspector runR8(List<Class> programClasses, String proguardConfig) throws Exception {
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java b/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java
new file mode 100644
index 0000000..14391ee
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/inlining/IfRuleWithInlining.java
@@ -0,0 +1,105 @@
+// Copyright (c) 2018, 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.shaking.ifrule.inlining;
+
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatabilityTestBase;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+class A {
+  static public int a() {
+    try {
+      String p = A.class.getPackage().getName();
+      Class.forName(p + ".D");
+    } catch (ClassNotFoundException e) {
+      return 2;
+    }
+    return 1;
+  }
+}
+
+class B {
+  // Depending on inlining option, this method is kept to make inlining of A.a() infeasible.
+  void x() {
+    System.out.print("" + A.a() + A.a() + A.a() + A.a() + A.a() + A.a() + A.a() + A.a());
+  }
+}
+
+class D {
+}
+
+class Main {
+  public static void main(String[] args) {
+    System.out.print("" + A.a());
+  }
+}
+
+@RunWith(Parameterized.class)
+public class IfRuleWithInlining extends ProguardCompatabilityTestBase {
+  private final static List<Class> CLASSES = ImmutableList.of(
+      A.class, B.class, D.class, Main.class);
+
+  private final Shrinker shrinker;
+  private final boolean inlineMethod;
+
+  public IfRuleWithInlining(Shrinker shrinker, boolean inlineMethod) {
+    this.shrinker = shrinker;
+    this.inlineMethod = inlineMethod;
+  }
+
+  @Parameters(name = "shrinker: {0} inlineMethod: {1}")
+  public static Collection<Object[]> data() {
+    // We don't run this on Proguard, as triggering inlining in Proguard is out of our control.
+    return ImmutableList.of(
+        new Object[]{Shrinker.R8, true},
+        new Object[]{Shrinker.R8, false}
+    );
+  }
+
+  private void check(AndroidApp app) throws Exception {
+    DexInspector inspector = new DexInspector(app);
+    ClassSubject clazzA = inspector.clazz(A.class);
+    assertThat(clazzA, isPresent());
+    // A.a might be inlined.
+    assertEquals(!inlineMethod, clazzA.method("int", "a", ImmutableList.of()).isPresent());
+    // TODO(110148109): class D should be present - inlining or not.
+    assertEquals(!inlineMethod, inspector.clazz(D.class).isPresent());
+    ProcessResult result = runOnArtRaw(app, Main.class.getName());
+    assertEquals(0, result.exitCode);
+    // TODO(110148109): Output should be the same - inlining or not.
+    assertEquals(!inlineMethod ? "1" : "2", result.stdout);
+  }
+
+  @Test
+  public void testMergedClassMethodInIfRule() throws Exception {
+    List<String> config = ImmutableList.of(
+        "-keep class **.Main { public static void main(java.lang.String[]); }",
+        inlineMethod
+            ? "-alwaysinline class **.A { int a(); }"
+            : "-keep class **.B { *; }",
+        inlineMethod
+            ? "-checkdiscard class **.A { int a(); }"
+            : "",
+        "-if class **.A { static int a(); }",
+        "-keep class **.D",
+        "-dontobfuscate"
+    );
+
+    check(runShrinkerRaw(shrinker, CLASSES, config));
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java
new file mode 100644
index 0000000..b484d73
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/shaking/ifrule/verticalclassmerging/IfRuleWithVerticalClassMerging.java
@@ -0,0 +1,156 @@
+// Copyright (c) 2018, 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.shaking.ifrule.verticalclassmerging;
+
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.shaking.forceproguardcompatibility.ProguardCompatabilityTestBase;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import com.android.tools.r8.utils.InternalOptions;
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+class A {
+  int x = 1;
+  int a() throws ClassNotFoundException {
+    // Class D is expected to be kept - vertical class merging or not. The -if rule say that if
+    // the method A.a is in the output, then class D is needed.
+    String p =getClass().getPackage().getName();
+    Class.forName(p + ".D");
+    return 4;
+  }
+}
+
+class B extends A {
+  int y = 2;
+  int b() {
+    return 5;
+  }
+}
+
+class C extends B {
+  int z = 3;
+  int c() {
+    return 6;
+  }
+}
+
+class D {
+}
+
+class Main {
+  public static void main(String[] args) throws ClassNotFoundException {
+    C c = new C();
+    System.out.print("" + c.x + "" + c.y + "" + c.z + "" + c.a() + "" + c.b() + "" + c.c());
+  }
+}
+
+@RunWith(Parameterized.class)
+public class IfRuleWithVerticalClassMerging extends ProguardCompatabilityTestBase {
+  private final static List<Class> CLASSES = ImmutableList.of(
+      A.class, B.class, C.class, D.class, Main.class);
+
+  private final Shrinker shrinker;
+  private final boolean enableClassMerging;
+
+  public IfRuleWithVerticalClassMerging(Shrinker shrinker, boolean enableClassMerging) {
+    this.shrinker = shrinker;
+    this.enableClassMerging = enableClassMerging;
+  }
+
+  @Parameters(name = "shrinker: {0} classMerging: {1}")
+  public static Collection<Object[]> data() {
+    // We don't run this on Proguard, as Proguard does not merge A into B.
+    return ImmutableList.of(
+        new Object[]{Shrinker.R8, true},
+        new Object[]{Shrinker.R8, false}
+    );
+  }
+
+  private void configure(InternalOptions options) {
+    options.enableClassMerging = enableClassMerging;
+  }
+
+  @Override
+  protected AndroidApp runR8Raw(
+      List<Class> programClasses, String proguardConfig) throws Exception {
+    return super.runR8Raw(programClasses, proguardConfig, this::configure);
+  }
+
+  private void check(AndroidApp app) throws Exception {
+    DexInspector inspector = new DexInspector(app);
+    ClassSubject clazzA = inspector.clazz(A.class);
+    assertEquals(!enableClassMerging, clazzA.isPresent());
+    ClassSubject clazzB = inspector.clazz(B.class);
+    assertThat(clazzB, isPresent());
+    ClassSubject clazzD = inspector.clazz(D.class);
+    // TODO(110141157): Class D should be kept - vertical class merging or not.
+    assertEquals(!enableClassMerging, clazzD.isPresent());
+
+    ProcessResult result = runOnArtRaw(app, Main.class.getName());
+    // TODO(110141157): The code should run - vertical class merging or not.
+    assertEquals(enableClassMerging ? 1 : 0, result.exitCode);
+    if (!enableClassMerging) {
+      assertEquals("123456", result.stdout);
+    }
+  }
+
+  @Test
+  public void testMergedClassInIfRule() throws Exception {
+    // Class C is kept, meaning that it will not be touched.
+    // Class A will be merged into class B.
+    List<String> config = ImmutableList.of(
+        "-keep class **.Main { public static void main(java.lang.String[]); }",
+        "-keep class **.C",
+        "-if class **.A",
+        "-keep class **.D",
+        "-dontobfuscate"
+    );
+
+    check(runShrinkerRaw(shrinker, CLASSES, config));
+  }
+
+  @Test
+  public void testMergedClassFieldInIfRule() throws Exception {
+    // Class C is kept, meaning that it will not be touched.
+    // Class A will be merged into class B.
+    // Main.main access A.x, so that field exists satisfying the if rule.
+    List<String> config = ImmutableList.of(
+        "-keep class **.Main { public static void main(java.lang.String[]); }",
+        "-keep class **.C",
+        "-if class **.A { int x; }",
+        "-keep class **.D",
+        "-dontobfuscate"
+    );
+
+    check(runShrinkerRaw(shrinker, CLASSES, config));
+  }
+
+  @Test
+  public void testMergedClassMethodInIfRule() throws Exception {
+    // Class C is kept, meaning that it will not be touched.
+    // Class A will be merged into class B.
+    // Main.main access A.a(), that method exists satisfying the if rule.
+    List<String> config = ImmutableList.of(
+        "-keep class **.Main { public static void main(java.lang.String[]); }",
+        "-keep class **.C",
+        "-if class **.A { int a(); }",
+        "-keep class **.D",
+        "-dontobfuscate"
+    );
+
+    check(runShrinkerRaw(shrinker, CLASSES, config));
+  }
+}
