diff options
Diffstat (limited to 'dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java')
-rw-r--r-- | dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java b/dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java new file mode 100644 index 0000000..851249b --- /dev/null +++ b/dx/src/com/android/dx/ssa/InterferenceRegisterMapper.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.dx.ssa; + +import com.android.dx.rop.code.RegisterSpecList; +import com.android.dx.rop.code.RegisterSpec; +import com.android.dx.ssa.back.InterferenceGraph; +import com.android.dx.util.IntSet; +import com.android.dx.util.BitIntSet; + +import java.util.ArrayList; +import java.util.BitSet; + +/** + * A register mapper that keeps track of the accumulated interference + * information for the registers in the new namespace. + * + * Please note that this mapper requires that the old namespace does not + * have variable register widths/categories, and the new namespace does. + */ +public class InterferenceRegisterMapper extends BasicRegisterMapper { + /** + * Array of interference sets. ArrayList is indexed by new namespace + * and BitIntSet's are indexed by old namespace. The list expands + * as needed and missing items are assumed to interfere with nothing. + * + * Bit sets are always used here, unlike elsewhere, because the max + * size of this matrix will be (countSsaRegs * countRopRegs), which may + * grow to hundreds of K but not megabytes. + */ + private final ArrayList<BitIntSet> newRegInterference; + + /** the interference graph for the old namespace */ + private final InterferenceGraph oldRegInterference; + + /** + * Constructs an instance + * + * @param countOldRegisters number of registers in old namespace + */ + public InterferenceRegisterMapper(InterferenceGraph oldRegInterference, + int countOldRegisters) { + super(countOldRegisters); + + newRegInterference = new ArrayList<BitIntSet>(); + this.oldRegInterference = oldRegInterference; + } + + /** {@inheritDoc} */ + @Override + public void addMapping(int oldReg, int newReg, int category) { + super.addMapping(oldReg, newReg, category); + + addInterfence(newReg, oldReg); + + if (category == 2) { + addInterfence(newReg + 1, oldReg); + } + } + + /** + * Checks to see if old namespace reg {@code oldReg} interferes + * with what currently maps to {@code newReg}. + * + * @param oldReg old namespace register + * @param newReg new namespace register + * @param category category of old namespace register + * @return true if oldReg will interfere with newReg + */ + public boolean interferes(int oldReg, int newReg, int category) { + if (newReg >= newRegInterference.size()) { + return false; + } else { + IntSet existing = newRegInterference.get(newReg); + + if (existing == null) { + return false; + } else if (category == 1) { + return existing.has(oldReg); + } else { + return existing.has(oldReg) + || (interferes(oldReg, newReg+1, category-1)); + } + } + } + + /** + * Checks to see if old namespace reg {@code oldReg} interferes + * with what currently maps to {@code newReg}. + * + * @param oldSpec {@code non-null;} old namespace register + * @param newReg new namespace register + * @return true if oldReg will interfere with newReg + */ + public boolean interferes(RegisterSpec oldSpec, int newReg) { + return interferes(oldSpec.getReg(), newReg, oldSpec.getCategory()); + } + + /** + * Adds a register's interference set to the interference list, + * growing it if necessary. + * + * @param newReg register in new namespace + * @param oldReg register in old namespace + */ + private void addInterfence(int newReg, int oldReg) { + newRegInterference.ensureCapacity(newReg + 1); + + while (newReg >= newRegInterference.size()) { + newRegInterference.add(new BitIntSet(newReg +1)); + } + + oldRegInterference.mergeInterferenceSet( + oldReg, newRegInterference.get(newReg)); + } + + /** + * Checks to see if any of a set of old-namespace registers are + * pinned to the specified new-namespace reg + category. Takes into + * account the category of the old-namespace registers. + * + * @param oldSpecs {@code non-null;} set of old-namespace regs + * @param newReg {@code >= 0;} new-namespace register + * @param targetCategory {@code 1..2;} the number of adjacent new-namespace + * registers (starting at ropReg) to consider + * @return true if any of the old-namespace register have been mapped + * to the new-namespace register + category + */ + public boolean areAnyPinned(RegisterSpecList oldSpecs, + int newReg, int targetCategory) { + int sz = oldSpecs.size(); + + for (int i = 0; i < sz; i++) { + RegisterSpec oldSpec = oldSpecs.get(i); + int r = oldToNew(oldSpec.getReg()); + + /* + * If oldSpec is a category-2 register, then check both newReg + * and newReg - 1. + */ + if (r == newReg + || (oldSpec.getCategory() == 2 && (r + 1) == newReg) + || (targetCategory == 2 && (r == newReg + 1))) { + return true; + } + } + + return false; + } +} |