blob: e2f2cd683bb47a2f9e24c21625b429a368ff43e8 [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
17/*
18 * This file contains register alloction support and is intended to be
19 * included by:
20 *
21 * Codegen-$(TARGET_ARCH_VARIANT).c
22 *
23 */
24
25#include "../CompilerUtility.h"
26#include "../CompilerIR.h"
27#include "../Dataflow.h"
28#include "Ralloc.h"
29
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080030namespace art {
31
buzbee67bf8852011-08-17 17:51:35 -070032#define SREG(c, s) ((c)->regLocation[(s)].sRegLow)
33/*
34 * Get the "real" sreg number associated with an sReg slot. In general,
35 * sReg values passed through codegen are the SSA names created by
36 * dataflow analysis and refer to slot numbers in the cUnit->regLocation
37 * array. However, renaming is accomplished by simply replacing RegLocation
38 * entries in the cUnit->reglocation[] array. Therefore, when location
39 * records for operands are first created, we need to ask the locRecord
40 * identified by the dataflow pass what it's new name is.
41 */
42
43/*
44 * Free all allocated temps in the temp pools. Note that this does
45 * not affect the "liveness" of a temp register, which will stay
46 * live until it is either explicitly killed or reallocated.
47 */
48extern void oatResetRegPool(CompilationUnit* cUnit)
49{
Bill Buzbeea114add2012-05-03 15:00:40 -070050 int i;
51 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
52 if (cUnit->regPool->coreRegs[i].isTemp)
53 cUnit->regPool->coreRegs[i].inUse = false;
54 }
55 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
56 if (cUnit->regPool->FPRegs[i].isTemp)
57 cUnit->regPool->FPRegs[i].inUse = false;
58 }
buzbee67bf8852011-08-17 17:51:35 -070059}
60
buzbeee3acd072012-02-25 17:03:10 -080061 /*
62 * Set up temp & preserved register pools specialized by target.
63 * Note: numRegs may be zero.
64 */
buzbee67bf8852011-08-17 17:51:35 -070065extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
66{
Bill Buzbeea114add2012-05-03 15:00:40 -070067 int i;
68 for (i=0; i < num; i++) {
69 regs[i].reg = regNums[i];
70 regs[i].inUse = false;
71 regs[i].isTemp = false;
72 regs[i].pair = false;
73 regs[i].live = false;
74 regs[i].dirty = false;
75 regs[i].sReg = INVALID_SREG;
76 }
buzbee67bf8852011-08-17 17:51:35 -070077}
78
buzbee31a4a6f2012-02-28 15:36:15 -080079void dumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070080{
Bill Buzbeea114add2012-05-03 15:00:40 -070081 LOG(INFO) << "================================================";
82 for (int i = 0; i < numRegs; i++) {
83 LOG(INFO) << StringPrintf(
84 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
85 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
86 p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
87 (int)p[i].defEnd);
88 }
89 LOG(INFO) << "================================================";
buzbee67bf8852011-08-17 17:51:35 -070090}
91
buzbee6181f792011-09-29 11:14:04 -070092void oatDumpCoreRegPool(CompilationUnit* cUnit)
93{
Bill Buzbeea114add2012-05-03 15:00:40 -070094 dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
buzbee6181f792011-09-29 11:14:04 -070095}
96
97void oatDumpFpRegPool(CompilationUnit* cUnit)
98{
Bill Buzbeea114add2012-05-03 15:00:40 -070099 dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
buzbee6181f792011-09-29 11:14:04 -0700100}
101
buzbee67bf8852011-08-17 17:51:35 -0700102/* Mark a temp register as dead. Does not affect allocation state. */
buzbee5abfa3e2012-01-31 17:01:43 -0800103static inline void clobberBody(CompilationUnit *cUnit, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700104{
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 if (p->isTemp) {
106 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
107 p->live = false;
108 p->sReg = INVALID_SREG;
109 p->defStart = NULL;
110 p->defEnd = NULL;
111 if (p->pair) {
112 p->pair = false;
113 oatClobber(cUnit, p->partner);
buzbee67bf8852011-08-17 17:51:35 -0700114 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 }
buzbee67bf8852011-08-17 17:51:35 -0700116}
117
buzbee5abfa3e2012-01-31 17:01:43 -0800118/* Mark a temp register as dead. Does not affect allocation state. */
119void oatClobber(CompilationUnit* cUnit, int reg)
120{
Bill Buzbeea114add2012-05-03 15:00:40 -0700121 clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800122}
123
buzbee31a4a6f2012-02-28 15:36:15 -0800124void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700125{
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 int i;
127 for (i=0; i< numRegs; i++) {
128 if (p[i].sReg == sReg) {
129 if (p[i].isTemp) {
130 p[i].live = false;
131 }
132 p[i].defStart = NULL;
133 p[i].defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700134 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 }
buzbee67bf8852011-08-17 17:51:35 -0700136}
137
138/* Clobber any temp associated with an sReg. Could be in either class */
139extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
140{
buzbee3d661942012-03-14 17:37:27 -0700141#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 /* Reset live temp tracking sanity checker */
143 if (sReg == cUnit->liveSReg) {
144 cUnit->liveSReg = INVALID_SREG;
145 }
buzbee3d661942012-03-14 17:37:27 -0700146#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700147 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs, sReg);
148 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700149}
150
buzbee9c044ce2012-03-18 13:24:07 -0700151/*
152 * SSA names associated with the initial definitions of Dalvik
153 * registers are the same as the Dalvik register number (and
154 * thus take the same position in the promotionMap. However,
155 * the special Method* and compiler temp resisters use negative
Elliott Hughesbdf6c3d2012-03-20 13:43:53 -0700156 * vReg numbers to distinguish them and can have an arbitrary
buzbee9c044ce2012-03-18 13:24:07 -0700157 * ssa name (above the last original Dalvik register). This function
158 * maps SSA names to positions in the promotionMap array.
159 */
160int SRegToPMap(CompilationUnit* cUnit, int sReg)
buzbeee1965672012-03-11 18:39:19 -0700161{
Bill Buzbeea114add2012-05-03 15:00:40 -0700162 DCHECK_LT(sReg, cUnit->numSSARegs);
163 DCHECK_GE(sReg, 0);
164 int vReg = SRegToVReg(cUnit, sReg);
165 if (vReg >= 0) {
166 DCHECK_LT(vReg, cUnit->numDalvikRegisters);
167 return vReg;
168 } else {
169 int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
170 DCHECK_LE(pos, cUnit->numCompilerTemps);
171 return cUnit->numDalvikRegisters + pos;
172 }
buzbeee1965672012-03-11 18:39:19 -0700173}
174
buzbee67bf8852011-08-17 17:51:35 -0700175/* Reserve a callee-save register. Return -1 if none available */
176extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
177{
Bill Buzbeea114add2012-05-03 15:00:40 -0700178 int res = -1;
179 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
180 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
181 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
182 int vReg = SRegToVReg(cUnit, sReg);
183 int pMapIdx = SRegToPMap(cUnit, sReg);
184 res = coreRegs[i].reg;
185 coreRegs[i].inUse = true;
186 cUnit->coreSpillMask |= (1 << res);
187 cUnit->coreVmapTable.push_back(vReg);
188 cUnit->numCoreSpills++;
189 cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
190 cUnit->promotionMap[pMapIdx].coreReg = res;
191 break;
buzbee67bf8852011-08-17 17:51:35 -0700192 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 }
194 return res;
buzbee67bf8852011-08-17 17:51:35 -0700195}
196
197/*
198 * Reserve a callee-save fp single register. Try to fullfill request for
199 * even/odd allocation, but go ahead and allocate anything if not
200 * available. If nothing's available, return -1.
201 */
buzbee31a4a6f2012-02-28 15:36:15 -0800202int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700203{
Bill Buzbeea114add2012-05-03 15:00:40 -0700204 int res = -1;
205 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
206 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
207 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
208 ((FPRegs[i].reg & 0x1) == 0) == even) {
209 int vReg = SRegToVReg(cUnit, sReg);
210 int pMapIdx = SRegToPMap(cUnit, sReg);
211 res = FPRegs[i].reg;
212 FPRegs[i].inUse = true;
213 oatMarkPreservedSingle(cUnit, vReg, res);
214 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
215 cUnit->promotionMap[pMapIdx].fpReg = res;
216 break;
buzbee67bf8852011-08-17 17:51:35 -0700217 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 }
219 return res;
buzbee67bf8852011-08-17 17:51:35 -0700220}
221
222/*
223 * Somewhat messy code here. We want to allocate a pair of contiguous
224 * physical single-precision floating point registers starting with
225 * an even numbered reg. It is possible that the paired sReg (sReg+1)
226 * has already been allocated - try to fit if possible. Fail to
227 * allocate if we can't meet the requirements for the pair of
228 * sReg<=sX[even] & (sReg+1)<= sX+1.
229 */
buzbee31a4a6f2012-02-28 15:36:15 -0800230int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700231{
Bill Buzbeea114add2012-05-03 15:00:40 -0700232 int res = -1; // Assume failure
233 int vReg = SRegToVReg(cUnit, sReg);
234 int pMapIdx = SRegToPMap(cUnit, sReg);
235 if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
236 // Upper reg is already allocated. Can we fit?
237 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
238 if ((highReg & 1) == 0) {
239 // High reg is even - fail.
240 return res;
241 }
242 // Is the low reg of the pair free?
243 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
244 if (p->inUse || p->isTemp) {
245 // Already allocated or not preserved - fail.
246 return res;
247 }
248 // OK - good to go.
249 res = p->reg;
250 p->inUse = true;
251 DCHECK_EQ((res & 1), 0);
252 oatMarkPreservedSingle(cUnit, vReg, res);
253 } else {
254 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
255 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
256 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
257 ((FPRegs[i].reg & 0x1) == 0x0) &&
258 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
259 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
260 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
261 res = FPRegs[i].reg;
262 FPRegs[i].inUse = true;
buzbee9c044ce2012-03-18 13:24:07 -0700263 oatMarkPreservedSingle(cUnit, vReg, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 FPRegs[i+1].inUse = true;
265 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
266 oatMarkPreservedSingle(cUnit, vReg+1, res+1);
267 break;
268 }
buzbee67bf8852011-08-17 17:51:35 -0700269 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 }
271 if (res != -1) {
272 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
273 cUnit->promotionMap[pMapIdx].fpReg = res;
274 cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
275 cUnit->promotionMap[pMapIdx+1].fpReg = res + 1;
276 }
277 return res;
buzbee67bf8852011-08-17 17:51:35 -0700278}
279
280
281/*
282 * Reserve a callee-save fp register. If this register can be used
283 * as the first of a double, attempt to allocate an even pair of fp
284 * single regs (but if can't still attempt to allocate a single, preferring
285 * first to allocate an odd register.
286 */
287extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
Bill Buzbeea114add2012-05-03 15:00:40 -0700288 bool doubleStart)
buzbee67bf8852011-08-17 17:51:35 -0700289{
Bill Buzbeea114add2012-05-03 15:00:40 -0700290 int res = -1;
291 if (doubleStart) {
292 res = allocPreservedDouble(cUnit, sReg);
293 }
294 if (res == -1) {
295 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
296 }
297 if (res == -1)
298 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
299 return res;
buzbee67bf8852011-08-17 17:51:35 -0700300}
301
buzbee31a4a6f2012-02-28 15:36:15 -0800302int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700303 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700304{
Bill Buzbeea114add2012-05-03 15:00:40 -0700305 int i;
306 int next = *nextTemp;
307 for (i=0; i< numRegs; i++) {
308 if (next >= numRegs)
309 next = 0;
310 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
311 oatClobber(cUnit, p[next].reg);
312 p[next].inUse = true;
313 p[next].pair = false;
314 *nextTemp = next + 1;
315 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700316 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700317 next++;
318 }
319 next = *nextTemp;
320 for (i=0; i< numRegs; i++) {
321 if (next >= numRegs)
322 next = 0;
323 if (p[next].isTemp && !p[next].inUse) {
324 oatClobber(cUnit, p[next].reg);
325 p[next].inUse = true;
326 p[next].pair = false;
327 *nextTemp = next + 1;
328 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700329 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700330 next++;
331 }
332 if (required) {
333 oatCodegenDump(cUnit);
334 dumpRegPool(cUnit->regPool->coreRegs,
335 cUnit->regPool->numCoreRegs);
336 LOG(FATAL) << "No free temp registers";
337 }
338 return -1; // No register available
buzbee67bf8852011-08-17 17:51:35 -0700339}
340
341//REDO: too many assumptions.
342extern int oatAllocTempDouble(CompilationUnit* cUnit)
343{
Bill Buzbeea114add2012-05-03 15:00:40 -0700344 RegisterInfo* p = cUnit->regPool->FPRegs;
345 int numRegs = cUnit->regPool->numFPRegs;
346 /* Start looking at an even reg */
347 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700348
Bill Buzbeea114add2012-05-03 15:00:40 -0700349 // First try to avoid allocating live registers
350 for (int i=0; i < numRegs; i+=2) {
351 if (next >= numRegs)
352 next = 0;
353 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
354 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
355 oatClobber(cUnit, p[next].reg);
356 oatClobber(cUnit, p[next+1].reg);
357 p[next].inUse = true;
358 p[next+1].inUse = true;
359 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
360 DCHECK_EQ((p[next].reg & 0x1), 0);
361 cUnit->regPool->nextFPReg = next + 2;
362 if (cUnit->regPool->nextFPReg >= numRegs) {
363 cUnit->regPool->nextFPReg = 0;
364 }
365 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700366 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 next += 2;
368 }
369 next = cUnit->regPool->nextFPReg & ~0x1;
buzbeea50638b2011-11-02 15:15:06 -0700370
Bill Buzbeea114add2012-05-03 15:00:40 -0700371 // No choice - find a pair and kill it.
372 for (int i=0; i < numRegs; i+=2) {
373 if (next >= numRegs)
374 next = 0;
375 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
376 !p[next+1].inUse) {
377 oatClobber(cUnit, p[next].reg);
378 oatClobber(cUnit, p[next+1].reg);
379 p[next].inUse = true;
380 p[next+1].inUse = true;
381 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
382 DCHECK_EQ((p[next].reg & 0x1), 0);
383 cUnit->regPool->nextFPReg = next + 2;
384 if (cUnit->regPool->nextFPReg >= numRegs) {
385 cUnit->regPool->nextFPReg = 0;
386 }
387 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700388 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700389 next += 2;
390 }
391 LOG(FATAL) << "No free temp registers (pair)";
392 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700393}
394
395/* Return a temp if one is available, -1 otherwise */
396extern int oatAllocFreeTemp(CompilationUnit* cUnit)
397{
Bill Buzbeea114add2012-05-03 15:00:40 -0700398 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
399 cUnit->regPool->numCoreRegs,
400 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700401}
402
403extern int oatAllocTemp(CompilationUnit* cUnit)
404{
Bill Buzbeea114add2012-05-03 15:00:40 -0700405 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
406 cUnit->regPool->numCoreRegs,
407 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700408}
409
410extern int oatAllocTempFloat(CompilationUnit* cUnit)
411{
Bill Buzbeea114add2012-05-03 15:00:40 -0700412 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
413 cUnit->regPool->numFPRegs,
414 &cUnit->regPool->nextFPReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700415}
416
buzbee31a4a6f2012-02-28 15:36:15 -0800417RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700418{
Bill Buzbeea114add2012-05-03 15:00:40 -0700419 int i;
420 if (sReg == -1)
buzbee67bf8852011-08-17 17:51:35 -0700421 return NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700422 for (i=0; i < numRegs; i++) {
423 if (p[i].live && (p[i].sReg == sReg)) {
424 if (p[i].isTemp)
425 p[i].inUse = true;
426 return &p[i];
427 }
428 }
429 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700430}
431
buzbee31a4a6f2012-02-28 15:36:15 -0800432RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700433{
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 RegisterInfo* res = NULL;
435 switch (regClass) {
436 case kAnyReg:
437 res = allocLiveBody(cUnit->regPool->FPRegs,
438 cUnit->regPool->numFPRegs, sReg);
439 if (res)
440 break;
441 /* Intentional fallthrough */
442 case kCoreReg:
443 res = allocLiveBody(cUnit->regPool->coreRegs,
444 cUnit->regPool->numCoreRegs, sReg);
445 break;
446 case kFPReg:
447 res = allocLiveBody(cUnit->regPool->FPRegs,
448 cUnit->regPool->numFPRegs, sReg);
449 break;
450 default:
451 LOG(FATAL) << "Invalid register type";
452 }
453 return res;
buzbee67bf8852011-08-17 17:51:35 -0700454}
455
456extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
457{
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 RegisterInfo* p = cUnit->regPool->coreRegs;
459 int numRegs = cUnit->regPool->numCoreRegs;
460 int i;
461 for (i=0; i< numRegs; i++) {
462 if (p[i].reg == reg) {
463 if (p[i].isTemp) {
464 p[i].inUse = false;
465 }
466 p[i].pair = false;
467 return;
buzbee67bf8852011-08-17 17:51:35 -0700468 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700469 }
470 p = cUnit->regPool->FPRegs;
471 numRegs = cUnit->regPool->numFPRegs;
472 for (i=0; i< numRegs; i++) {
473 if (p[i].reg == reg) {
474 if (p[i].isTemp) {
475 p[i].inUse = false;
476 }
477 p[i].pair = false;
478 return;
buzbee67bf8852011-08-17 17:51:35 -0700479 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700480 }
481 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700482}
483
484extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
485{
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 RegisterInfo* p = cUnit->regPool->coreRegs;
487 int numRegs = cUnit->regPool->numCoreRegs;
488 int i;
489 for (i=0; i< numRegs; i++) {
490 if (p[i].reg == reg) {
491 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700492 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700493 }
494 p = cUnit->regPool->FPRegs;
495 numRegs = cUnit->regPool->numFPRegs;
496 for (i=0; i< numRegs; i++) {
497 if (p[i].reg == reg) {
498 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700499 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 }
501 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700502}
503
504extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
505{
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
507 return (p->isTemp) ? p : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700508}
509
buzbeeb29e4d12011-09-26 15:05:48 -0700510extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
511{
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
513 return (p->isTemp) ? NULL : p;
buzbeeb29e4d12011-09-26 15:05:48 -0700514}
515
buzbee67bf8852011-08-17 17:51:35 -0700516extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
517{
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
519 return p->dirty;
buzbee67bf8852011-08-17 17:51:35 -0700520}
521
522/*
523 * Similar to oatAllocTemp(), but forces the allocation of a specific
524 * register. No check is made to see if the register was previously
525 * allocated. Use with caution.
526 */
527extern void oatLockTemp(CompilationUnit* cUnit, int reg)
528{
Bill Buzbeea114add2012-05-03 15:00:40 -0700529 RegisterInfo* p = cUnit->regPool->coreRegs;
530 int numRegs = cUnit->regPool->numCoreRegs;
531 int i;
532 for (i=0; i< numRegs; i++) {
533 if (p[i].reg == reg) {
534 DCHECK(p[i].isTemp);
535 p[i].inUse = true;
536 p[i].live = false;
537 return;
buzbee67bf8852011-08-17 17:51:35 -0700538 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700539 }
540 p = cUnit->regPool->FPRegs;
541 numRegs = cUnit->regPool->numFPRegs;
542 for (i=0; i< numRegs; i++) {
543 if (p[i].reg == reg) {
544 DCHECK(p[i].isTemp);
545 p[i].inUse = true;
546 p[i].live = false;
547 return;
buzbee67bf8852011-08-17 17:51:35 -0700548 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700549 }
550 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700551}
552
buzbee5abfa3e2012-01-31 17:01:43 -0800553static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700554{
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 p->defStart = NULL;
556 p->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700557}
558
buzbee5abfa3e2012-01-31 17:01:43 -0800559extern void oatResetDef(CompilationUnit* cUnit, int reg)
560{
Bill Buzbeea114add2012-05-03 15:00:40 -0700561 resetDefBody(oatGetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800562}
563
buzbee31a4a6f2012-02-28 15:36:15 -0800564void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 int sReg1, int sReg2)
buzbee67bf8852011-08-17 17:51:35 -0700566{
Bill Buzbeea114add2012-05-03 15:00:40 -0700567 if (start && finish) {
568 LIR *p;
569 DCHECK_EQ(sReg1, sReg2);
570 for (p = start; ;p = p->next) {
571 oatNopLIR(p);
572 if (p == finish)
573 break;
buzbee67bf8852011-08-17 17:51:35 -0700574 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 }
buzbee67bf8852011-08-17 17:51:35 -0700576}
577
578/*
579 * Mark the beginning and end LIR of a def sequence. Note that
580 * on entry start points to the LIR prior to the beginning of the
581 * sequence.
582 */
583extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700584 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700585{
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 DCHECK(!rl.wide);
587 DCHECK(start && start->next);
588 DCHECK(finish);
589 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
590 p->defStart = start->next;
591 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700592}
593
594/*
595 * Mark the beginning and end LIR of a def sequence. Note that
596 * on entry start points to the LIR prior to the beginning of the
597 * sequence.
598 */
599extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700600 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700601{
Bill Buzbeea114add2012-05-03 15:00:40 -0700602 DCHECK(rl.wide);
603 DCHECK(start && start->next);
604 DCHECK(finish);
605 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
606 oatResetDef(cUnit, rl.highReg); // Only track low of pair
607 p->defStart = start->next;
608 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700609}
610
buzbee31a4a6f2012-02-28 15:36:15 -0800611extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700612{
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 DCHECK(rl.wide);
614 if (rl.location == kLocPhysReg) {
615 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
616 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
617 if (infoLo->isTemp) {
618 infoLo->pair = false;
619 infoLo->defStart = NULL;
620 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700621 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 if (infoHi->isTemp) {
623 infoHi->pair = false;
624 infoHi->defStart = NULL;
625 infoHi->defEnd = NULL;
626 }
627 }
628 rl.wide = false;
629 return rl;
buzbee67bf8852011-08-17 17:51:35 -0700630}
631
632extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
633{
Bill Buzbeea114add2012-05-03 15:00:40 -0700634 DCHECK(!rl.wide);
635 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
636 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
637 DCHECK(!p->pair);
638 nullifyRange(cUnit, p->defStart, p->defEnd, p->sReg, rl.sRegLow);
639 }
640 oatResetDef(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700641}
642
643extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
644{
Bill Buzbeea114add2012-05-03 15:00:40 -0700645 DCHECK(rl.wide);
646 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
647 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
648 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
649 DCHECK(pLow->pair);
650 nullifyRange(cUnit, pLow->defStart, pLow->defEnd, pLow->sReg, rl.sRegLow);
651 }
652 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
653 DCHECK(pHigh->pair);
654 }
655 oatResetDef(cUnit, rl.lowReg);
656 oatResetDef(cUnit, rl.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700657}
658
659extern void oatResetDefTracking(CompilationUnit* cUnit)
660{
Bill Buzbeea114add2012-05-03 15:00:40 -0700661 int i;
662 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
663 resetDefBody(&cUnit->regPool->coreRegs[i]);
664 }
665 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
666 resetDefBody(&cUnit->regPool->FPRegs[i]);
667 }
buzbee67bf8852011-08-17 17:51:35 -0700668}
669
670extern void oatClobberAllRegs(CompilationUnit* cUnit)
671{
Bill Buzbeea114add2012-05-03 15:00:40 -0700672 int i;
673 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
674 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
675 }
676 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
677 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
678 }
buzbee67bf8852011-08-17 17:51:35 -0700679}
680
buzbee67bf8852011-08-17 17:51:35 -0700681// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800682void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
Bill Buzbeea114add2012-05-03 15:00:40 -0700683 int numRegs)
buzbee67bf8852011-08-17 17:51:35 -0700684{
Bill Buzbeea114add2012-05-03 15:00:40 -0700685 int i;
686 for (i=0; i < numRegs; i++) {
687 if (info[i].live && info[i].dirty) {
688 if (info[i].pair) {
689 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
690 } else {
691 oatFlushReg(cUnit, info[i].reg);
692 }
buzbee67bf8852011-08-17 17:51:35 -0700693 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700694 }
buzbee67bf8852011-08-17 17:51:35 -0700695}
696
697extern void oatFlushAllRegs(CompilationUnit* cUnit)
698{
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
700 cUnit->regPool->numCoreRegs);
701 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
702 cUnit->regPool->numFPRegs);
703 oatClobberAllRegs(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700704}
705
706
707//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800708bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700709{
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 if (regClass == kAnyReg) {
711 return true;
712 } else if (regClass == kCoreReg) {
713 return !oatIsFpReg(reg);
714 } else {
715 return oatIsFpReg(reg);
716 }
buzbee67bf8852011-08-17 17:51:35 -0700717}
718
719extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
720{
Bill Buzbeea114add2012-05-03 15:00:40 -0700721 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
722 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
723 return; /* already live */
724 } else if (sReg != INVALID_SREG) {
725 oatClobberSReg(cUnit, sReg);
726 if (info->isTemp) {
727 info->live = true;
buzbee67bf8852011-08-17 17:51:35 -0700728 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700729 } else {
730 /* Can't be live if no associated sReg */
731 DCHECK(info->isTemp);
732 info->live = false;
733 }
734 info->sReg = sReg;
buzbee67bf8852011-08-17 17:51:35 -0700735}
736
737extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
738{
Bill Buzbeea114add2012-05-03 15:00:40 -0700739 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
740 info->isTemp = true;
buzbee67bf8852011-08-17 17:51:35 -0700741}
742
buzbee9e0f9b02011-08-24 15:32:46 -0700743extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
744{
Bill Buzbeea114add2012-05-03 15:00:40 -0700745 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
746 info->isTemp = false;
buzbee9e0f9b02011-08-24 15:32:46 -0700747}
748
buzbee67bf8852011-08-17 17:51:35 -0700749extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
750{
Bill Buzbeea114add2012-05-03 15:00:40 -0700751 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
752 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
753 infoLo->pair = infoHi->pair = true;
754 infoLo->partner = highReg;
755 infoHi->partner = lowReg;
buzbee67bf8852011-08-17 17:51:35 -0700756}
757
758extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
759{
Bill Buzbeea114add2012-05-03 15:00:40 -0700760 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
761 info->dirty = false;
762 if (loc.wide) {
763 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700764 info->dirty = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700765 }
buzbee67bf8852011-08-17 17:51:35 -0700766}
767
768extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
769{
Bill Buzbeea114add2012-05-03 15:00:40 -0700770 if (loc.home) {
771 // If already home, can't be dirty
772 return;
773 }
774 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
775 info->dirty = true;
776 if (loc.wide) {
777 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700778 info->dirty = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700779 }
buzbee67bf8852011-08-17 17:51:35 -0700780}
781
782extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
783{
Bill Buzbeea114add2012-05-03 15:00:40 -0700784 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
785 info->inUse = true;
buzbee67bf8852011-08-17 17:51:35 -0700786}
787
buzbee31a4a6f2012-02-28 15:36:15 -0800788void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700789{
Bill Buzbeea114add2012-05-03 15:00:40 -0700790 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
791 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
792 // Target temp status must not change
793 bool isTemp = newInfo->isTemp;
794 *newInfo = *oldInfo;
795 // Restore target's temp status
796 newInfo->isTemp = isTemp;
797 newInfo->reg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700798}
799
800/*
801 * Return an updated location record with current in-register status.
802 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700803 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700804 * clobber both low and high.
805 * TUNING: clobbering both is a bit heavy-handed, but the alternative
806 * is a bit complex when dealing with FP regs. Examine code to see
807 * if it's worthwhile trying to be more clever here.
808 */
809
810extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
811{
Bill Buzbeea114add2012-05-03 15:00:40 -0700812 DCHECK(!loc.wide);
813 DCHECK(oatCheckCorePoolSanity(cUnit));
814 if (loc.location != kLocPhysReg) {
815 DCHECK((loc.location == kLocDalvikFrame) ||
816 (loc.location == kLocCompilerTemp));
817 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
818 if (infoLo) {
819 if (infoLo->pair) {
820 oatClobber(cUnit, infoLo->reg);
821 oatClobber(cUnit, infoLo->partner);
822 oatFreeTemp(cUnit, infoLo->reg);
823 } else {
824 loc.lowReg = infoLo->reg;
825 loc.location = kLocPhysReg;
826 }
buzbee67bf8852011-08-17 17:51:35 -0700827 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700828 }
buzbee67bf8852011-08-17 17:51:35 -0700829
Bill Buzbeea114add2012-05-03 15:00:40 -0700830 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700831}
832
buzbee6181f792011-09-29 11:14:04 -0700833bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
834{
835 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700836 if (cUnit->regPool->coreRegs[i].pair) {
837 static int myReg = cUnit->regPool->coreRegs[i].reg;
838 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
839 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
840 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
841 DCHECK(partner != NULL);
842 DCHECK(partner->pair);
843 DCHECK_EQ(myReg, partner->partner);
844 static int partnerSreg = partner->sReg;
845 if (mySreg == INVALID_SREG) {
846 DCHECK_EQ(partnerSreg, INVALID_SREG);
847 } else {
848 int diff = mySreg - partnerSreg;
849 DCHECK((diff == -1) || (diff == 1));
buzbee6181f792011-09-29 11:14:04 -0700850 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 }
852 if (!cUnit->regPool->coreRegs[i].live) {
853 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
854 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
855 }
buzbee6181f792011-09-29 11:14:04 -0700856 }
857 return true;
858}
859
buzbee67bf8852011-08-17 17:51:35 -0700860/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800861extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700862{
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 DCHECK(loc.wide);
864 DCHECK(oatCheckCorePoolSanity(cUnit));
865 if (loc.location != kLocPhysReg) {
866 DCHECK((loc.location == kLocDalvikFrame) ||
867 (loc.location == kLocCompilerTemp));
868 // Are the dalvik regs already live in physical registers?
869 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
870 RegisterInfo* infoHi = allocLive(cUnit,
871 oatSRegHi(loc.sRegLow), kAnyReg);
872 bool match = true;
873 match = match && (infoLo != NULL);
874 match = match && (infoHi != NULL);
875 // Are they both core or both FP?
876 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
877 // If a pair of floating point singles, are they properly aligned?
878 if (match && oatIsFpReg(infoLo->reg)) {
879 match &= ((infoLo->reg & 0x1) == 0);
880 match &= ((infoHi->reg - infoLo->reg) == 1);
buzbee67bf8852011-08-17 17:51:35 -0700881 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700882 // If previously used as a pair, it is the same pair?
883 if (match && (infoLo->pair || infoHi->pair)) {
884 match = (infoLo->pair == infoHi->pair);
885 match &= ((infoLo->reg == infoHi->partner) &&
886 (infoHi->reg == infoLo->partner));
887 }
888 if (match) {
889 // Can reuse - update the register usage info
890 loc.lowReg = infoLo->reg;
891 loc.highReg = infoHi->reg;
892 loc.location = kLocPhysReg;
893 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
894 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
895 return loc;
896 }
897 // Can't easily reuse - clobber and free any overlaps
898 if (infoLo) {
899 oatClobber(cUnit, infoLo->reg);
900 oatFreeTemp(cUnit, infoLo->reg);
901 if (infoLo->pair)
902 oatClobber(cUnit, infoLo->partner);
903 }
904 if (infoHi) {
905 oatClobber(cUnit, infoHi->reg);
906 oatFreeTemp(cUnit, infoHi->reg);
907 if (infoHi->pair)
908 oatClobber(cUnit, infoHi->partner);
909 }
910 }
911 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700912}
913
buzbeeed3e9302011-09-23 17:34:19 -0700914
915/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800916extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700917{
Bill Buzbeea114add2012-05-03 15:00:40 -0700918 if (loc.wide)
919 return oatUpdateLocWide(cUnit, loc);
920 else
921 return oatUpdateLoc(cUnit, loc);
buzbeeed3e9302011-09-23 17:34:19 -0700922}
923
buzbee31a4a6f2012-02-28 15:36:15 -0800924RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700925 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700926{
Bill Buzbeea114add2012-05-03 15:00:40 -0700927 DCHECK(loc.wide);
928 int newRegs;
929 int lowReg;
930 int highReg;
buzbee67bf8852011-08-17 17:51:35 -0700931
Bill Buzbeea114add2012-05-03 15:00:40 -0700932 loc = oatUpdateLocWide(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700933
Bill Buzbeea114add2012-05-03 15:00:40 -0700934 /* If already in registers, we can assume proper form. Right reg class? */
935 if (loc.location == kLocPhysReg) {
936 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
buzbeee3acd072012-02-25 17:03:10 -0800937 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700938 if (!regClassMatches(regClass, loc.lowReg)) {
939 /* Wrong register class. Reallocate and copy */
940 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
941 lowReg = newRegs & 0xff;
942 highReg = (newRegs >> 8) & 0xff;
943 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
944 loc.highReg);
945 copyRegInfo(cUnit, lowReg, loc.lowReg);
946 copyRegInfo(cUnit, highReg, loc.highReg);
947 oatClobber(cUnit, loc.lowReg);
948 oatClobber(cUnit, loc.highReg);
949 loc.lowReg = lowReg;
950 loc.highReg = highReg;
951 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
952 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
953 }
buzbee67bf8852011-08-17 17:51:35 -0700954 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700955 }
956
957 DCHECK_NE(loc.sRegLow, INVALID_SREG);
958 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
959
960 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
961 loc.lowReg = newRegs & 0xff;
962 loc.highReg = (newRegs >> 8) & 0xff;
963
964 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
965 if (update) {
966 loc.location = kLocPhysReg;
967 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
968 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
969 }
970 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
971 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700972}
973
974extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700976{
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 int newReg;
buzbee67bf8852011-08-17 17:51:35 -0700978
Bill Buzbeea114add2012-05-03 15:00:40 -0700979 if (loc.wide)
980 return evalLocWide(cUnit, loc, regClass, update);
buzbee67bf8852011-08-17 17:51:35 -0700981
Bill Buzbeea114add2012-05-03 15:00:40 -0700982 loc = oatUpdateLoc(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700983
Bill Buzbeea114add2012-05-03 15:00:40 -0700984 if (loc.location == kLocPhysReg) {
985 if (!regClassMatches(regClass, loc.lowReg)) {
986 /* Wrong register class. Realloc, copy and transfer ownership */
987 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
988 oatRegCopy(cUnit, newReg, loc.lowReg);
989 copyRegInfo(cUnit, newReg, loc.lowReg);
990 oatClobber(cUnit, loc.lowReg);
991 loc.lowReg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700992 }
993 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700994 }
995
996 DCHECK_NE(loc.sRegLow, INVALID_SREG);
997
998 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
999 loc.lowReg = newReg;
1000
1001 if (update) {
1002 loc.location = kLocPhysReg;
1003 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1004 }
1005 return loc;
buzbee67bf8852011-08-17 17:51:35 -07001006}
1007
buzbee15bf9802012-06-12 17:49:27 -07001008extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
buzbee67bf8852011-08-17 17:51:35 -07001009{
buzbee15bf9802012-06-12 17:49:27 -07001010 DCHECK(num < mir->ssaRep->numUses);
1011 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
1012 DCHECK(!res.wide || num < (mir->ssaRep->numUses - 1));
1013 return res;
1014}
1015extern RegLocation oatGetRawDest(CompilationUnit* cUnit, MIR* mir)
1016{
1017 DCHECK(mir->ssaRep->numDefs > 0);
1018 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[0]];
1019 DCHECK(!res.wide || mir->ssaRep->numDefs == 2);
1020 return res;
1021}
1022extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir)
1023{
1024 RegLocation res = oatGetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001025 DCHECK(!res.wide);
1026 return res;
buzbee67bf8852011-08-17 17:51:35 -07001027}
1028extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1029{
buzbee15bf9802012-06-12 17:49:27 -07001030 RegLocation res = oatGetRawSrc(cUnit, mir, num);
Bill Buzbeea114add2012-05-03 15:00:40 -07001031 DCHECK(!res.wide);
1032 return res;
buzbeee9a72f62011-09-04 17:59:07 -07001033}
buzbee15bf9802012-06-12 17:49:27 -07001034extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir)
buzbeee9a72f62011-09-04 17:59:07 -07001035{
buzbee15bf9802012-06-12 17:49:27 -07001036 RegLocation res = oatGetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001037 DCHECK(res.wide);
1038 return res;
buzbee67bf8852011-08-17 17:51:35 -07001039}
1040
1041extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
buzbee15bf9802012-06-12 17:49:27 -07001042 int low)
buzbee67bf8852011-08-17 17:51:35 -07001043{
buzbee15bf9802012-06-12 17:49:27 -07001044 RegLocation res = oatGetRawSrc(cUnit, mir, low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001045 DCHECK(res.wide);
1046 return res;
buzbee67bf8852011-08-17 17:51:35 -07001047}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001048
buzbeee3acd072012-02-25 17:03:10 -08001049/* USE SSA names to count references of base Dalvik vRegs. */
1050void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001052{
Bill Buzbeea114add2012-05-03 15:00:40 -07001053 if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
1054 !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
1055 (bb->blockType == kDalvikByteCode))) {
1056 return;
1057 }
1058 for (int i = 0; i < cUnit->numSSARegs;) {
1059 RegLocation loc = cUnit->regLocation[i];
1060 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
1061 int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
1062 if (loc.defined) {
1063 counts[pMapIdx].count += cUnit->useCounts.elemList[i];
buzbee239c4e72012-03-16 08:42:29 -07001064 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001065 if (loc.wide) {
1066 if (loc.defined) {
1067 if (loc.fp) {
1068 counts[pMapIdx].doubleStart = true;
1069 counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
buzbee239c4e72012-03-16 08:42:29 -07001070 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001071 }
1072 i += 2;
1073 } else {
1074 i++;
buzbeee3acd072012-02-25 17:03:10 -08001075 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001076 }
buzbeee3acd072012-02-25 17:03:10 -08001077}
1078
1079/* qsort callback function, sort descending */
1080int oatSortCounts(const void *val1, const void *val2)
1081{
Bill Buzbeea114add2012-05-03 15:00:40 -07001082 const RefCounts* op1 = (const RefCounts*)val1;
1083 const RefCounts* op2 = (const RefCounts*)val2;
1084 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
buzbeee3acd072012-02-25 17:03:10 -08001085}
1086
1087void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
1088{
Bill Buzbeea114add2012-05-03 15:00:40 -07001089 LOG(INFO) << msg;
1090 for (int i = 0; i < size; i++) {
1091 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1092 }
buzbeee3acd072012-02-25 17:03:10 -08001093}
1094
1095/*
1096 * Note: some portions of this code required even if the kPromoteRegs
1097 * optimization is disabled.
1098 */
1099extern void oatDoPromotion(CompilationUnit* cUnit)
1100{
Bill Buzbeea114add2012-05-03 15:00:40 -07001101 int regBias = cUnit->numCompilerTemps + 1;
1102 int dalvikRegs = cUnit->numDalvikRegisters;
1103 int numRegs = dalvikRegs + regBias;
1104 const int promotionThreshold = 2;
buzbeee3acd072012-02-25 17:03:10 -08001105
Bill Buzbeea114add2012-05-03 15:00:40 -07001106 // Allow target code to add any special registers
1107 oatAdjustSpillMask(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001108
Bill Buzbeea114add2012-05-03 15:00:40 -07001109 /*
1110 * Simple register promotion. Just do a static count of the uses
1111 * of Dalvik registers. Note that we examine the SSA names, but
1112 * count based on original Dalvik register name. Count refs
1113 * separately based on type in order to give allocation
1114 * preference to fp doubles - which must be allocated sequential
1115 * physical single fp registers started with an even-numbered
1116 * reg.
1117 * TUNING: replace with linear scan once we have the ability
1118 * to describe register live ranges for GC.
1119 */
1120 RefCounts *coreRegs = (RefCounts *)
1121 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1122 RefCounts *fpRegs = (RefCounts *)
1123 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1124 // Set ssa names for original Dalvik registers
1125 for (int i = 0; i < dalvikRegs; i++) {
1126 coreRegs[i].sReg = fpRegs[i].sReg = i;
1127 }
1128 // Set ssa name for Method*
1129 coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
1130 fpRegs[dalvikRegs].sReg = cUnit->methodSReg; // For consistecy
1131 // Set ssa names for compilerTemps
1132 for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
1133 CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
1134 coreRegs[dalvikRegs + i].sReg = ct->sReg;
1135 fpRegs[dalvikRegs + i].sReg = ct->sReg;
1136 }
1137
1138 GrowableListIterator iterator;
1139 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1140 while (true) {
1141 BasicBlock* bb;
1142 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
1143 if (bb == NULL) break;
1144 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1145 }
1146
1147 /*
1148 * Ideally, we'd allocate doubles starting with an even-numbered
1149 * register. Bias the counts to try to allocate any vreg that's
1150 * used as the start of a pair first.
1151 */
1152 for (int i = 0; i < numRegs; i++) {
1153 if (fpRegs[i].doubleStart) {
1154 fpRegs[i].count *= 2;
buzbeee3acd072012-02-25 17:03:10 -08001155 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001156 }
1157
1158 // Sort the count arrays
1159 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1160 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1161
1162 if (cUnit->printMe) {
1163 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1164 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1165 }
1166
1167 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1168 // Promote fpRegs
1169 for (int i = 0; (i < numRegs) &&
1170 (fpRegs[i].count >= promotionThreshold ); i++) {
1171 int pMapIdx = SRegToPMap(cUnit, fpRegs[i].sReg);
1172 if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
1173 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1174 fpRegs[i].doubleStart);
1175 if (reg < 0) {
1176 break; // No more left
1177 }
1178 }
buzbee239c4e72012-03-16 08:42:29 -07001179 }
buzbee9c044ce2012-03-18 13:24:07 -07001180
Bill Buzbeea114add2012-05-03 15:00:40 -07001181 // Promote core regs
1182 for (int i = 0; (i < numRegs) &&
1183 (coreRegs[i].count > promotionThreshold); i++) {
1184 int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
1185 if (cUnit->promotionMap[pMapIdx].coreLocation !=
1186 kLocPhysReg) {
1187 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1188 if (reg < 0) {
1189 break; // No more left
1190 }
1191 }
buzbeee3acd072012-02-25 17:03:10 -08001192 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001193 } else if (cUnit->qdMode) {
1194 oatAllocPreservedCoreReg(cUnit, cUnit->methodSReg);
buzbeee3acd072012-02-25 17:03:10 -08001195 for (int i = 0; i < numRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001196 int reg = oatAllocPreservedCoreReg(cUnit, i);
1197 if (reg < 0) {
1198 break; // No more left
1199 }
buzbeee3acd072012-02-25 17:03:10 -08001200 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001201 }
buzbeee3acd072012-02-25 17:03:10 -08001202
buzbeee3acd072012-02-25 17:03:10 -08001203
Bill Buzbeea114add2012-05-03 15:00:40 -07001204 // Now, update SSA names to new home locations
1205 for (int i = 0; i < cUnit->numSSARegs; i++) {
1206 RegLocation *curr = &cUnit->regLocation[i];
1207 int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
1208 if (!curr->wide) {
1209 if (curr->fp) {
1210 if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
1211 curr->location = kLocPhysReg;
1212 curr->lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1213 curr->home = true;
1214 }
1215 } else {
1216 if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
1217 curr->location = kLocPhysReg;
1218 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1219 curr->home = true;
1220 }
1221 }
1222 curr->highReg = INVALID_REG;
1223 } else {
1224 if (curr->highWord) {
1225 continue;
1226 }
1227 if (curr->fp) {
1228 if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
1229 (cUnit->promotionMap[pMapIdx+1].fpLocation ==
1230 kLocPhysReg)) {
1231 int lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1232 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
1233 // Doubles require pair of singles starting at even reg
1234 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1235 curr->location = kLocPhysReg;
1236 curr->lowReg = lowReg;
1237 curr->highReg = highReg;
1238 curr->home = true;
1239 }
1240 }
1241 } else {
1242 if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
1243 && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
1244 kLocPhysReg)) {
1245 curr->location = kLocPhysReg;
1246 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1247 curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
1248 curr->home = true;
1249 }
1250 }
buzbeee3acd072012-02-25 17:03:10 -08001251 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001252 }
buzbeee3acd072012-02-25 17:03:10 -08001253}
1254
1255/* Returns sp-relative offset in bytes for a VReg */
1256extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1257{
Bill Buzbeea114add2012-05-03 15:00:40 -07001258 return Frame::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1259 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001260}
1261
1262/* Returns sp-relative offset in bytes for a SReg */
1263extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1264{
Bill Buzbeea114add2012-05-03 15:00:40 -07001265 return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001266}
1267
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001268} // namespace art