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 }