1 /* 2 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.core.common.alloc; 24 25 import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; 26 27 import java.util.HashMap; 28 import java.util.Map; 29 30 import jdk.vm.ci.code.Register; 31 import jdk.vm.ci.code.RegisterArray; 32 import jdk.vm.ci.code.RegisterConfig; 33 import jdk.vm.ci.meta.PlatformKind; 34 35 import org.graalvm.compiler.core.common.GraalOptions; 36 37 /** 38 * Configuration for register allocation. This is different to {@link RegisterConfig} as it only 39 * returns registers specified by {@link GraalOptions#RegisterPressure}. 40 */ 41 public class RegisterAllocationConfig { 42 43 public static final class AllocatableRegisters { 44 public final Register[] allocatableRegisters; 45 public final int minRegisterNumber; 46 public final int maxRegisterNumber; 47 48 public AllocatableRegisters(RegisterArray allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) { 49 this.allocatableRegisters = allocatableRegisters.toArray(); 50 this.minRegisterNumber = minRegisterNumber; 51 this.maxRegisterNumber = maxRegisterNumber; 52 assert verify(allocatableRegisters, minRegisterNumber, maxRegisterNumber); 53 } 54 55 private static boolean verify(RegisterArray allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) { 56 int min = Integer.MAX_VALUE; 57 int max = Integer.MIN_VALUE; 58 for (Register reg : allocatableRegisters) { 59 int number = reg.number; 60 if (number < min) { 61 min = number; 62 } 63 if (number > max) { 64 max = number; 65 } 66 } 67 assert minRegisterNumber == min; 68 assert maxRegisterNumber == max; 69 return true; 70 } 71 } 72 73 public static final String ALL_REGISTERS = "<all>"; 74 75 private static Register findRegister(String name, RegisterArray all) { 76 for (Register reg : all) { 77 if (reg.name.equals(name)) { 78 return reg; 79 } 80 } 81 throw new IllegalArgumentException("register " + name + " is not allocatable"); 82 } 83 84 protected RegisterArray initAllocatable(RegisterArray registers) { 85 if (RegisterPressure.getValue() != null && !RegisterPressure.getValue().equals(ALL_REGISTERS)) { 86 String[] names = RegisterPressure.getValue().split(","); 87 Register[] regs = new Register[names.length]; 88 for (int i = 0; i < names.length; i++) { 89 regs[i] = findRegister(names[i], registers); 90 } 91 return new RegisterArray(regs); 92 } 93 94 return registers; 95 } 96 97 protected final RegisterConfig registerConfig; 98 private final Map<PlatformKind.Key, AllocatableRegisters> categorized = new HashMap<>(); 99 private RegisterArray cachedRegisters; 100 101 public RegisterAllocationConfig(RegisterConfig registerConfig) { 102 assert registerConfig != null; 103 this.registerConfig = registerConfig; 104 } 105 106 /** 107 * Gets the set of registers that can be used by the register allocator for a value of a 108 * particular kind. 109 */ 110 public AllocatableRegisters getAllocatableRegisters(PlatformKind kind) { 111 PlatformKind.Key key = kind.getKey(); 112 if (categorized.containsKey(key)) { 113 AllocatableRegisters val = categorized.get(key); 114 return val; 115 } 116 AllocatableRegisters ret = createAllocatableRegisters(registerConfig.filterAllocatableRegisters(kind, getAllocatableRegisters())); 117 categorized.put(key, ret); 118 return ret; 119 } 120 121 protected AllocatableRegisters createAllocatableRegisters(RegisterArray registers) { 122 int min = Integer.MAX_VALUE; 123 int max = Integer.MIN_VALUE; 124 for (Register reg : registers) { 125 int number = reg.number; 126 if (number < min) { 127 min = number; 128 } 129 if (number > max) { 130 max = number; 131 } 132 } 133 assert min < max; 134 return new AllocatableRegisters(registers, min, max); 135 136 } 137 138 /** 139 * Gets the set of registers that can be used by the register allocator. 140 */ 141 public RegisterArray getAllocatableRegisters() { 142 if (cachedRegisters == null) { 143 cachedRegisters = initAllocatable(registerConfig.getAllocatableRegisters()); 144 } 145 assert cachedRegisters != null; 146 return cachedRegisters; 147 } 148 149 public RegisterConfig getRegisterConfig() { 150 return registerConfig; 151 } 152 153 }