• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 package com.android.dx.ssa;
18 
19 import com.android.dx.rop.code.RegisterSpec;
20 import com.android.dx.rop.code.RegisterSpecList;
21 import com.android.dx.ssa.back.InterferenceGraph;
22 import com.android.dx.util.BitIntSet;
23 import com.android.dx.util.IntSet;
24 import java.util.ArrayList;
25 
26 /**
27  * A register mapper that keeps track of the accumulated interference
28  * information for the registers in the new namespace.
29  *
30  * Please note that this mapper requires that the old namespace does not
31  * have variable register widths/categories, and the new namespace does.
32  */
33 public class InterferenceRegisterMapper extends BasicRegisterMapper {
34     /**
35      * Array of interference sets. ArrayList is indexed by new namespace
36      * and BitIntSet's are indexed by old namespace.  The list expands
37      * as needed and missing items are assumed to interfere with nothing.
38      *
39      * Bit sets are always used here, unlike elsewhere, because the max
40      * size of this matrix will be (countSsaRegs * countRopRegs), which may
41      * grow to hundreds of K but not megabytes.
42      */
43     private final ArrayList<BitIntSet> newRegInterference;
44 
45     /** the interference graph for the old namespace */
46     private final InterferenceGraph oldRegInterference;
47 
48     /**
49      * Constructs an instance
50      *
51      * @param countOldRegisters number of registers in old namespace
52      */
InterferenceRegisterMapper(InterferenceGraph oldRegInterference, int countOldRegisters)53     public InterferenceRegisterMapper(InterferenceGraph oldRegInterference,
54             int countOldRegisters) {
55         super(countOldRegisters);
56 
57         newRegInterference = new ArrayList<BitIntSet>();
58         this.oldRegInterference = oldRegInterference;
59     }
60 
61     /** {@inheritDoc} */
62     @Override
addMapping(int oldReg, int newReg, int category)63     public void addMapping(int oldReg, int newReg, int category) {
64         super.addMapping(oldReg, newReg, category);
65 
66         addInterfence(newReg, oldReg);
67 
68         if (category == 2) {
69             addInterfence(newReg + 1, oldReg);
70         }
71     }
72 
73     /**
74      * Checks to see if old namespace reg {@code oldReg} interferes
75      * with what currently maps to {@code newReg}.
76      *
77      * @param oldReg old namespace register
78      * @param newReg new namespace register
79      * @param category category of old namespace register
80      * @return true if oldReg will interfere with newReg
81      */
interferes(int oldReg, int newReg, int category)82     public boolean interferes(int oldReg, int newReg, int category) {
83         if (newReg >= newRegInterference.size()) {
84             return false;
85         } else {
86             IntSet existing = newRegInterference.get(newReg);
87 
88             if (existing == null) {
89                 return false;
90             } else if (category == 1) {
91                 return existing.has(oldReg);
92             } else {
93                 return existing.has(oldReg)
94                         || (interferes(oldReg, newReg+1, category-1));
95             }
96         }
97     }
98 
99     /**
100      * Checks to see if old namespace reg {@code oldReg} interferes
101      * with what currently maps to {@code newReg}.
102      *
103      * @param oldSpec {@code non-null;} old namespace register
104      * @param newReg new namespace register
105      * @return true if oldReg will interfere with newReg
106      */
interferes(RegisterSpec oldSpec, int newReg)107     public boolean interferes(RegisterSpec oldSpec, int newReg) {
108         return interferes(oldSpec.getReg(), newReg, oldSpec.getCategory());
109     }
110 
111     /**
112      * Adds a register's interference set to the interference list,
113      * growing it if necessary.
114      *
115      * @param newReg register in new namespace
116      * @param oldReg register in old namespace
117      */
addInterfence(int newReg, int oldReg)118     private void addInterfence(int newReg, int oldReg) {
119         newRegInterference.ensureCapacity(newReg + 1);
120 
121         while (newReg >= newRegInterference.size()) {
122             newRegInterference.add(new BitIntSet(newReg +1));
123         }
124 
125         oldRegInterference.mergeInterferenceSet(
126                 oldReg, newRegInterference.get(newReg));
127     }
128 
129     /**
130      * Checks to see if any of a set of old-namespace registers are
131      * pinned to the specified new-namespace reg + category. Takes into
132      * account the category of the old-namespace registers.
133      *
134      * @param oldSpecs {@code non-null;} set of old-namespace regs
135      * @param newReg {@code >= 0;} new-namespace register
136      * @param targetCategory {@code 1..2;} the number of adjacent new-namespace
137      * registers (starting at ropReg) to consider
138      * @return true if any of the old-namespace register have been mapped
139      * to the new-namespace register + category
140      */
areAnyPinned(RegisterSpecList oldSpecs, int newReg, int targetCategory)141     public boolean areAnyPinned(RegisterSpecList oldSpecs,
142             int newReg, int targetCategory) {
143         int sz = oldSpecs.size();
144 
145         for (int i = 0; i < sz; i++) {
146             RegisterSpec oldSpec = oldSpecs.get(i);
147             int r = oldToNew(oldSpec.getReg());
148 
149             /*
150              * If oldSpec is a category-2 register, then check both newReg
151              * and newReg - 1.
152              */
153             if (r == newReg
154                 || (oldSpec.getCategory() == 2 && (r + 1) == newReg)
155                 || (targetCategory == 2 && (r == newReg + 1))) {
156                 return true;
157             }
158         }
159 
160         return false;
161     }
162 }
163