1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/*
2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project
3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License.
6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at
7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and
14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License.
15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.ssa.back;
18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.CstInsn;
20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstInteger;
21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.ssa.NormalSsaInsn;
22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.ssa.BasicRegisterMapper;
23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.ssa.RegisterMapper;
24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.ssa.SsaMethod;
25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.IntSet;
26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.BitIntSet;
27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.BitSet;
29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.ArrayList;
30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/**
32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Allocates registers via a naive n^2 register allocator.
33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * This allocator does not try to co-locate local variables or deal
34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * intelligently with different size register uses.
35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic class FirstFitAllocator extends RegisterAllocator {
37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * If true, allocator places parameters at the top of the frame
39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * in calling-convention order.
40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static final boolean PRESLOT_PARAMS = true;
42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** indexed by old reg; the set of old regs we've mapped */
44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private final BitSet mapped;
45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public FirstFitAllocator(
48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            final SsaMethod ssaMeth, final InterferenceGraph interference) {
49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        super(ssaMeth, interference);
50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        mapped = new BitSet(ssaMeth.getRegCount());
52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean wantsParamsMovedHigh() {
57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return PRESLOT_PARAMS;
58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public RegisterMapper allocateRegisters() {
63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int oldRegCount = ssaMeth.getRegCount();
64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        BasicRegisterMapper mapper
66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                = new BasicRegisterMapper(oldRegCount);
67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int nextNewRegister = 0;
69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (PRESLOT_PARAMS) {
71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            /*
72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * Reserve space for the params at the bottom of the register
73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * space. Later, we'll flip the params to the end of the register
74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * space.
75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             */
76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            nextNewRegister = ssaMeth.getParamWidth();
78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (int i = 0; i < oldRegCount; i++) {
81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (mapped.get(i)) {
82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                // we already got this one
83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                continue;
84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int maxCategory = getCategoryForSsaReg(i);
87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            IntSet current = new BitIntSet(oldRegCount);
88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            interference.mergeInterferenceSet(i, current);
90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            boolean isPreslotted = false;
92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int newReg = 0;
93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (PRESLOT_PARAMS && isDefinitionMoveParam(i)) {
95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                // Any move-param definition must be a NormalSsaInsn
96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                NormalSsaInsn defInsn = (NormalSsaInsn)
97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                       ssaMeth.getDefinitionForRegister(i);
98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                newReg = paramNumberFromMoveParam(defInsn);
100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                mapper.addMapping(i, newReg, maxCategory);
102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                isPreslotted = true;
103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                mapper.addMapping(i, nextNewRegister, maxCategory);
105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                newReg = nextNewRegister;
106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (int j = i + 1; j < oldRegCount; j++) {
109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (mapped.get(j) || isDefinitionMoveParam(j)) {
110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    continue;
111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                /*
114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                 * If reg j doesn't interfere with the current mapping.
115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                 * Also, if this is a pre-slotted method parameter, we
116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                 * can't use more than the original param width.
117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                 */
118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (!current.has(j)
119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        && !(isPreslotted
120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            && (maxCategory < getCategoryForSsaReg(j)))) {
121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    interference.mergeInterferenceSet(j, current);
123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    maxCategory = Math.max(maxCategory,
125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            getCategoryForSsaReg(j));
126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    mapper.addMapping(j, newReg, maxCategory);
128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    mapped.set(j);
129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            mapped.set(i);
133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (!isPreslotted) {
134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                nextNewRegister += maxCategory;
135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return mapper;
139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Returns the parameter number that this move-param insn refers to
143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param ndefInsn a move-param insn (otherwise, exceptions will be thrown)
144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return parameter number (offset in the total parameter width)
145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private int paramNumberFromMoveParam(NormalSsaInsn ndefInsn) {
147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        CstInsn origInsn = (CstInsn) ndefInsn.getOriginalRopInsn();
148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return ((CstInteger) origInsn.getConstant()).getValue();
150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}
152