blob: 2a4880aac77b9c161eac3b6aecb769a6aff34c1e [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 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
buzbeeb046e162012-10-30 15:48:42 -070017/* This file contains register alloction support. */
buzbee67bf8852011-08-17 17:51:35 -070018
buzbeeefc63692012-11-14 16:31:52 -080019#include "../compiler_utility.h"
20#include "../compiler_ir.h"
21#include "../dataflow.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080022#include "ralloc_util.h"
23#include "codegen_util.h"
buzbee67bf8852011-08-17 17:51:35 -070024
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080025namespace art {
26
buzbee67bf8852011-08-17 17:51:35 -070027/*
28 * Free all allocated temps in the temp pools. Note that this does
29 * not affect the "liveness" of a temp register, which will stay
30 * live until it is either explicitly killed or reallocated.
31 */
buzbee52a77fc2012-11-20 19:50:46 -080032extern void ResetRegPool(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -070033{
Bill Buzbeea114add2012-05-03 15:00:40 -070034 int i;
35 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
36 if (cUnit->regPool->coreRegs[i].isTemp)
37 cUnit->regPool->coreRegs[i].inUse = false;
38 }
39 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
40 if (cUnit->regPool->FPRegs[i].isTemp)
41 cUnit->regPool->FPRegs[i].inUse = false;
42 }
buzbee67bf8852011-08-17 17:51:35 -070043}
44
buzbeee3acd072012-02-25 17:03:10 -080045 /*
46 * Set up temp & preserved register pools specialized by target.
47 * Note: numRegs may be zero.
48 */
buzbee52a77fc2012-11-20 19:50:46 -080049extern void CompilerInitPool(RegisterInfo* regs, int* regNums, int num)
buzbee67bf8852011-08-17 17:51:35 -070050{
Bill Buzbeea114add2012-05-03 15:00:40 -070051 int i;
52 for (i=0; i < num; i++) {
53 regs[i].reg = regNums[i];
54 regs[i].inUse = false;
55 regs[i].isTemp = false;
56 regs[i].pair = false;
57 regs[i].live = false;
58 regs[i].dirty = false;
59 regs[i].sReg = INVALID_SREG;
60 }
buzbee67bf8852011-08-17 17:51:35 -070061}
62
buzbee52a77fc2012-11-20 19:50:46 -080063void DumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070064{
Bill Buzbeea114add2012-05-03 15:00:40 -070065 LOG(INFO) << "================================================";
66 for (int i = 0; i < numRegs; i++) {
67 LOG(INFO) << StringPrintf(
68 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
69 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
buzbeecbd6d442012-11-17 14:11:25 -080070 p[i].live, p[i].dirty, p[i].sReg, reinterpret_cast<uintptr_t>(p[i].defStart),
71 reinterpret_cast<uintptr_t>(p[i].defEnd));
Bill Buzbeea114add2012-05-03 15:00:40 -070072 }
73 LOG(INFO) << "================================================";
buzbee67bf8852011-08-17 17:51:35 -070074}
75
buzbee52a77fc2012-11-20 19:50:46 -080076void DumpCoreRegPool(CompilationUnit* cUnit)
buzbee6181f792011-09-29 11:14:04 -070077{
buzbee52a77fc2012-11-20 19:50:46 -080078 DumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
buzbee6181f792011-09-29 11:14:04 -070079}
80
buzbee52a77fc2012-11-20 19:50:46 -080081void DumpFpRegPool(CompilationUnit* cUnit)
buzbee6181f792011-09-29 11:14:04 -070082{
buzbee52a77fc2012-11-20 19:50:46 -080083 DumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
buzbee6181f792011-09-29 11:14:04 -070084}
85
buzbee67bf8852011-08-17 17:51:35 -070086/* Mark a temp register as dead. Does not affect allocation state. */
buzbee52a77fc2012-11-20 19:50:46 -080087static inline void ClobberBody(CompilationUnit *cUnit, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -070088{
Bill Buzbeea114add2012-05-03 15:00:40 -070089 if (p->isTemp) {
90 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
91 p->live = false;
92 p->sReg = INVALID_SREG;
93 p->defStart = NULL;
94 p->defEnd = NULL;
95 if (p->pair) {
96 p->pair = false;
buzbee52a77fc2012-11-20 19:50:46 -080097 Clobber(cUnit, p->partner);
buzbee67bf8852011-08-17 17:51:35 -070098 }
Bill Buzbeea114add2012-05-03 15:00:40 -070099 }
buzbee67bf8852011-08-17 17:51:35 -0700100}
101
buzbee5abfa3e2012-01-31 17:01:43 -0800102/* Mark a temp register as dead. Does not affect allocation state. */
buzbee52a77fc2012-11-20 19:50:46 -0800103void Clobber(CompilationUnit* cUnit, int reg)
buzbee5abfa3e2012-01-31 17:01:43 -0800104{
buzbee52a77fc2012-11-20 19:50:46 -0800105 ClobberBody(cUnit, GetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800106}
107
buzbee52a77fc2012-11-20 19:50:46 -0800108void ClobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700109{
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 int i;
111 for (i=0; i< numRegs; i++) {
112 if (p[i].sReg == sReg) {
113 if (p[i].isTemp) {
114 p[i].live = false;
115 }
116 p[i].defStart = NULL;
117 p[i].defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700118 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700119 }
buzbee67bf8852011-08-17 17:51:35 -0700120}
121
122/* Clobber any temp associated with an sReg. Could be in either class */
buzbee52a77fc2012-11-20 19:50:46 -0800123extern void ClobberSReg(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700124{
buzbee3d661942012-03-14 17:37:27 -0700125#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 /* Reset live temp tracking sanity checker */
127 if (sReg == cUnit->liveSReg) {
128 cUnit->liveSReg = INVALID_SREG;
129 }
buzbee3d661942012-03-14 17:37:27 -0700130#endif
buzbee52a77fc2012-11-20 19:50:46 -0800131 ClobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs, sReg);
132 ClobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700133}
134
buzbee9c044ce2012-03-18 13:24:07 -0700135/*
136 * SSA names associated with the initial definitions of Dalvik
137 * registers are the same as the Dalvik register number (and
138 * thus take the same position in the promotionMap. However,
139 * the special Method* and compiler temp resisters use negative
Elliott Hughesbdf6c3d2012-03-20 13:43:53 -0700140 * vReg numbers to distinguish them and can have an arbitrary
buzbee9c044ce2012-03-18 13:24:07 -0700141 * ssa name (above the last original Dalvik register). This function
142 * maps SSA names to positions in the promotionMap array.
143 */
144int SRegToPMap(CompilationUnit* cUnit, int sReg)
buzbeee1965672012-03-11 18:39:19 -0700145{
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 DCHECK_LT(sReg, cUnit->numSSARegs);
147 DCHECK_GE(sReg, 0);
148 int vReg = SRegToVReg(cUnit, sReg);
149 if (vReg >= 0) {
150 DCHECK_LT(vReg, cUnit->numDalvikRegisters);
151 return vReg;
152 } else {
153 int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
154 DCHECK_LE(pos, cUnit->numCompilerTemps);
155 return cUnit->numDalvikRegisters + pos;
156 }
buzbeee1965672012-03-11 18:39:19 -0700157}
158
buzbee52a77fc2012-11-20 19:50:46 -0800159void RecordCorePromotion(CompilationUnit* cUnit, int reg, int sReg)
buzbeeca7a5e42012-08-20 11:12:18 -0700160{
161 int pMapIdx = SRegToPMap(cUnit, sReg);
162 int vReg = SRegToVReg(cUnit, sReg);
buzbee52a77fc2012-11-20 19:50:46 -0800163 GetRegInfo(cUnit, reg)->inUse = true;
buzbeeca7a5e42012-08-20 11:12:18 -0700164 cUnit->coreSpillMask |= (1 << reg);
165 // Include reg for later sort
166 cUnit->coreVmapTable.push_back(reg << VREG_NUM_WIDTH |
167 (vReg & ((1 << VREG_NUM_WIDTH) - 1)));
168 cUnit->numCoreSpills++;
169 cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
170 cUnit->promotionMap[pMapIdx].coreReg = reg;
171}
172
buzbee67bf8852011-08-17 17:51:35 -0700173/* Reserve a callee-save register. Return -1 if none available */
buzbee52a77fc2012-11-20 19:50:46 -0800174extern int AllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700175{
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 int res = -1;
177 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
178 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
179 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700180 res = coreRegs[i].reg;
buzbee52a77fc2012-11-20 19:50:46 -0800181 RecordCorePromotion(cUnit, res, sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 break;
buzbee67bf8852011-08-17 17:51:35 -0700183 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700184 }
185 return res;
buzbee67bf8852011-08-17 17:51:35 -0700186}
187
buzbee52a77fc2012-11-20 19:50:46 -0800188void RecordFpPromotion(CompilationUnit* cUnit, int reg, int sReg)
buzbeeca7a5e42012-08-20 11:12:18 -0700189{
190 int pMapIdx = SRegToPMap(cUnit, sReg);
191 int vReg = SRegToVReg(cUnit, sReg);
buzbee52a77fc2012-11-20 19:50:46 -0800192 GetRegInfo(cUnit, reg)->inUse = true;
193 MarkPreservedSingle(cUnit, vReg, reg);
buzbeeca7a5e42012-08-20 11:12:18 -0700194 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
buzbee52a77fc2012-11-20 19:50:46 -0800195 cUnit->promotionMap[pMapIdx].FpReg = reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700196}
197
buzbee67bf8852011-08-17 17:51:35 -0700198/*
199 * Reserve a callee-save fp single register. Try to fullfill request for
200 * even/odd allocation, but go ahead and allocate anything if not
201 * available. If nothing's available, return -1.
202 */
buzbee52a77fc2012-11-20 19:50:46 -0800203int AllocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700204{
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 int res = -1;
206 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
207 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
208 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
209 ((FPRegs[i].reg & 0x1) == 0) == even) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 res = FPRegs[i].reg;
buzbee52a77fc2012-11-20 19:50:46 -0800211 RecordFpPromotion(cUnit, res, sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 break;
buzbee67bf8852011-08-17 17:51:35 -0700213 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 }
215 return res;
buzbee67bf8852011-08-17 17:51:35 -0700216}
217
218/*
219 * Somewhat messy code here. We want to allocate a pair of contiguous
220 * physical single-precision floating point registers starting with
221 * an even numbered reg. It is possible that the paired sReg (sReg+1)
222 * has already been allocated - try to fit if possible. Fail to
223 * allocate if we can't meet the requirements for the pair of
224 * sReg<=sX[even] & (sReg+1)<= sX+1.
225 */
buzbee52a77fc2012-11-20 19:50:46 -0800226int AllocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700227{
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 int res = -1; // Assume failure
229 int vReg = SRegToVReg(cUnit, sReg);
230 int pMapIdx = SRegToPMap(cUnit, sReg);
231 if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
232 // Upper reg is already allocated. Can we fit?
buzbee52a77fc2012-11-20 19:50:46 -0800233 int highReg = cUnit->promotionMap[pMapIdx+1].FpReg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700234 if ((highReg & 1) == 0) {
235 // High reg is even - fail.
236 return res;
237 }
238 // Is the low reg of the pair free?
buzbee52a77fc2012-11-20 19:50:46 -0800239 RegisterInfo* p = GetRegInfo(cUnit, highReg-1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 if (p->inUse || p->isTemp) {
241 // Already allocated or not preserved - fail.
242 return res;
243 }
244 // OK - good to go.
245 res = p->reg;
246 p->inUse = true;
247 DCHECK_EQ((res & 1), 0);
buzbee52a77fc2012-11-20 19:50:46 -0800248 MarkPreservedSingle(cUnit, vReg, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 } else {
250 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
251 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
252 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
253 ((FPRegs[i].reg & 0x1) == 0x0) &&
254 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
255 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
256 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
257 res = FPRegs[i].reg;
258 FPRegs[i].inUse = true;
buzbee52a77fc2012-11-20 19:50:46 -0800259 MarkPreservedSingle(cUnit, vReg, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 FPRegs[i+1].inUse = true;
261 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
buzbee52a77fc2012-11-20 19:50:46 -0800262 MarkPreservedSingle(cUnit, vReg+1, res+1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 break;
264 }
buzbee67bf8852011-08-17 17:51:35 -0700265 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 }
267 if (res != -1) {
268 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
buzbee52a77fc2012-11-20 19:50:46 -0800269 cUnit->promotionMap[pMapIdx].FpReg = res;
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
buzbee52a77fc2012-11-20 19:50:46 -0800271 cUnit->promotionMap[pMapIdx+1].FpReg = res + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700272 }
273 return res;
buzbee67bf8852011-08-17 17:51:35 -0700274}
275
276
277/*
278 * Reserve a callee-save fp register. If this register can be used
279 * as the first of a double, attempt to allocate an even pair of fp
280 * single regs (but if can't still attempt to allocate a single, preferring
281 * first to allocate an odd register.
282 */
buzbee52a77fc2012-11-20 19:50:46 -0800283extern int AllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 bool doubleStart)
buzbee67bf8852011-08-17 17:51:35 -0700285{
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 int res = -1;
287 if (doubleStart) {
buzbee52a77fc2012-11-20 19:50:46 -0800288 res = AllocPreservedDouble(cUnit, sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700289 }
290 if (res == -1) {
buzbee52a77fc2012-11-20 19:50:46 -0800291 res = AllocPreservedSingle(cUnit, sReg, false /* try odd # */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 }
293 if (res == -1)
buzbee52a77fc2012-11-20 19:50:46 -0800294 res = AllocPreservedSingle(cUnit, sReg, true /* try even # */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700295 return res;
buzbee67bf8852011-08-17 17:51:35 -0700296}
297
buzbee52a77fc2012-11-20 19:50:46 -0800298int AllocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700299 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700300{
Bill Buzbeea114add2012-05-03 15:00:40 -0700301 int i;
302 int next = *nextTemp;
303 for (i=0; i< numRegs; i++) {
304 if (next >= numRegs)
305 next = 0;
306 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
buzbee52a77fc2012-11-20 19:50:46 -0800307 Clobber(cUnit, p[next].reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700308 p[next].inUse = true;
309 p[next].pair = false;
310 *nextTemp = next + 1;
311 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700312 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700313 next++;
314 }
315 next = *nextTemp;
316 for (i=0; i< numRegs; i++) {
317 if (next >= numRegs)
318 next = 0;
319 if (p[next].isTemp && !p[next].inUse) {
buzbee52a77fc2012-11-20 19:50:46 -0800320 Clobber(cUnit, p[next].reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700321 p[next].inUse = true;
322 p[next].pair = false;
323 *nextTemp = next + 1;
324 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700325 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 next++;
327 }
328 if (required) {
buzbee52a77fc2012-11-20 19:50:46 -0800329 CodegenDump(cUnit);
330 DumpRegPool(cUnit->regPool->coreRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 cUnit->regPool->numCoreRegs);
332 LOG(FATAL) << "No free temp registers";
333 }
334 return -1; // No register available
buzbee67bf8852011-08-17 17:51:35 -0700335}
336
337//REDO: too many assumptions.
buzbee52a77fc2012-11-20 19:50:46 -0800338extern int AllocTempDouble(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700339{
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 RegisterInfo* p = cUnit->regPool->FPRegs;
341 int numRegs = cUnit->regPool->numFPRegs;
342 /* Start looking at an even reg */
343 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700344
Bill Buzbeea114add2012-05-03 15:00:40 -0700345 // First try to avoid allocating live registers
346 for (int i=0; i < numRegs; i+=2) {
347 if (next >= numRegs)
348 next = 0;
349 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
350 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
buzbee52a77fc2012-11-20 19:50:46 -0800351 Clobber(cUnit, p[next].reg);
352 Clobber(cUnit, p[next+1].reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 p[next].inUse = true;
354 p[next+1].inUse = true;
355 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
356 DCHECK_EQ((p[next].reg & 0x1), 0);
357 cUnit->regPool->nextFPReg = next + 2;
358 if (cUnit->regPool->nextFPReg >= numRegs) {
359 cUnit->regPool->nextFPReg = 0;
360 }
361 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700362 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700363 next += 2;
364 }
365 next = cUnit->regPool->nextFPReg & ~0x1;
buzbeea50638b2011-11-02 15:15:06 -0700366
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 // No choice - find a pair and kill it.
368 for (int i=0; i < numRegs; i+=2) {
369 if (next >= numRegs)
370 next = 0;
371 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
372 !p[next+1].inUse) {
buzbee52a77fc2012-11-20 19:50:46 -0800373 Clobber(cUnit, p[next].reg);
374 Clobber(cUnit, p[next+1].reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 p[next].inUse = true;
376 p[next+1].inUse = true;
377 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
378 DCHECK_EQ((p[next].reg & 0x1), 0);
379 cUnit->regPool->nextFPReg = next + 2;
380 if (cUnit->regPool->nextFPReg >= numRegs) {
381 cUnit->regPool->nextFPReg = 0;
382 }
383 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700384 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 next += 2;
386 }
387 LOG(FATAL) << "No free temp registers (pair)";
388 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700389}
390
391/* Return a temp if one is available, -1 otherwise */
buzbee52a77fc2012-11-20 19:50:46 -0800392extern int AllocFreeTemp(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700393{
buzbee52a77fc2012-11-20 19:50:46 -0800394 return AllocTempBody(cUnit, cUnit->regPool->coreRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700395 cUnit->regPool->numCoreRegs,
396 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700397}
398
buzbee52a77fc2012-11-20 19:50:46 -0800399extern int AllocTemp(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700400{
buzbee52a77fc2012-11-20 19:50:46 -0800401 return AllocTempBody(cUnit, cUnit->regPool->coreRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 cUnit->regPool->numCoreRegs,
403 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700404}
405
buzbee52a77fc2012-11-20 19:50:46 -0800406extern int AllocTempFloat(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700407{
buzbee52a77fc2012-11-20 19:50:46 -0800408 return AllocTempBody(cUnit, cUnit->regPool->FPRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700409 cUnit->regPool->numFPRegs,
410 &cUnit->regPool->nextFPReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700411}
412
buzbee52a77fc2012-11-20 19:50:46 -0800413RegisterInfo* AllocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700414{
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 int i;
416 if (sReg == -1)
buzbee67bf8852011-08-17 17:51:35 -0700417 return NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 for (i=0; i < numRegs; i++) {
419 if (p[i].live && (p[i].sReg == sReg)) {
420 if (p[i].isTemp)
421 p[i].inUse = true;
422 return &p[i];
423 }
424 }
425 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700426}
427
buzbee52a77fc2012-11-20 19:50:46 -0800428RegisterInfo* AllocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700429{
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 RegisterInfo* res = NULL;
431 switch (regClass) {
432 case kAnyReg:
buzbee52a77fc2012-11-20 19:50:46 -0800433 res = AllocLiveBody(cUnit->regPool->FPRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 cUnit->regPool->numFPRegs, sReg);
435 if (res)
436 break;
437 /* Intentional fallthrough */
438 case kCoreReg:
buzbee52a77fc2012-11-20 19:50:46 -0800439 res = AllocLiveBody(cUnit->regPool->coreRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 cUnit->regPool->numCoreRegs, sReg);
441 break;
442 case kFPReg:
buzbee52a77fc2012-11-20 19:50:46 -0800443 res = AllocLiveBody(cUnit->regPool->FPRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 cUnit->regPool->numFPRegs, sReg);
445 break;
446 default:
447 LOG(FATAL) << "Invalid register type";
448 }
449 return res;
buzbee67bf8852011-08-17 17:51:35 -0700450}
451
buzbee52a77fc2012-11-20 19:50:46 -0800452extern void FreeTemp(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700453{
Bill Buzbeea114add2012-05-03 15:00:40 -0700454 RegisterInfo* p = cUnit->regPool->coreRegs;
455 int numRegs = cUnit->regPool->numCoreRegs;
456 int i;
457 for (i=0; i< numRegs; i++) {
458 if (p[i].reg == reg) {
459 if (p[i].isTemp) {
460 p[i].inUse = false;
461 }
462 p[i].pair = false;
463 return;
buzbee67bf8852011-08-17 17:51:35 -0700464 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 }
466 p = cUnit->regPool->FPRegs;
467 numRegs = cUnit->regPool->numFPRegs;
468 for (i=0; i< numRegs; i++) {
469 if (p[i].reg == reg) {
470 if (p[i].isTemp) {
471 p[i].inUse = false;
472 }
473 p[i].pair = false;
474 return;
buzbee67bf8852011-08-17 17:51:35 -0700475 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 }
477 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700478}
479
buzbee52a77fc2012-11-20 19:50:46 -0800480extern RegisterInfo* IsLive(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700481{
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 RegisterInfo* p = cUnit->regPool->coreRegs;
483 int numRegs = cUnit->regPool->numCoreRegs;
484 int i;
485 for (i=0; i< numRegs; i++) {
486 if (p[i].reg == reg) {
487 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700488 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 }
490 p = cUnit->regPool->FPRegs;
491 numRegs = cUnit->regPool->numFPRegs;
492 for (i=0; i< numRegs; i++) {
493 if (p[i].reg == reg) {
494 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700495 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 }
497 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700498}
499
buzbee52a77fc2012-11-20 19:50:46 -0800500extern RegisterInfo* IsTemp(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700501{
buzbee52a77fc2012-11-20 19:50:46 -0800502 RegisterInfo* p = GetRegInfo(cUnit, reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 return (p->isTemp) ? p : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700504}
505
buzbee52a77fc2012-11-20 19:50:46 -0800506extern RegisterInfo* IsPromoted(CompilationUnit* cUnit, int reg)
buzbeeb29e4d12011-09-26 15:05:48 -0700507{
buzbee52a77fc2012-11-20 19:50:46 -0800508 RegisterInfo* p = GetRegInfo(cUnit, reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700509 return (p->isTemp) ? NULL : p;
buzbeeb29e4d12011-09-26 15:05:48 -0700510}
511
buzbee52a77fc2012-11-20 19:50:46 -0800512extern bool IsDirty(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700513{
buzbee52a77fc2012-11-20 19:50:46 -0800514 RegisterInfo* p = GetRegInfo(cUnit, reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700515 return p->dirty;
buzbee67bf8852011-08-17 17:51:35 -0700516}
517
518/*
buzbee52a77fc2012-11-20 19:50:46 -0800519 * Similar to AllocTemp(), but forces the allocation of a specific
buzbee67bf8852011-08-17 17:51:35 -0700520 * register. No check is made to see if the register was previously
521 * allocated. Use with caution.
522 */
buzbee52a77fc2012-11-20 19:50:46 -0800523extern void LockTemp(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700524{
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 RegisterInfo* p = cUnit->regPool->coreRegs;
526 int numRegs = cUnit->regPool->numCoreRegs;
527 int i;
528 for (i=0; i< numRegs; i++) {
529 if (p[i].reg == reg) {
530 DCHECK(p[i].isTemp);
531 p[i].inUse = true;
532 p[i].live = false;
533 return;
buzbee67bf8852011-08-17 17:51:35 -0700534 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700535 }
536 p = cUnit->regPool->FPRegs;
537 numRegs = cUnit->regPool->numFPRegs;
538 for (i=0; i< numRegs; i++) {
539 if (p[i].reg == reg) {
540 DCHECK(p[i].isTemp);
541 p[i].inUse = true;
542 p[i].live = false;
543 return;
buzbee67bf8852011-08-17 17:51:35 -0700544 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700545 }
546 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700547}
548
buzbee52a77fc2012-11-20 19:50:46 -0800549static inline void ResetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700550{
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 p->defStart = NULL;
552 p->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700553}
554
buzbee52a77fc2012-11-20 19:50:46 -0800555extern void ResetDef(CompilationUnit* cUnit, int reg)
buzbee5abfa3e2012-01-31 17:01:43 -0800556{
buzbee52a77fc2012-11-20 19:50:46 -0800557 ResetDefBody(GetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800558}
559
buzbee52a77fc2012-11-20 19:50:46 -0800560void NullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
Bill Buzbeea114add2012-05-03 15:00:40 -0700561 int sReg1, int sReg2)
buzbee67bf8852011-08-17 17:51:35 -0700562{
Bill Buzbeea114add2012-05-03 15:00:40 -0700563 if (start && finish) {
564 LIR *p;
565 DCHECK_EQ(sReg1, sReg2);
566 for (p = start; ;p = p->next) {
buzbee52a77fc2012-11-20 19:50:46 -0800567 NopLIR(p);
Bill Buzbeea114add2012-05-03 15:00:40 -0700568 if (p == finish)
569 break;
buzbee67bf8852011-08-17 17:51:35 -0700570 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700571 }
buzbee67bf8852011-08-17 17:51:35 -0700572}
573
574/*
575 * Mark the beginning and end LIR of a def sequence. Note that
576 * on entry start points to the LIR prior to the beginning of the
577 * sequence.
578 */
buzbee52a77fc2012-11-20 19:50:46 -0800579extern void MarkDef(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700581{
Bill Buzbeea114add2012-05-03 15:00:40 -0700582 DCHECK(!rl.wide);
583 DCHECK(start && start->next);
584 DCHECK(finish);
buzbee52a77fc2012-11-20 19:50:46 -0800585 RegisterInfo* p = GetRegInfo(cUnit, rl.lowReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 p->defStart = start->next;
587 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700588}
589
590/*
591 * Mark the beginning and end LIR of a def sequence. Note that
592 * on entry start points to the LIR prior to the beginning of the
593 * sequence.
594 */
buzbee52a77fc2012-11-20 19:50:46 -0800595extern void MarkDefWide(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700596 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700597{
Bill Buzbeea114add2012-05-03 15:00:40 -0700598 DCHECK(rl.wide);
599 DCHECK(start && start->next);
600 DCHECK(finish);
buzbee52a77fc2012-11-20 19:50:46 -0800601 RegisterInfo* p = GetRegInfo(cUnit, rl.lowReg);
602 ResetDef(cUnit, rl.highReg); // Only track low of pair
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 p->defStart = start->next;
604 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700605}
606
buzbee52a77fc2012-11-20 19:50:46 -0800607extern RegLocation WideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700608{
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 DCHECK(rl.wide);
610 if (rl.location == kLocPhysReg) {
buzbee52a77fc2012-11-20 19:50:46 -0800611 RegisterInfo* infoLo = GetRegInfo(cUnit, rl.lowReg);
612 RegisterInfo* infoHi = GetRegInfo(cUnit, rl.highReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 if (infoLo->isTemp) {
614 infoLo->pair = false;
615 infoLo->defStart = NULL;
616 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700617 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 if (infoHi->isTemp) {
619 infoHi->pair = false;
620 infoHi->defStart = NULL;
621 infoHi->defEnd = NULL;
622 }
623 }
624 rl.wide = false;
625 return rl;
buzbee67bf8852011-08-17 17:51:35 -0700626}
627
buzbee52a77fc2012-11-20 19:50:46 -0800628extern void ResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700629{
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 DCHECK(!rl.wide);
buzbee52a77fc2012-11-20 19:50:46 -0800631 RegisterInfo* p = IsTemp(cUnit, rl.lowReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
633 DCHECK(!p->pair);
buzbee52a77fc2012-11-20 19:50:46 -0800634 NullifyRange(cUnit, p->defStart, p->defEnd, p->sReg, rl.sRegLow);
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 }
buzbee52a77fc2012-11-20 19:50:46 -0800636 ResetDef(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700637}
638
buzbee52a77fc2012-11-20 19:50:46 -0800639extern void ResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700640{
Bill Buzbeea114add2012-05-03 15:00:40 -0700641 DCHECK(rl.wide);
buzbee52a77fc2012-11-20 19:50:46 -0800642 RegisterInfo* pLow = IsTemp(cUnit, rl.lowReg);
643 RegisterInfo* pHigh = IsTemp(cUnit, rl.highReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
645 DCHECK(pLow->pair);
buzbee52a77fc2012-11-20 19:50:46 -0800646 NullifyRange(cUnit, pLow->defStart, pLow->defEnd, pLow->sReg, rl.sRegLow);
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 }
648 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
649 DCHECK(pHigh->pair);
650 }
buzbee52a77fc2012-11-20 19:50:46 -0800651 ResetDef(cUnit, rl.lowReg);
652 ResetDef(cUnit, rl.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700653}
654
buzbee52a77fc2012-11-20 19:50:46 -0800655extern void ResetDefTracking(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700656{
Bill Buzbeea114add2012-05-03 15:00:40 -0700657 int i;
658 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800659 ResetDefBody(&cUnit->regPool->coreRegs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700660 }
661 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800662 ResetDefBody(&cUnit->regPool->FPRegs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 }
buzbee67bf8852011-08-17 17:51:35 -0700664}
665
buzbee52a77fc2012-11-20 19:50:46 -0800666extern void ClobberAllRegs(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700667{
Bill Buzbeea114add2012-05-03 15:00:40 -0700668 int i;
669 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800670 ClobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700671 }
672 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
buzbee52a77fc2012-11-20 19:50:46 -0800673 ClobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 }
buzbee67bf8852011-08-17 17:51:35 -0700675}
676
buzbee67bf8852011-08-17 17:51:35 -0700677// Make sure nothing is live and dirty
buzbee52a77fc2012-11-20 19:50:46 -0800678void FlushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
Bill Buzbeea114add2012-05-03 15:00:40 -0700679 int numRegs)
buzbee67bf8852011-08-17 17:51:35 -0700680{
Bill Buzbeea114add2012-05-03 15:00:40 -0700681 int i;
682 for (i=0; i < numRegs; i++) {
683 if (info[i].live && info[i].dirty) {
684 if (info[i].pair) {
buzbee52a77fc2012-11-20 19:50:46 -0800685 FlushRegWide(cUnit, info[i].reg, info[i].partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700686 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800687 FlushReg(cUnit, info[i].reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700688 }
buzbee67bf8852011-08-17 17:51:35 -0700689 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700690 }
buzbee67bf8852011-08-17 17:51:35 -0700691}
692
buzbee52a77fc2012-11-20 19:50:46 -0800693extern void FlushAllRegs(CompilationUnit* cUnit)
buzbee67bf8852011-08-17 17:51:35 -0700694{
buzbee52a77fc2012-11-20 19:50:46 -0800695 FlushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 cUnit->regPool->numCoreRegs);
buzbee52a77fc2012-11-20 19:50:46 -0800697 FlushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 cUnit->regPool->numFPRegs);
buzbee52a77fc2012-11-20 19:50:46 -0800699 ClobberAllRegs(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700700}
701
702
703//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee52a77fc2012-11-20 19:50:46 -0800704bool RegClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700705{
Bill Buzbeea114add2012-05-03 15:00:40 -0700706 if (regClass == kAnyReg) {
707 return true;
708 } else if (regClass == kCoreReg) {
buzbee52a77fc2012-11-20 19:50:46 -0800709 return !IsFpReg(reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 } else {
buzbee52a77fc2012-11-20 19:50:46 -0800711 return IsFpReg(reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700712 }
buzbee67bf8852011-08-17 17:51:35 -0700713}
714
buzbee52a77fc2012-11-20 19:50:46 -0800715extern void MarkLive(CompilationUnit* cUnit, int reg, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700716{
buzbee52a77fc2012-11-20 19:50:46 -0800717 RegisterInfo* info = GetRegInfo(cUnit, reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700718 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
719 return; /* already live */
720 } else if (sReg != INVALID_SREG) {
buzbee52a77fc2012-11-20 19:50:46 -0800721 ClobberSReg(cUnit, sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700722 if (info->isTemp) {
723 info->live = true;
buzbee67bf8852011-08-17 17:51:35 -0700724 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700725 } else {
726 /* Can't be live if no associated sReg */
727 DCHECK(info->isTemp);
728 info->live = false;
729 }
730 info->sReg = sReg;
buzbee67bf8852011-08-17 17:51:35 -0700731}
732
buzbee52a77fc2012-11-20 19:50:46 -0800733extern void MarkTemp(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700734{
buzbee52a77fc2012-11-20 19:50:46 -0800735 RegisterInfo* info = GetRegInfo(cUnit, reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700736 info->isTemp = true;
buzbee67bf8852011-08-17 17:51:35 -0700737}
738
buzbee52a77fc2012-11-20 19:50:46 -0800739extern void UnmarkTemp(CompilationUnit* cUnit, int reg)
buzbee9e0f9b02011-08-24 15:32:46 -0700740{
buzbee52a77fc2012-11-20 19:50:46 -0800741 RegisterInfo* info = GetRegInfo(cUnit, reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700742 info->isTemp = false;
buzbee9e0f9b02011-08-24 15:32:46 -0700743}
744
buzbee52a77fc2012-11-20 19:50:46 -0800745extern void MarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
buzbee67bf8852011-08-17 17:51:35 -0700746{
buzbee52a77fc2012-11-20 19:50:46 -0800747 RegisterInfo* infoLo = GetRegInfo(cUnit, lowReg);
748 RegisterInfo* infoHi = GetRegInfo(cUnit, highReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700749 infoLo->pair = infoHi->pair = true;
750 infoLo->partner = highReg;
751 infoHi->partner = lowReg;
buzbee67bf8852011-08-17 17:51:35 -0700752}
753
buzbee52a77fc2012-11-20 19:50:46 -0800754extern void MarkClean(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700755{
buzbee52a77fc2012-11-20 19:50:46 -0800756 RegisterInfo* info = GetRegInfo(cUnit, loc.lowReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700757 info->dirty = false;
758 if (loc.wide) {
buzbee52a77fc2012-11-20 19:50:46 -0800759 info = GetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700760 info->dirty = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700761 }
buzbee67bf8852011-08-17 17:51:35 -0700762}
763
buzbee52a77fc2012-11-20 19:50:46 -0800764extern void MarkDirty(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700765{
Bill Buzbeea114add2012-05-03 15:00:40 -0700766 if (loc.home) {
767 // If already home, can't be dirty
768 return;
769 }
buzbee52a77fc2012-11-20 19:50:46 -0800770 RegisterInfo* info = GetRegInfo(cUnit, loc.lowReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700771 info->dirty = true;
772 if (loc.wide) {
buzbee52a77fc2012-11-20 19:50:46 -0800773 info = GetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700774 info->dirty = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 }
buzbee67bf8852011-08-17 17:51:35 -0700776}
777
buzbee52a77fc2012-11-20 19:50:46 -0800778extern void MarkInUse(CompilationUnit* cUnit, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700779{
buzbee52a77fc2012-11-20 19:50:46 -0800780 RegisterInfo* info = GetRegInfo(cUnit, reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700781 info->inUse = true;
buzbee67bf8852011-08-17 17:51:35 -0700782}
783
buzbee52a77fc2012-11-20 19:50:46 -0800784void CopyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700785{
buzbee52a77fc2012-11-20 19:50:46 -0800786 RegisterInfo* newInfo = GetRegInfo(cUnit, newReg);
787 RegisterInfo* oldInfo = GetRegInfo(cUnit, oldReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700788 // Target temp status must not change
789 bool isTemp = newInfo->isTemp;
790 *newInfo = *oldInfo;
791 // Restore target's temp status
792 newInfo->isTemp = isTemp;
793 newInfo->reg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700794}
795
796/*
797 * Return an updated location record with current in-register status.
798 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700799 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700800 * clobber both low and high.
801 * TUNING: clobbering both is a bit heavy-handed, but the alternative
802 * is a bit complex when dealing with FP regs. Examine code to see
803 * if it's worthwhile trying to be more clever here.
804 */
805
buzbee52a77fc2012-11-20 19:50:46 -0800806extern RegLocation UpdateLoc(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700807{
Bill Buzbeea114add2012-05-03 15:00:40 -0700808 DCHECK(!loc.wide);
buzbee52a77fc2012-11-20 19:50:46 -0800809 DCHECK(CheckCorePoolSanity(cUnit));
Bill Buzbeea114add2012-05-03 15:00:40 -0700810 if (loc.location != kLocPhysReg) {
811 DCHECK((loc.location == kLocDalvikFrame) ||
812 (loc.location == kLocCompilerTemp));
buzbee52a77fc2012-11-20 19:50:46 -0800813 RegisterInfo* infoLo = AllocLive(cUnit, loc.sRegLow, kAnyReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700814 if (infoLo) {
815 if (infoLo->pair) {
buzbee52a77fc2012-11-20 19:50:46 -0800816 Clobber(cUnit, infoLo->reg);
817 Clobber(cUnit, infoLo->partner);
818 FreeTemp(cUnit, infoLo->reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700819 } else {
820 loc.lowReg = infoLo->reg;
821 loc.location = kLocPhysReg;
822 }
buzbee67bf8852011-08-17 17:51:35 -0700823 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 }
buzbee67bf8852011-08-17 17:51:35 -0700825
Bill Buzbeea114add2012-05-03 15:00:40 -0700826 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700827}
828
buzbee52a77fc2012-11-20 19:50:46 -0800829bool CheckCorePoolSanity(CompilationUnit* cUnit)
buzbee6181f792011-09-29 11:14:04 -0700830{
831 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700832 if (cUnit->regPool->coreRegs[i].pair) {
833 static int myReg = cUnit->regPool->coreRegs[i].reg;
834 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
835 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
buzbee52a77fc2012-11-20 19:50:46 -0800836 static RegisterInfo* partner = GetRegInfo(cUnit, partnerReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 DCHECK(partner != NULL);
838 DCHECK(partner->pair);
839 DCHECK_EQ(myReg, partner->partner);
840 static int partnerSreg = partner->sReg;
841 if (mySreg == INVALID_SREG) {
842 DCHECK_EQ(partnerSreg, INVALID_SREG);
843 } else {
844 int diff = mySreg - partnerSreg;
845 DCHECK((diff == -1) || (diff == 1));
buzbee6181f792011-09-29 11:14:04 -0700846 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700847 }
848 if (!cUnit->regPool->coreRegs[i].live) {
849 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
850 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
851 }
buzbee6181f792011-09-29 11:14:04 -0700852 }
853 return true;
854}
855
buzbee67bf8852011-08-17 17:51:35 -0700856/* see comments for updateLoc */
buzbee52a77fc2012-11-20 19:50:46 -0800857extern RegLocation UpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700858{
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 DCHECK(loc.wide);
buzbee52a77fc2012-11-20 19:50:46 -0800860 DCHECK(CheckCorePoolSanity(cUnit));
Bill Buzbeea114add2012-05-03 15:00:40 -0700861 if (loc.location != kLocPhysReg) {
862 DCHECK((loc.location == kLocDalvikFrame) ||
863 (loc.location == kLocCompilerTemp));
864 // Are the dalvik regs already live in physical registers?
buzbee52a77fc2012-11-20 19:50:46 -0800865 RegisterInfo* infoLo = AllocLive(cUnit, loc.sRegLow, kAnyReg);
866 RegisterInfo* infoHi = AllocLive(cUnit,
Bill Buzbeea114add2012-05-03 15:00:40 -0700867 oatSRegHi(loc.sRegLow), kAnyReg);
868 bool match = true;
869 match = match && (infoLo != NULL);
870 match = match && (infoHi != NULL);
871 // Are they both core or both FP?
buzbee52a77fc2012-11-20 19:50:46 -0800872 match = match && (IsFpReg(infoLo->reg) == IsFpReg(infoHi->reg));
Bill Buzbeea114add2012-05-03 15:00:40 -0700873 // If a pair of floating point singles, are they properly aligned?
buzbee52a77fc2012-11-20 19:50:46 -0800874 if (match && IsFpReg(infoLo->reg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 match &= ((infoLo->reg & 0x1) == 0);
876 match &= ((infoHi->reg - infoLo->reg) == 1);
buzbee67bf8852011-08-17 17:51:35 -0700877 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700878 // If previously used as a pair, it is the same pair?
879 if (match && (infoLo->pair || infoHi->pair)) {
880 match = (infoLo->pair == infoHi->pair);
881 match &= ((infoLo->reg == infoHi->partner) &&
882 (infoHi->reg == infoLo->partner));
883 }
884 if (match) {
885 // Can reuse - update the register usage info
886 loc.lowReg = infoLo->reg;
887 loc.highReg = infoHi->reg;
888 loc.location = kLocPhysReg;
buzbee52a77fc2012-11-20 19:50:46 -0800889 MarkPair(cUnit, loc.lowReg, loc.highReg);
890 DCHECK(!IsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700891 return loc;
892 }
893 // Can't easily reuse - clobber and free any overlaps
894 if (infoLo) {
buzbee52a77fc2012-11-20 19:50:46 -0800895 Clobber(cUnit, infoLo->reg);
896 FreeTemp(cUnit, infoLo->reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700897 if (infoLo->pair)
buzbee52a77fc2012-11-20 19:50:46 -0800898 Clobber(cUnit, infoLo->partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 }
900 if (infoHi) {
buzbee52a77fc2012-11-20 19:50:46 -0800901 Clobber(cUnit, infoHi->reg);
902 FreeTemp(cUnit, infoHi->reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700903 if (infoHi->pair)
buzbee52a77fc2012-11-20 19:50:46 -0800904 Clobber(cUnit, infoHi->partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 }
906 }
907 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700908}
909
buzbeeed3e9302011-09-23 17:34:19 -0700910
911/* For use in cases we don't know (or care) width */
buzbee52a77fc2012-11-20 19:50:46 -0800912extern RegLocation UpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700913{
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 if (loc.wide)
buzbee52a77fc2012-11-20 19:50:46 -0800915 return UpdateLocWide(cUnit, loc);
Bill Buzbeea114add2012-05-03 15:00:40 -0700916 else
buzbee52a77fc2012-11-20 19:50:46 -0800917 return UpdateLoc(cUnit, loc);
buzbeeed3e9302011-09-23 17:34:19 -0700918}
919
buzbee52a77fc2012-11-20 19:50:46 -0800920RegLocation EvalLocWide(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700921 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700922{
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 DCHECK(loc.wide);
924 int newRegs;
925 int lowReg;
926 int highReg;
buzbee67bf8852011-08-17 17:51:35 -0700927
buzbee52a77fc2012-11-20 19:50:46 -0800928 loc = UpdateLocWide(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700929
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 /* If already in registers, we can assume proper form. Right reg class? */
931 if (loc.location == kLocPhysReg) {
buzbee52a77fc2012-11-20 19:50:46 -0800932 DCHECK_EQ(IsFpReg(loc.lowReg), IsFpReg(loc.highReg));
933 DCHECK(!IsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
934 if (!RegClassMatches(regClass, loc.lowReg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700935 /* Wrong register class. Reallocate and copy */
buzbee52a77fc2012-11-20 19:50:46 -0800936 newRegs = AllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbeea114add2012-05-03 15:00:40 -0700937 lowReg = newRegs & 0xff;
938 highReg = (newRegs >> 8) & 0xff;
buzbee52a77fc2012-11-20 19:50:46 -0800939 OpRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
buzbeeeaf09bc2012-11-15 14:51:41 -0800940 loc.highReg);
buzbee52a77fc2012-11-20 19:50:46 -0800941 CopyRegInfo(cUnit, lowReg, loc.lowReg);
942 CopyRegInfo(cUnit, highReg, loc.highReg);
943 Clobber(cUnit, loc.lowReg);
944 Clobber(cUnit, loc.highReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700945 loc.lowReg = lowReg;
946 loc.highReg = highReg;
buzbee52a77fc2012-11-20 19:50:46 -0800947 MarkPair(cUnit, loc.lowReg, loc.highReg);
948 DCHECK(!IsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700949 }
buzbee67bf8852011-08-17 17:51:35 -0700950 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 }
952
953 DCHECK_NE(loc.sRegLow, INVALID_SREG);
954 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
955
buzbee52a77fc2012-11-20 19:50:46 -0800956 newRegs = AllocTypedTempPair(cUnit, loc.fp, regClass);
Bill Buzbeea114add2012-05-03 15:00:40 -0700957 loc.lowReg = newRegs & 0xff;
958 loc.highReg = (newRegs >> 8) & 0xff;
959
buzbee52a77fc2012-11-20 19:50:46 -0800960 MarkPair(cUnit, loc.lowReg, loc.highReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700961 if (update) {
962 loc.location = kLocPhysReg;
buzbee52a77fc2012-11-20 19:50:46 -0800963 MarkLive(cUnit, loc.lowReg, loc.sRegLow);
964 MarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
Bill Buzbeea114add2012-05-03 15:00:40 -0700965 }
buzbee52a77fc2012-11-20 19:50:46 -0800966 DCHECK(!IsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700967 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700968}
969
buzbee52a77fc2012-11-20 19:50:46 -0800970extern RegLocation EvalLoc(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700972{
Bill Buzbeea114add2012-05-03 15:00:40 -0700973 int newReg;
buzbee67bf8852011-08-17 17:51:35 -0700974
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 if (loc.wide)
buzbee52a77fc2012-11-20 19:50:46 -0800976 return EvalLocWide(cUnit, loc, regClass, update);
buzbee67bf8852011-08-17 17:51:35 -0700977
buzbee52a77fc2012-11-20 19:50:46 -0800978 loc = UpdateLoc(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700979
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 if (loc.location == kLocPhysReg) {
buzbee52a77fc2012-11-20 19:50:46 -0800981 if (!RegClassMatches(regClass, loc.lowReg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700982 /* Wrong register class. Realloc, copy and transfer ownership */
buzbee52a77fc2012-11-20 19:50:46 -0800983 newReg = AllocTypedTemp(cUnit, loc.fp, regClass);
984 OpRegCopy(cUnit, newReg, loc.lowReg);
985 CopyRegInfo(cUnit, newReg, loc.lowReg);
986 Clobber(cUnit, loc.lowReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700987 loc.lowReg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700988 }
989 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700990 }
991
992 DCHECK_NE(loc.sRegLow, INVALID_SREG);
993
buzbee52a77fc2012-11-20 19:50:46 -0800994 newReg = AllocTypedTemp(cUnit, loc.fp, regClass);
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 loc.lowReg = newReg;
996
997 if (update) {
998 loc.location = kLocPhysReg;
buzbee52a77fc2012-11-20 19:50:46 -0800999 MarkLive(cUnit, loc.lowReg, loc.sRegLow);
Bill Buzbeea114add2012-05-03 15:00:40 -07001000 }
1001 return loc;
buzbee67bf8852011-08-17 17:51:35 -07001002}
1003
buzbee52a77fc2012-11-20 19:50:46 -08001004extern RegLocation GetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
buzbee67bf8852011-08-17 17:51:35 -07001005{
buzbee15bf9802012-06-12 17:49:27 -07001006 DCHECK(num < mir->ssaRep->numUses);
1007 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbee15bf9802012-06-12 17:49:27 -07001008 return res;
1009}
buzbeeeaf09bc2012-11-15 14:51:41 -08001010
buzbee52a77fc2012-11-20 19:50:46 -08001011extern RegLocation GetRawDest(CompilationUnit* cUnit, MIR* mir)
buzbee15bf9802012-06-12 17:49:27 -07001012{
Elliott Hughes74847412012-06-20 18:10:21 -07001013 DCHECK_GT(mir->ssaRep->numDefs, 0);
buzbee15bf9802012-06-12 17:49:27 -07001014 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[0]];
buzbee15bf9802012-06-12 17:49:27 -07001015 return res;
1016}
buzbeeeaf09bc2012-11-15 14:51:41 -08001017
buzbee52a77fc2012-11-20 19:50:46 -08001018extern RegLocation GetDest(CompilationUnit* cUnit, MIR* mir)
buzbee15bf9802012-06-12 17:49:27 -07001019{
buzbee52a77fc2012-11-20 19:50:46 -08001020 RegLocation res = GetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001021 DCHECK(!res.wide);
1022 return res;
buzbee67bf8852011-08-17 17:51:35 -07001023}
buzbeeeaf09bc2012-11-15 14:51:41 -08001024
buzbee52a77fc2012-11-20 19:50:46 -08001025extern RegLocation GetSrc(CompilationUnit* cUnit, MIR* mir, int num)
buzbee67bf8852011-08-17 17:51:35 -07001026{
buzbee52a77fc2012-11-20 19:50:46 -08001027 RegLocation res = GetRawSrc(cUnit, mir, num);
Bill Buzbeea114add2012-05-03 15:00:40 -07001028 DCHECK(!res.wide);
1029 return res;
buzbeee9a72f62011-09-04 17:59:07 -07001030}
buzbeeeaf09bc2012-11-15 14:51:41 -08001031
buzbee52a77fc2012-11-20 19:50:46 -08001032extern RegLocation GetDestWide(CompilationUnit* cUnit, MIR* mir)
buzbeee9a72f62011-09-04 17:59:07 -07001033{
buzbee52a77fc2012-11-20 19:50:46 -08001034 RegLocation res = GetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001035 DCHECK(res.wide);
1036 return res;
buzbee67bf8852011-08-17 17:51:35 -07001037}
1038
buzbee52a77fc2012-11-20 19:50:46 -08001039extern RegLocation GetSrcWide(CompilationUnit* cUnit, MIR* mir,
buzbee15bf9802012-06-12 17:49:27 -07001040 int low)
buzbee67bf8852011-08-17 17:51:35 -07001041{
buzbee52a77fc2012-11-20 19:50:46 -08001042 RegLocation res = GetRawSrc(cUnit, mir, low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001043 DCHECK(res.wide);
1044 return res;
buzbee67bf8852011-08-17 17:51:35 -07001045}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001046
buzbeee3acd072012-02-25 17:03:10 -08001047/* USE SSA names to count references of base Dalvik vRegs. */
buzbee52a77fc2012-11-20 19:50:46 -08001048void CountRefs(CompilationUnit *cUnit, BasicBlock* bb,
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001050{
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
1052 !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
1053 (bb->blockType == kDalvikByteCode))) {
1054 return;
1055 }
1056 for (int i = 0; i < cUnit->numSSARegs;) {
1057 RegLocation loc = cUnit->regLocation[i];
1058 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
1059 int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
1060 if (loc.defined) {
1061 counts[pMapIdx].count += cUnit->useCounts.elemList[i];
buzbee239c4e72012-03-16 08:42:29 -07001062 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001063 if (loc.wide) {
1064 if (loc.defined) {
1065 if (loc.fp) {
1066 counts[pMapIdx].doubleStart = true;
1067 counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
buzbee239c4e72012-03-16 08:42:29 -07001068 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001069 }
1070 i += 2;
1071 } else {
1072 i++;
buzbeee3acd072012-02-25 17:03:10 -08001073 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001074 }
buzbeee3acd072012-02-25 17:03:10 -08001075}
1076
1077/* qsort callback function, sort descending */
buzbee52a77fc2012-11-20 19:50:46 -08001078int SortCounts(const void *val1, const void *val2)
buzbeee3acd072012-02-25 17:03:10 -08001079{
buzbeecbd6d442012-11-17 14:11:25 -08001080 const RefCounts* op1 = reinterpret_cast<const RefCounts*>(val1);
1081 const RefCounts* op2 = reinterpret_cast<const RefCounts*>(val2);
Bill Buzbeea114add2012-05-03 15:00:40 -07001082 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
buzbeee3acd072012-02-25 17:03:10 -08001083}
1084
buzbee52a77fc2012-11-20 19:50:46 -08001085void DumpCounts(const RefCounts* arr, int size, const char* msg)
buzbeee3acd072012-02-25 17:03:10 -08001086{
Bill Buzbeea114add2012-05-03 15:00:40 -07001087 LOG(INFO) << msg;
1088 for (int i = 0; i < size; i++) {
1089 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1090 }
buzbeee3acd072012-02-25 17:03:10 -08001091}
1092
1093/*
1094 * Note: some portions of this code required even if the kPromoteRegs
1095 * optimization is disabled.
1096 */
buzbee52a77fc2012-11-20 19:50:46 -08001097extern void DoPromotion(CompilationUnit* cUnit)
buzbeee3acd072012-02-25 17:03:10 -08001098{
Bill Buzbeea114add2012-05-03 15:00:40 -07001099 int regBias = cUnit->numCompilerTemps + 1;
1100 int dalvikRegs = cUnit->numDalvikRegisters;
1101 int numRegs = dalvikRegs + regBias;
1102 const int promotionThreshold = 2;
buzbeee3acd072012-02-25 17:03:10 -08001103
Bill Buzbeea114add2012-05-03 15:00:40 -07001104 // Allow target code to add any special registers
buzbee52a77fc2012-11-20 19:50:46 -08001105 AdjustSpillMask(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001106
Bill Buzbeea114add2012-05-03 15:00:40 -07001107 /*
1108 * Simple register promotion. Just do a static count of the uses
1109 * of Dalvik registers. Note that we examine the SSA names, but
1110 * count based on original Dalvik register name. Count refs
1111 * separately based on type in order to give allocation
1112 * preference to fp doubles - which must be allocated sequential
1113 * physical single fp registers started with an even-numbered
1114 * reg.
1115 * TUNING: replace with linear scan once we have the ability
1116 * to describe register live ranges for GC.
1117 */
buzbee52a77fc2012-11-20 19:50:46 -08001118 RefCounts *coreRegs = static_cast<RefCounts*>(NewMem(cUnit, sizeof(RefCounts) * numRegs,
buzbeecbd6d442012-11-17 14:11:25 -08001119 true, kAllocRegAlloc));
buzbee52a77fc2012-11-20 19:50:46 -08001120 RefCounts *FpRegs = static_cast<RefCounts *>(NewMem(cUnit, sizeof(RefCounts) * numRegs,
buzbeecbd6d442012-11-17 14:11:25 -08001121 true, kAllocRegAlloc));
Bill Buzbeea114add2012-05-03 15:00:40 -07001122 // Set ssa names for original Dalvik registers
1123 for (int i = 0; i < dalvikRegs; i++) {
buzbee52a77fc2012-11-20 19:50:46 -08001124 coreRegs[i].sReg = FpRegs[i].sReg = i;
Bill Buzbeea114add2012-05-03 15:00:40 -07001125 }
1126 // Set ssa name for Method*
1127 coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
buzbee52a77fc2012-11-20 19:50:46 -08001128 FpRegs[dalvikRegs].sReg = cUnit->methodSReg; // For consistecy
Bill Buzbeea114add2012-05-03 15:00:40 -07001129 // Set ssa names for compilerTemps
1130 for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
buzbeecbd6d442012-11-17 14:11:25 -08001131 CompilerTemp* ct = reinterpret_cast<CompilerTemp*>(cUnit->compilerTemps.elemList[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001132 coreRegs[dalvikRegs + i].sReg = ct->sReg;
buzbee52a77fc2012-11-20 19:50:46 -08001133 FpRegs[dalvikRegs + i].sReg = ct->sReg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001134 }
1135
1136 GrowableListIterator iterator;
buzbee52a77fc2012-11-20 19:50:46 -08001137 GrowableListIteratorInit(&cUnit->blockList, &iterator);
Bill Buzbeea114add2012-05-03 15:00:40 -07001138 while (true) {
1139 BasicBlock* bb;
buzbee52a77fc2012-11-20 19:50:46 -08001140 bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -07001141 if (bb == NULL) break;
buzbee52a77fc2012-11-20 19:50:46 -08001142 CountRefs(cUnit, bb, coreRegs, FpRegs);
Bill Buzbeea114add2012-05-03 15:00:40 -07001143 }
1144
1145 /*
1146 * Ideally, we'd allocate doubles starting with an even-numbered
1147 * register. Bias the counts to try to allocate any vreg that's
1148 * used as the start of a pair first.
1149 */
1150 for (int i = 0; i < numRegs; i++) {
buzbee52a77fc2012-11-20 19:50:46 -08001151 if (FpRegs[i].doubleStart) {
1152 FpRegs[i].count *= 2;
buzbeee3acd072012-02-25 17:03:10 -08001153 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001154 }
1155
1156 // Sort the count arrays
buzbee52a77fc2012-11-20 19:50:46 -08001157 qsort(coreRegs, numRegs, sizeof(RefCounts), SortCounts);
1158 qsort(FpRegs, numRegs, sizeof(RefCounts), SortCounts);
Bill Buzbeea114add2012-05-03 15:00:40 -07001159
1160 if (cUnit->printMe) {
buzbee52a77fc2012-11-20 19:50:46 -08001161 DumpCounts(coreRegs, numRegs, "Core regs after sort");
1162 DumpCounts(FpRegs, numRegs, "Fp regs after sort");
Bill Buzbeea114add2012-05-03 15:00:40 -07001163 }
1164
1165 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
buzbee52a77fc2012-11-20 19:50:46 -08001166 // Promote FpRegs
Bill Buzbeea114add2012-05-03 15:00:40 -07001167 for (int i = 0; (i < numRegs) &&
buzbee52a77fc2012-11-20 19:50:46 -08001168 (FpRegs[i].count >= promotionThreshold ); i++) {
1169 int pMapIdx = SRegToPMap(cUnit, FpRegs[i].sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -07001170 if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
buzbee52a77fc2012-11-20 19:50:46 -08001171 int reg = AllocPreservedFPReg(cUnit, FpRegs[i].sReg,
1172 FpRegs[i].doubleStart);
Bill Buzbeea114add2012-05-03 15:00:40 -07001173 if (reg < 0) {
1174 break; // No more left
1175 }
1176 }
buzbee239c4e72012-03-16 08:42:29 -07001177 }
buzbee9c044ce2012-03-18 13:24:07 -07001178
Bill Buzbeea114add2012-05-03 15:00:40 -07001179 // Promote core regs
1180 for (int i = 0; (i < numRegs) &&
1181 (coreRegs[i].count > promotionThreshold); i++) {
1182 int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
1183 if (cUnit->promotionMap[pMapIdx].coreLocation !=
1184 kLocPhysReg) {
buzbee52a77fc2012-11-20 19:50:46 -08001185 int reg = AllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -07001186 if (reg < 0) {
1187 break; // No more left
1188 }
1189 }
buzbeee3acd072012-02-25 17:03:10 -08001190 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001191 } else if (cUnit->qdMode) {
buzbee52a77fc2012-11-20 19:50:46 -08001192 AllocPreservedCoreReg(cUnit, cUnit->methodSReg);
buzbeee3acd072012-02-25 17:03:10 -08001193 for (int i = 0; i < numRegs; i++) {
buzbee52a77fc2012-11-20 19:50:46 -08001194 int reg = AllocPreservedCoreReg(cUnit, i);
Bill Buzbeea114add2012-05-03 15:00:40 -07001195 if (reg < 0) {
1196 break; // No more left
1197 }
buzbeee3acd072012-02-25 17:03:10 -08001198 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001199 }
buzbeee3acd072012-02-25 17:03:10 -08001200
buzbeee3acd072012-02-25 17:03:10 -08001201
Bill Buzbeea114add2012-05-03 15:00:40 -07001202 // Now, update SSA names to new home locations
1203 for (int i = 0; i < cUnit->numSSARegs; i++) {
1204 RegLocation *curr = &cUnit->regLocation[i];
1205 int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
1206 if (!curr->wide) {
1207 if (curr->fp) {
1208 if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
1209 curr->location = kLocPhysReg;
buzbee52a77fc2012-11-20 19:50:46 -08001210 curr->lowReg = cUnit->promotionMap[pMapIdx].FpReg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001211 curr->home = true;
1212 }
1213 } else {
1214 if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
1215 curr->location = kLocPhysReg;
1216 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1217 curr->home = true;
1218 }
1219 }
1220 curr->highReg = INVALID_REG;
1221 } else {
1222 if (curr->highWord) {
1223 continue;
1224 }
1225 if (curr->fp) {
1226 if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
1227 (cUnit->promotionMap[pMapIdx+1].fpLocation ==
1228 kLocPhysReg)) {
buzbee52a77fc2012-11-20 19:50:46 -08001229 int lowReg = cUnit->promotionMap[pMapIdx].FpReg;
1230 int highReg = cUnit->promotionMap[pMapIdx+1].FpReg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001231 // Doubles require pair of singles starting at even reg
1232 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1233 curr->location = kLocPhysReg;
1234 curr->lowReg = lowReg;
1235 curr->highReg = highReg;
1236 curr->home = true;
1237 }
1238 }
1239 } else {
1240 if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
1241 && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
1242 kLocPhysReg)) {
1243 curr->location = kLocPhysReg;
1244 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1245 curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
1246 curr->home = true;
1247 }
1248 }
buzbeee3acd072012-02-25 17:03:10 -08001249 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001250 }
buzbeeca7a5e42012-08-20 11:12:18 -07001251 if (cUnit->printMe) {
buzbee52a77fc2012-11-20 19:50:46 -08001252 DumpPromotionMap(cUnit);
buzbeeca7a5e42012-08-20 11:12:18 -07001253 }
buzbeee3acd072012-02-25 17:03:10 -08001254}
1255
1256/* Returns sp-relative offset in bytes for a VReg */
buzbee52a77fc2012-11-20 19:50:46 -08001257extern int VRegOffset(CompilationUnit* cUnit, int vReg)
buzbeee3acd072012-02-25 17:03:10 -08001258{
Ian Rogers0399dde2012-06-06 17:09:28 -07001259 return StackVisitor::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1260 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001261}
1262
1263/* Returns sp-relative offset in bytes for a SReg */
buzbee52a77fc2012-11-20 19:50:46 -08001264extern int SRegOffset(CompilationUnit* cUnit, int sReg)
buzbeee3acd072012-02-25 17:03:10 -08001265{
buzbee52a77fc2012-11-20 19:50:46 -08001266 return VRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001267}
1268
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001269} // namespace art