001/*
002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.compiler.common.alloc;
024
025import static com.oracle.graal.compiler.common.GraalOptions.*;
026
027import java.util.*;
028
029import jdk.internal.jvmci.code.*;
030import jdk.internal.jvmci.meta.*;
031
032import com.oracle.graal.compiler.common.*;
033
034/**
035 * Configuration for register allocation. This is different to {@link RegisterConfig} as it only
036 * returns registers specified by {@link GraalOptions#RegisterPressure}.
037 */
038public class RegisterAllocationConfig {
039
040    public static final class AllocatableRegisters {
041        public final Register[] allocatableRegisters;
042        public final int minRegisterNumber;
043        public final int maxRegisterNumber;
044
045        public AllocatableRegisters(Register[] allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) {
046            this.allocatableRegisters = allocatableRegisters;
047            this.minRegisterNumber = minRegisterNumber;
048            this.maxRegisterNumber = maxRegisterNumber;
049            assert verify(allocatableRegisters, minRegisterNumber, maxRegisterNumber);
050        }
051
052        private static boolean verify(Register[] allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) {
053            int min = Integer.MAX_VALUE;
054            int max = Integer.MIN_VALUE;
055            for (Register reg : allocatableRegisters) {
056                int number = reg.number;
057                if (number < min) {
058                    min = number;
059                }
060                if (number > max) {
061                    max = number;
062                }
063            }
064            assert minRegisterNumber == min;
065            assert maxRegisterNumber == max;
066            return true;
067        }
068    }
069
070    public static final String ALL_REGISTERS = "<all>";
071
072    private static Register findRegister(String name, Register[] all) {
073        for (Register reg : all) {
074            if (reg.name.equals(name)) {
075                return reg;
076            }
077        }
078        throw new IllegalArgumentException("register " + name + " is not allocatable");
079    }
080
081    protected Register[] initAllocatable(Register[] registers) {
082        if (RegisterPressure.getValue() != null && !RegisterPressure.getValue().equals(ALL_REGISTERS)) {
083            String[] names = RegisterPressure.getValue().split(",");
084            Register[] regs = new Register[names.length];
085            for (int i = 0; i < names.length; i++) {
086                regs[i] = findRegister(names[i], registers);
087            }
088            return regs;
089        }
090
091        return registers;
092    }
093
094    protected final RegisterConfig registerConfig;
095    private final Map<PlatformKind.Key, AllocatableRegisters> categorized = new HashMap<>();
096    private Register[] cachedRegisters;
097
098    public RegisterAllocationConfig(RegisterConfig registerConfig) {
099        assert registerConfig != null;
100        this.registerConfig = registerConfig;
101    }
102
103    /**
104     * Gets the set of registers that can be used by the register allocator for a value of a
105     * particular kind.
106     */
107    public AllocatableRegisters getAllocatableRegisters(PlatformKind kind) {
108        PlatformKind.Key key = kind.getKey();
109        if (categorized.containsKey(key)) {
110            AllocatableRegisters val = categorized.get(key);
111            return val;
112        }
113        AllocatableRegisters ret = createAllocatableRegisters(registerConfig.filterAllocatableRegisters(kind, getAllocatableRegisters()));
114        categorized.put(key, ret);
115        return ret;
116    }
117
118    protected AllocatableRegisters createAllocatableRegisters(Register[] registers) {
119        return new AllocatableRegisters(registers, registers[0].number, registers[registers.length - 1].number);
120    }
121
122    /**
123     * Gets the set of registers that can be used by the register allocator.
124     */
125    public Register[] getAllocatableRegisters() {
126        if (cachedRegisters == null) {
127            cachedRegisters = initAllocatable(registerConfig.getAllocatableRegisters());
128        }
129        assert cachedRegisters != null;
130        return cachedRegisters;
131    }
132
133    public RegisterConfig getRegisterConfig() {
134        return registerConfig;
135    }
136
137}