blob: 1ef2f6a1805bc660ef3d6872e8b3af97523c9053 [file] [log] [blame]
// Copyright (c) 2020, 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.horizontalclassmerging.policies;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.horizontalclassmerging.MergeGroup;
import com.android.tools.r8.horizontalclassmerging.MultiClassPolicy;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class MinimizeFieldCasts extends MultiClassPolicy {
@Override
public final Collection<MergeGroup> apply(MergeGroup group) {
// First find all classes that can be merged without changing field types.
Map<Multiset<DexType>, MergeGroup> newGroups = new LinkedHashMap<>();
group.forEach(clazz -> addExact(clazz, newGroups));
// Create a single group from all trivial groups.
MergeGroup pendingGroup = new MergeGroup();
newGroups
.values()
.removeIf(
newGroup -> {
if (newGroup.isTrivial()) {
pendingGroup.add(newGroup);
return true;
}
return false;
});
if (pendingGroup.isEmpty()) {
return newGroups.values();
}
if (!pendingGroup.isTrivial()) {
List<MergeGroup> newGroupsIncludingRelaxedGroup = new ArrayList<>(newGroups.values());
newGroupsIncludingRelaxedGroup.add(pendingGroup);
return newGroupsIncludingRelaxedGroup;
}
MergeGroup smallestNewGroup = null;
for (MergeGroup newGroup : newGroups.values()) {
if (smallestNewGroup == null || newGroup.size() < smallestNewGroup.size()) {
smallestNewGroup = newGroup;
}
}
assert smallestNewGroup != null;
smallestNewGroup.add(pendingGroup);
return newGroups.values();
}
private void addExact(DexProgramClass clazz, Map<Multiset<DexType>, MergeGroup> groups) {
groups.computeIfAbsent(getExactMergeKey(clazz), ignore -> new MergeGroup()).add(clazz);
}
private Multiset<DexType> getExactMergeKey(DexProgramClass clazz) {
Multiset<DexType> fieldTypes = HashMultiset.create();
for (DexEncodedField field : clazz.instanceFields()) {
fieldTypes.add(field.getType());
}
return fieldTypes;
}
@Override
public String getName() {
return "MinimizeFieldCasts";
}
}