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