package org.graalvm.compiler.core.common.alloc;
import jdk.internal.vm.compiler.collections.EconomicMap;
import jdk.internal.vm.compiler.collections.Equivalence;
import org.graalvm.compiler.core.common.GraalOptions;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.Register.RegisterCategory;
import jdk.vm.ci.code.RegisterArray;
import jdk.vm.ci.code.RegisterConfig;
import jdk.vm.ci.meta.PlatformKind;
public class RegisterAllocationConfig {
public static final class AllocatableRegisters {
public final Register[] allocatableRegisters;
public final int minRegisterNumber;
public final int maxRegisterNumber;
public AllocatableRegisters(RegisterArray allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) {
this.allocatableRegisters = allocatableRegisters.toArray();
this.minRegisterNumber = minRegisterNumber;
this.maxRegisterNumber = maxRegisterNumber;
assert verify(allocatableRegisters, minRegisterNumber, maxRegisterNumber);
}
private static boolean verify(RegisterArray allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (Register reg : allocatableRegisters) {
int number = reg.number;
if (number < min) {
min = number;
}
if (number > max) {
max = number;
}
}
assert minRegisterNumber == min;
assert maxRegisterNumber == max;
return true;
}
}
public static final String ALL_REGISTERS = "<all>";
private static Register findRegister(String name, RegisterArray all) {
for (Register reg : all) {
if (reg.name.equals(name)) {
return reg;
}
}
throw new IllegalArgumentException("register " + name + " is not allocatable");
}
protected RegisterArray initAllocatable(RegisterArray registers) {
if (allocationRestrictedTo != null) {
Register[] regs = new Register[allocationRestrictedTo.length];
for (int i = 0; i < allocationRestrictedTo.length; i++) {
regs[i] = findRegister(allocationRestrictedTo[i], registers);
}
return new RegisterArray(regs);
}
return registers;
}
protected final RegisterConfig registerConfig;
private final EconomicMap<PlatformKind.Key, AllocatableRegisters> categorized = EconomicMap.create(Equivalence.DEFAULT);
private final String[] allocationRestrictedTo;
private RegisterArray cachedRegisters;
public RegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) {
assert registerConfig != null;
this.registerConfig = registerConfig;
this.allocationRestrictedTo = allocationRestrictedTo;
}
public AllocatableRegisters getAllocatableRegisters(PlatformKind kind) {
PlatformKind.Key key = kind.getKey();
if (categorized.containsKey(key)) {
AllocatableRegisters val = categorized.get(key);
return val;
}
AllocatableRegisters ret = createAllocatableRegisters(registerConfig.filterAllocatableRegisters(kind, getAllocatableRegisters()));
categorized.put(key, ret);
return ret;
}
public RegisterCategory getRegisterCategory(PlatformKind kind) {
return getAllocatableRegisters(kind).allocatableRegisters[0].getRegisterCategory();
}
protected AllocatableRegisters createAllocatableRegisters(RegisterArray registers) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
for (Register reg : registers) {
int number = reg.number;
if (number < min) {
min = number;
}
if (number > max) {
max = number;
}
}
assert min < max;
return new AllocatableRegisters(registers, min, max);
}
public RegisterArray getAllocatableRegisters() {
if (cachedRegisters == null) {
cachedRegisters = initAllocatable(registerConfig.getAllocatableRegisters());
}
assert cachedRegisters != null;
return cachedRegisters;
}
public RegisterConfig getRegisterConfig() {
return registerConfig;
}
}