diff --git a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java
index cb6f3bef7..b8d49cfe9 100644
--- a/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java
+++ b/core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java
@@ -460,7 +460,9 @@ class DependencyGraphBuilder {
                         return;
                     }
                 }
-                valueNode.connect(receiverNode, dependencyAnalyzer.getSuperClassFilter(targetType.toString()));
+                if (valueNode != null && receiverNode != null) {
+                    valueNode.connect(receiverNode, dependencyAnalyzer.getSuperClassFilter(targetType.toString()));
+                }
                 return;
             }
             if (valueNode != null && receiverNode != null) {
diff --git a/core/src/main/java/org/teavm/dependency/DependencyNode.java b/core/src/main/java/org/teavm/dependency/DependencyNode.java
index e469b387d..a6ff6da6d 100644
--- a/core/src/main/java/org/teavm/dependency/DependencyNode.java
+++ b/core/src/main/java/org/teavm/dependency/DependencyNode.java
@@ -33,7 +33,7 @@ import org.teavm.model.ValueType;
 public class DependencyNode implements ValueDependencyInfo {
     private static final int SMALL_TYPES_THRESHOLD = 3;
     private static final int DEGREE_THRESHOLD = 2;
-    private DependencyAnalyzer dependencyAnalyzer;
+    DependencyAnalyzer dependencyAnalyzer;
     List<DependencyConsumer> followers;
     TypeSet typeSet;
     ObjectObjectHashMap<DependencyNode, DependencyNodeToNodeTransition> transitions;
@@ -46,11 +46,10 @@ public class DependencyNode implements ValueDependencyInfo {
     private int degree;
     boolean locked;
     MethodReference method;
-    private ValueType typeFilter;
+    ValueType typeFilter;
     private DependencyTypeFilter cachedTypeFilter;
 
     boolean visitedFlag;
-    int splitCount;
 
     DependencyNode(DependencyAnalyzer dependencyAnalyzer, ValueType typeFilter) {
         this(dependencyAnalyzer, typeFilter, 0);
@@ -287,7 +286,7 @@ public class DependencyNode implements ValueDependencyInfo {
                 typeSet.transitions.add(transition);
             }
 
-            node.propagate(getTypesInternal());
+            node.propagate(filter != null ? getTypesInternal(filter) : getTypesInternal());
         }
 
         connectArrayItemNodes(node);
@@ -446,6 +445,21 @@ public class DependencyNode implements ValueDependencyInfo {
         return i == result.length ? result : Arrays.copyOf(result, i);
     }
 
+    DependencyType[] getTypesInternal(DependencyTypeFilter filter) {
+        if (typeSet == null) {
+            return new DependencyType[0];
+        }
+        DependencyType[] types = typeSet.getTypes();
+        DependencyType[] result = new DependencyType[types.length];
+        int i = 0;
+        for (DependencyType type : types) {
+            if (filter(type) && filter.match(type)) {
+                result[i++] = type;
+            }
+        }
+        return i == result.length ? result : Arrays.copyOf(result, i);
+    }
+
     public String getTag() {
         return tag;
     }
@@ -483,7 +497,6 @@ public class DependencyNode implements ValueDependencyInfo {
 
         for (DependencyNode node : domain) {
             node.typeSet = typeSet;
-            node.splitCount++;
         }
     }
 
@@ -502,7 +515,7 @@ public class DependencyNode implements ValueDependencyInfo {
                 for (ObjectCursor<DependencyNodeToNodeTransition> cursor : node.transitionList) {
                     DependencyNodeToNodeTransition transition = cursor.value;
                     if (transition.filter == null && transition.destination.typeSet == typeSet
-                            && !visited.contains(transition.destination)) {
+                            && !visited.contains(transition.destination) && transition.isDestSubsetOfSrc()) {
                         stack.push(transition.destination);
                     }
                 }
diff --git a/core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java b/core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java
index 4a654e268..b2a247516 100644
--- a/core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java
+++ b/core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java
@@ -19,6 +19,8 @@ import com.carrotsearch.hppc.IntSet;
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Collection;
+import org.teavm.model.ClassReaderSource;
+import org.teavm.model.ValueType;
 
 class DependencyNodeToNodeTransition  {
     DependencyNode source;
@@ -26,6 +28,7 @@ class DependencyNodeToNodeTransition  {
     DependencyTypeFilter filter;
     private BitSet knownFilteredOffTypes;
     IntSet pendingTypes;
+    byte destSubsetOfSrc;
 
     DependencyNodeToNodeTransition(DependencyNode source, DependencyNode destination, DependencyTypeFilter filter) {
         this.source = source;
@@ -69,7 +72,6 @@ class DependencyNodeToNodeTransition  {
             Collection<DependencyNode> domainToMerge = destination.typeSet.domain;
             for (DependencyNode node : domainToMerge) {
                 node.typeSet = source.typeSet;
-                node.splitCount++;
                 source.typeSet.domain.add(node);
             }
             source.typeSet.invalidate();
@@ -77,7 +79,7 @@ class DependencyNodeToNodeTransition  {
     }
 
     boolean shouldMergeDomains() {
-        if (filter != null || destination.splitCount > 2) {
+        if (filter != null) {
             return false;
         }
         if (destination.typeSet == null) {
@@ -171,4 +173,25 @@ class DependencyNodeToNodeTransition  {
     boolean pointsToDomainOrigin() {
         return destination.typeSet == null || destination.typeSet.origin == destination;
     }
+
+    boolean isDestSubsetOfSrc() {
+        if (destSubsetOfSrc == 0) {
+            destSubsetOfSrc = calculateDestSubsetOfSrc() ? (byte) 2 : 1;
+        }
+        return destSubsetOfSrc == 2;
+    }
+
+    private boolean calculateDestSubsetOfSrc() {
+        if (source.typeFilter == null) {
+            return true;
+        }
+        if (destination.typeFilter == null) {
+            return false;
+        }
+
+        ValueType sourceType = source.typeFilter;
+        ValueType destType = destination.typeFilter;
+        ClassReaderSource classSource = source.dependencyAnalyzer.getClassSource();
+        return classSource.isSuperType(sourceType, destType).orElse(false);
+    }
 }