2 * Copyright (C) 2007 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.android.dx.ssa;
19 import com.android.dx.rop.code.RegisterSpecList;
20 import com.android.dx.rop.code.RegisterSpec;
21 import com.android.dx.ssa.back.InterferenceGraph;
22 import com.android.dx.util.IntSet;
23 import com.android.dx.util.BitIntSet;
25 import java.util.ArrayList;
26 import java.util.BitSet;
29 * A register mapper that keeps track of the accumulated interference
30 * information for the registers in the new namespace.
32 * Please note that this mapper requires that the old namespace does not
33 * have variable register widths/categories, and the new namespace does.
35 public class InterferenceRegisterMapper extends BasicRegisterMapper {
37 * Array of interference sets. ArrayList is indexed by new namespace
38 * and BitIntSet's are indexed by old namespace. The list expands
39 * as needed and missing items are assumed to interfere with nothing.
41 * Bit sets are always used here, unlike elsewhere, because the max
42 * size of this matrix will be (countSsaRegs * countRopRegs), which may
43 * grow to hundreds of K but not megabytes.
45 private final ArrayList<BitIntSet> newRegInterference;
47 /** the interference graph for the old namespace */
48 private final InterferenceGraph oldRegInterference;
51 * Constructs an instance
53 * @param countOldRegisters number of registers in old namespace
55 public InterferenceRegisterMapper(InterferenceGraph oldRegInterference,
56 int countOldRegisters) {
57 super(countOldRegisters);
59 newRegInterference = new ArrayList<BitIntSet>();
60 this.oldRegInterference = oldRegInterference;
65 public void addMapping(int oldReg, int newReg, int category) {
66 super.addMapping(oldReg, newReg, category);
68 addInterfence(newReg, oldReg);
71 addInterfence(newReg + 1, oldReg);
76 * Checks to see if old namespace reg {@code oldReg} interferes
77 * with what currently maps to {@code newReg}.
79 * @param oldReg old namespace register
80 * @param newReg new namespace register
81 * @param category category of old namespace register
82 * @return true if oldReg will interfere with newReg
84 public boolean interferes(int oldReg, int newReg, int category) {
85 if (newReg >= newRegInterference.size()) {
88 IntSet existing = newRegInterference.get(newReg);
90 if (existing == null) {
92 } else if (category == 1) {
93 return existing.has(oldReg);
95 return existing.has(oldReg)
96 || (interferes(oldReg, newReg+1, category-1));
102 * Checks to see if old namespace reg {@code oldReg} interferes
103 * with what currently maps to {@code newReg}.
105 * @param oldSpec {@code non-null;} old namespace register
106 * @param newReg new namespace register
107 * @return true if oldReg will interfere with newReg
109 public boolean interferes(RegisterSpec oldSpec, int newReg) {
110 return interferes(oldSpec.getReg(), newReg, oldSpec.getCategory());
114 * Adds a register's interference set to the interference list,
115 * growing it if necessary.
117 * @param newReg register in new namespace
118 * @param oldReg register in old namespace
120 private void addInterfence(int newReg, int oldReg) {
121 newRegInterference.ensureCapacity(newReg + 1);
123 while (newReg >= newRegInterference.size()) {
124 newRegInterference.add(new BitIntSet(newReg +1));
127 oldRegInterference.mergeInterferenceSet(
128 oldReg, newRegInterference.get(newReg));
132 * Checks to see if any of a set of old-namespace registers are
133 * pinned to the specified new-namespace reg + category. Takes into
134 * account the category of the old-namespace registers.
136 * @param oldSpecs {@code non-null;} set of old-namespace regs
137 * @param newReg {@code >= 0;} new-namespace register
138 * @param targetCategory {@code 1..2;} the number of adjacent new-namespace
139 * registers (starting at ropReg) to consider
140 * @return true if any of the old-namespace register have been mapped
141 * to the new-namespace register + category
143 public boolean areAnyPinned(RegisterSpecList oldSpecs,
144 int newReg, int targetCategory) {
145 int sz = oldSpecs.size();
147 for (int i = 0; i < sz; i++) {
148 RegisterSpec oldSpec = oldSpecs.get(i);
149 int r = oldToNew(oldSpec.getReg());
152 * If oldSpec is a category-2 register, then check both newReg
156 || (oldSpec.getCategory() == 2 && (r + 1) == newReg)
157 || (targetCategory == 2 && (r == newReg + 1))) {