RegisterAllocationConfig.java revision 12657:6ef01bd40ce2
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 */
23package org.graalvm.compiler.core.common.alloc;
24
25import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure;
26
27import java.util.HashMap;
28import java.util.Map;
29
30import jdk.vm.ci.code.Register;
31import jdk.vm.ci.code.RegisterArray;
32import jdk.vm.ci.code.RegisterConfig;
33import jdk.vm.ci.meta.PlatformKind;
34
35import 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 */
41public 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}
154