blob: 8fa110a90d7abc3706cc71ac6e50029806f46117 [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/*
33 * Free all allocated temps in the temp pools. Note that this does
34 * not affect the "liveness" of a temp register, which will stay
35 * live until it is either explicitly killed or reallocated.
36 */
37extern void oatResetRegPool(CompilationUnit* cUnit)
38{
Bill Buzbeea114add2012-05-03 15:00:40 -070039 int i;
40 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
41 if (cUnit->regPool->coreRegs[i].isTemp)
42 cUnit->regPool->coreRegs[i].inUse = false;
43 }
44 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
45 if (cUnit->regPool->FPRegs[i].isTemp)
46 cUnit->regPool->FPRegs[i].inUse = false;
47 }
buzbee67bf8852011-08-17 17:51:35 -070048}
49
buzbeee3acd072012-02-25 17:03:10 -080050 /*
51 * Set up temp & preserved register pools specialized by target.
52 * Note: numRegs may be zero.
53 */
buzbee67bf8852011-08-17 17:51:35 -070054extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
55{
Bill Buzbeea114add2012-05-03 15:00:40 -070056 int i;
57 for (i=0; i < num; i++) {
58 regs[i].reg = regNums[i];
59 regs[i].inUse = false;
60 regs[i].isTemp = false;
61 regs[i].pair = false;
62 regs[i].live = false;
63 regs[i].dirty = false;
64 regs[i].sReg = INVALID_SREG;
65 }
buzbee67bf8852011-08-17 17:51:35 -070066}
67
buzbee31a4a6f2012-02-28 15:36:15 -080068void dumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070069{
Bill Buzbeea114add2012-05-03 15:00:40 -070070 LOG(INFO) << "================================================";
71 for (int i = 0; i < numRegs; i++) {
72 LOG(INFO) << StringPrintf(
73 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
74 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
75 p[i].live, p[i].dirty, p[i].sReg,(int)p[i].defStart,
76 (int)p[i].defEnd);
77 }
78 LOG(INFO) << "================================================";
buzbee67bf8852011-08-17 17:51:35 -070079}
80
buzbee6181f792011-09-29 11:14:04 -070081void oatDumpCoreRegPool(CompilationUnit* cUnit)
82{
Bill Buzbeea114add2012-05-03 15:00:40 -070083 dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
buzbee6181f792011-09-29 11:14:04 -070084}
85
86void oatDumpFpRegPool(CompilationUnit* cUnit)
87{
Bill Buzbeea114add2012-05-03 15:00:40 -070088 dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
buzbee6181f792011-09-29 11:14:04 -070089}
90
buzbee67bf8852011-08-17 17:51:35 -070091/* Mark a temp register as dead. Does not affect allocation state. */
buzbee5abfa3e2012-01-31 17:01:43 -080092static inline void clobberBody(CompilationUnit *cUnit, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -070093{
Bill Buzbeea114add2012-05-03 15:00:40 -070094 if (p->isTemp) {
95 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
96 p->live = false;
97 p->sReg = INVALID_SREG;
98 p->defStart = NULL;
99 p->defEnd = NULL;
100 if (p->pair) {
101 p->pair = false;
102 oatClobber(cUnit, p->partner);
buzbee67bf8852011-08-17 17:51:35 -0700103 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 }
buzbee67bf8852011-08-17 17:51:35 -0700105}
106
buzbee5abfa3e2012-01-31 17:01:43 -0800107/* Mark a temp register as dead. Does not affect allocation state. */
108void oatClobber(CompilationUnit* cUnit, int reg)
109{
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800111}
112
buzbee31a4a6f2012-02-28 15:36:15 -0800113void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700114{
Bill Buzbeea114add2012-05-03 15:00:40 -0700115 int i;
116 for (i=0; i< numRegs; i++) {
117 if (p[i].sReg == sReg) {
118 if (p[i].isTemp) {
119 p[i].live = false;
120 }
121 p[i].defStart = NULL;
122 p[i].defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700123 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700124 }
buzbee67bf8852011-08-17 17:51:35 -0700125}
126
127/* Clobber any temp associated with an sReg. Could be in either class */
128extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
129{
buzbee3d661942012-03-14 17:37:27 -0700130#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 /* Reset live temp tracking sanity checker */
132 if (sReg == cUnit->liveSReg) {
133 cUnit->liveSReg = INVALID_SREG;
134 }
buzbee3d661942012-03-14 17:37:27 -0700135#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs, sReg);
137 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700138}
139
buzbee9c044ce2012-03-18 13:24:07 -0700140/*
141 * SSA names associated with the initial definitions of Dalvik
142 * registers are the same as the Dalvik register number (and
143 * thus take the same position in the promotionMap. However,
144 * the special Method* and compiler temp resisters use negative
Elliott Hughesbdf6c3d2012-03-20 13:43:53 -0700145 * vReg numbers to distinguish them and can have an arbitrary
buzbee9c044ce2012-03-18 13:24:07 -0700146 * ssa name (above the last original Dalvik register). This function
147 * maps SSA names to positions in the promotionMap array.
148 */
149int SRegToPMap(CompilationUnit* cUnit, int sReg)
buzbeee1965672012-03-11 18:39:19 -0700150{
Bill Buzbeea114add2012-05-03 15:00:40 -0700151 DCHECK_LT(sReg, cUnit->numSSARegs);
152 DCHECK_GE(sReg, 0);
153 int vReg = SRegToVReg(cUnit, sReg);
154 if (vReg >= 0) {
155 DCHECK_LT(vReg, cUnit->numDalvikRegisters);
156 return vReg;
157 } else {
158 int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
159 DCHECK_LE(pos, cUnit->numCompilerTemps);
160 return cUnit->numDalvikRegisters + pos;
161 }
buzbeee1965672012-03-11 18:39:19 -0700162}
163
buzbeeca7a5e42012-08-20 11:12:18 -0700164void oatRecordCorePromotion(CompilationUnit* cUnit, int reg, int sReg)
165{
166 int pMapIdx = SRegToPMap(cUnit, sReg);
167 int vReg = SRegToVReg(cUnit, sReg);
168 oatGetRegInfo(cUnit, reg)->inUse = true;
169 cUnit->coreSpillMask |= (1 << reg);
170 // Include reg for later sort
171 cUnit->coreVmapTable.push_back(reg << VREG_NUM_WIDTH |
172 (vReg & ((1 << VREG_NUM_WIDTH) - 1)));
173 cUnit->numCoreSpills++;
174 cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
175 cUnit->promotionMap[pMapIdx].coreReg = reg;
176}
177
buzbee67bf8852011-08-17 17:51:35 -0700178/* Reserve a callee-save register. Return -1 if none available */
179extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
180{
Bill Buzbeea114add2012-05-03 15:00:40 -0700181 int res = -1;
182 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
183 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
184 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700185 res = coreRegs[i].reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700186 oatRecordCorePromotion(cUnit, res, sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700187 break;
buzbee67bf8852011-08-17 17:51:35 -0700188 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700189 }
190 return res;
buzbee67bf8852011-08-17 17:51:35 -0700191}
192
buzbeeca7a5e42012-08-20 11:12:18 -0700193void oatRecordFpPromotion(CompilationUnit* cUnit, int reg, int sReg)
194{
195 int pMapIdx = SRegToPMap(cUnit, sReg);
196 int vReg = SRegToVReg(cUnit, sReg);
197 oatGetRegInfo(cUnit, reg)->inUse = true;
198 oatMarkPreservedSingle(cUnit, vReg, reg);
199 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
200 cUnit->promotionMap[pMapIdx].fpReg = reg;
201}
202
buzbee67bf8852011-08-17 17:51:35 -0700203/*
204 * Reserve a callee-save fp single register. Try to fullfill request for
205 * even/odd allocation, but go ahead and allocate anything if not
206 * available. If nothing's available, return -1.
207 */
buzbee31a4a6f2012-02-28 15:36:15 -0800208int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700209{
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 int res = -1;
211 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
212 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
213 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
214 ((FPRegs[i].reg & 0x1) == 0) == even) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 res = FPRegs[i].reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700216 oatRecordFpPromotion(cUnit, res, sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700217 break;
buzbee67bf8852011-08-17 17:51:35 -0700218 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700219 }
220 return res;
buzbee67bf8852011-08-17 17:51:35 -0700221}
222
223/*
224 * Somewhat messy code here. We want to allocate a pair of contiguous
225 * physical single-precision floating point registers starting with
226 * an even numbered reg. It is possible that the paired sReg (sReg+1)
227 * has already been allocated - try to fit if possible. Fail to
228 * allocate if we can't meet the requirements for the pair of
229 * sReg<=sX[even] & (sReg+1)<= sX+1.
230 */
buzbee31a4a6f2012-02-28 15:36:15 -0800231int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700232{
Bill Buzbeea114add2012-05-03 15:00:40 -0700233 int res = -1; // Assume failure
234 int vReg = SRegToVReg(cUnit, sReg);
235 int pMapIdx = SRegToPMap(cUnit, sReg);
236 if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
237 // Upper reg is already allocated. Can we fit?
238 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
239 if ((highReg & 1) == 0) {
240 // High reg is even - fail.
241 return res;
242 }
243 // Is the low reg of the pair free?
244 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
245 if (p->inUse || p->isTemp) {
246 // Already allocated or not preserved - fail.
247 return res;
248 }
249 // OK - good to go.
250 res = p->reg;
251 p->inUse = true;
252 DCHECK_EQ((res & 1), 0);
253 oatMarkPreservedSingle(cUnit, vReg, res);
254 } else {
255 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
256 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
257 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
258 ((FPRegs[i].reg & 0x1) == 0x0) &&
259 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
260 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
261 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
262 res = FPRegs[i].reg;
263 FPRegs[i].inUse = true;
buzbee9c044ce2012-03-18 13:24:07 -0700264 oatMarkPreservedSingle(cUnit, vReg, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700265 FPRegs[i+1].inUse = true;
266 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
267 oatMarkPreservedSingle(cUnit, vReg+1, res+1);
268 break;
269 }
buzbee67bf8852011-08-17 17:51:35 -0700270 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700271 }
272 if (res != -1) {
273 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
274 cUnit->promotionMap[pMapIdx].fpReg = res;
275 cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
276 cUnit->promotionMap[pMapIdx+1].fpReg = res + 1;
277 }
278 return res;
buzbee67bf8852011-08-17 17:51:35 -0700279}
280
281
282/*
283 * Reserve a callee-save fp register. If this register can be used
284 * as the first of a double, attempt to allocate an even pair of fp
285 * single regs (but if can't still attempt to allocate a single, preferring
286 * first to allocate an odd register.
287 */
288extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
Bill Buzbeea114add2012-05-03 15:00:40 -0700289 bool doubleStart)
buzbee67bf8852011-08-17 17:51:35 -0700290{
Bill Buzbeea114add2012-05-03 15:00:40 -0700291 int res = -1;
292 if (doubleStart) {
293 res = allocPreservedDouble(cUnit, sReg);
294 }
295 if (res == -1) {
296 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
297 }
298 if (res == -1)
299 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
300 return res;
buzbee67bf8852011-08-17 17:51:35 -0700301}
302
buzbee31a4a6f2012-02-28 15:36:15 -0800303int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700304 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700305{
Bill Buzbeea114add2012-05-03 15:00:40 -0700306 int i;
307 int next = *nextTemp;
308 for (i=0; i< numRegs; i++) {
309 if (next >= numRegs)
310 next = 0;
311 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
312 oatClobber(cUnit, p[next].reg);
313 p[next].inUse = true;
314 p[next].pair = false;
315 *nextTemp = next + 1;
316 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700317 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700318 next++;
319 }
320 next = *nextTemp;
321 for (i=0; i< numRegs; i++) {
322 if (next >= numRegs)
323 next = 0;
324 if (p[next].isTemp && !p[next].inUse) {
325 oatClobber(cUnit, p[next].reg);
326 p[next].inUse = true;
327 p[next].pair = false;
328 *nextTemp = next + 1;
329 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700330 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 next++;
332 }
333 if (required) {
334 oatCodegenDump(cUnit);
335 dumpRegPool(cUnit->regPool->coreRegs,
336 cUnit->regPool->numCoreRegs);
337 LOG(FATAL) << "No free temp registers";
338 }
339 return -1; // No register available
buzbee67bf8852011-08-17 17:51:35 -0700340}
341
342//REDO: too many assumptions.
343extern int oatAllocTempDouble(CompilationUnit* cUnit)
344{
Bill Buzbeea114add2012-05-03 15:00:40 -0700345 RegisterInfo* p = cUnit->regPool->FPRegs;
346 int numRegs = cUnit->regPool->numFPRegs;
347 /* Start looking at an even reg */
348 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700349
Bill Buzbeea114add2012-05-03 15:00:40 -0700350 // First try to avoid allocating live registers
351 for (int i=0; i < numRegs; i+=2) {
352 if (next >= numRegs)
353 next = 0;
354 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
355 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
356 oatClobber(cUnit, p[next].reg);
357 oatClobber(cUnit, p[next+1].reg);
358 p[next].inUse = true;
359 p[next+1].inUse = true;
360 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
361 DCHECK_EQ((p[next].reg & 0x1), 0);
362 cUnit->regPool->nextFPReg = next + 2;
363 if (cUnit->regPool->nextFPReg >= numRegs) {
364 cUnit->regPool->nextFPReg = 0;
365 }
366 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700367 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 next += 2;
369 }
370 next = cUnit->regPool->nextFPReg & ~0x1;
buzbeea50638b2011-11-02 15:15:06 -0700371
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 // No choice - find a pair and kill it.
373 for (int i=0; i < numRegs; i+=2) {
374 if (next >= numRegs)
375 next = 0;
376 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
377 !p[next+1].inUse) {
378 oatClobber(cUnit, p[next].reg);
379 oatClobber(cUnit, p[next+1].reg);
380 p[next].inUse = true;
381 p[next+1].inUse = true;
382 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
383 DCHECK_EQ((p[next].reg & 0x1), 0);
384 cUnit->regPool->nextFPReg = next + 2;
385 if (cUnit->regPool->nextFPReg >= numRegs) {
386 cUnit->regPool->nextFPReg = 0;
387 }
388 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700389 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700390 next += 2;
391 }
392 LOG(FATAL) << "No free temp registers (pair)";
393 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700394}
395
396/* Return a temp if one is available, -1 otherwise */
397extern int oatAllocFreeTemp(CompilationUnit* cUnit)
398{
Bill Buzbeea114add2012-05-03 15:00:40 -0700399 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
400 cUnit->regPool->numCoreRegs,
401 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700402}
403
404extern int oatAllocTemp(CompilationUnit* cUnit)
405{
Bill Buzbeea114add2012-05-03 15:00:40 -0700406 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
407 cUnit->regPool->numCoreRegs,
408 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700409}
410
411extern int oatAllocTempFloat(CompilationUnit* cUnit)
412{
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
414 cUnit->regPool->numFPRegs,
415 &cUnit->regPool->nextFPReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700416}
417
buzbee31a4a6f2012-02-28 15:36:15 -0800418RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700419{
Bill Buzbeea114add2012-05-03 15:00:40 -0700420 int i;
421 if (sReg == -1)
buzbee67bf8852011-08-17 17:51:35 -0700422 return NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 for (i=0; i < numRegs; i++) {
424 if (p[i].live && (p[i].sReg == sReg)) {
425 if (p[i].isTemp)
426 p[i].inUse = true;
427 return &p[i];
428 }
429 }
430 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700431}
432
buzbee31a4a6f2012-02-28 15:36:15 -0800433RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700434{
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 RegisterInfo* res = NULL;
436 switch (regClass) {
437 case kAnyReg:
438 res = allocLiveBody(cUnit->regPool->FPRegs,
439 cUnit->regPool->numFPRegs, sReg);
440 if (res)
441 break;
442 /* Intentional fallthrough */
443 case kCoreReg:
444 res = allocLiveBody(cUnit->regPool->coreRegs,
445 cUnit->regPool->numCoreRegs, sReg);
446 break;
447 case kFPReg:
448 res = allocLiveBody(cUnit->regPool->FPRegs,
449 cUnit->regPool->numFPRegs, sReg);
450 break;
451 default:
452 LOG(FATAL) << "Invalid register type";
453 }
454 return res;
buzbee67bf8852011-08-17 17:51:35 -0700455}
456
457extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
458{
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 RegisterInfo* p = cUnit->regPool->coreRegs;
460 int numRegs = cUnit->regPool->numCoreRegs;
461 int i;
462 for (i=0; i< numRegs; i++) {
463 if (p[i].reg == reg) {
464 if (p[i].isTemp) {
465 p[i].inUse = false;
466 }
467 p[i].pair = false;
468 return;
buzbee67bf8852011-08-17 17:51:35 -0700469 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 }
471 p = cUnit->regPool->FPRegs;
472 numRegs = cUnit->regPool->numFPRegs;
473 for (i=0; i< numRegs; i++) {
474 if (p[i].reg == reg) {
475 if (p[i].isTemp) {
476 p[i].inUse = false;
477 }
478 p[i].pair = false;
479 return;
buzbee67bf8852011-08-17 17:51:35 -0700480 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 }
482 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700483}
484
485extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
486{
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 RegisterInfo* p = cUnit->regPool->coreRegs;
488 int numRegs = cUnit->regPool->numCoreRegs;
489 int i;
490 for (i=0; i< numRegs; i++) {
491 if (p[i].reg == reg) {
492 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700493 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 }
495 p = cUnit->regPool->FPRegs;
496 numRegs = cUnit->regPool->numFPRegs;
497 for (i=0; i< numRegs; i++) {
498 if (p[i].reg == reg) {
499 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700500 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 }
502 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700503}
504
505extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
506{
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
508 return (p->isTemp) ? p : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700509}
510
buzbeeb29e4d12011-09-26 15:05:48 -0700511extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
512{
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
514 return (p->isTemp) ? NULL : p;
buzbeeb29e4d12011-09-26 15:05:48 -0700515}
516
buzbee67bf8852011-08-17 17:51:35 -0700517extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
518{
Bill Buzbeea114add2012-05-03 15:00:40 -0700519 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
520 return p->dirty;
buzbee67bf8852011-08-17 17:51:35 -0700521}
522
523/*
524 * Similar to oatAllocTemp(), but forces the allocation of a specific
525 * register. No check is made to see if the register was previously
526 * allocated. Use with caution.
527 */
528extern void oatLockTemp(CompilationUnit* cUnit, int reg)
529{
Bill Buzbeea114add2012-05-03 15:00:40 -0700530 RegisterInfo* p = cUnit->regPool->coreRegs;
531 int numRegs = cUnit->regPool->numCoreRegs;
532 int i;
533 for (i=0; i< numRegs; i++) {
534 if (p[i].reg == reg) {
535 DCHECK(p[i].isTemp);
536 p[i].inUse = true;
537 p[i].live = false;
538 return;
buzbee67bf8852011-08-17 17:51:35 -0700539 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 }
541 p = cUnit->regPool->FPRegs;
542 numRegs = cUnit->regPool->numFPRegs;
543 for (i=0; i< numRegs; i++) {
544 if (p[i].reg == reg) {
545 DCHECK(p[i].isTemp);
546 p[i].inUse = true;
547 p[i].live = false;
548 return;
buzbee67bf8852011-08-17 17:51:35 -0700549 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 }
551 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700552}
553
buzbee5abfa3e2012-01-31 17:01:43 -0800554static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700555{
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 p->defStart = NULL;
557 p->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700558}
559
buzbee5abfa3e2012-01-31 17:01:43 -0800560extern void oatResetDef(CompilationUnit* cUnit, int reg)
561{
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 resetDefBody(oatGetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800563}
564
buzbee31a4a6f2012-02-28 15:36:15 -0800565void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 int sReg1, int sReg2)
buzbee67bf8852011-08-17 17:51:35 -0700567{
Bill Buzbeea114add2012-05-03 15:00:40 -0700568 if (start && finish) {
569 LIR *p;
570 DCHECK_EQ(sReg1, sReg2);
571 for (p = start; ;p = p->next) {
572 oatNopLIR(p);
573 if (p == finish)
574 break;
buzbee67bf8852011-08-17 17:51:35 -0700575 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700576 }
buzbee67bf8852011-08-17 17:51:35 -0700577}
578
579/*
580 * Mark the beginning and end LIR of a def sequence. Note that
581 * on entry start points to the LIR prior to the beginning of the
582 * sequence.
583 */
584extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700586{
Bill Buzbeea114add2012-05-03 15:00:40 -0700587 DCHECK(!rl.wide);
588 DCHECK(start && start->next);
589 DCHECK(finish);
590 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
591 p->defStart = start->next;
592 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700593}
594
595/*
596 * Mark the beginning and end LIR of a def sequence. Note that
597 * on entry start points to the LIR prior to the beginning of the
598 * sequence.
599 */
600extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700602{
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 DCHECK(rl.wide);
604 DCHECK(start && start->next);
605 DCHECK(finish);
606 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
607 oatResetDef(cUnit, rl.highReg); // Only track low of pair
608 p->defStart = start->next;
609 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700610}
611
buzbee31a4a6f2012-02-28 15:36:15 -0800612extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700613{
Bill Buzbeea114add2012-05-03 15:00:40 -0700614 DCHECK(rl.wide);
615 if (rl.location == kLocPhysReg) {
616 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
617 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
618 if (infoLo->isTemp) {
619 infoLo->pair = false;
620 infoLo->defStart = NULL;
621 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700622 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 if (infoHi->isTemp) {
624 infoHi->pair = false;
625 infoHi->defStart = NULL;
626 infoHi->defEnd = NULL;
627 }
628 }
629 rl.wide = false;
630 return rl;
buzbee67bf8852011-08-17 17:51:35 -0700631}
632
633extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
634{
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 DCHECK(!rl.wide);
636 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
637 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
638 DCHECK(!p->pair);
639 nullifyRange(cUnit, p->defStart, p->defEnd, p->sReg, rl.sRegLow);
640 }
641 oatResetDef(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700642}
643
644extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
645{
Bill Buzbeea114add2012-05-03 15:00:40 -0700646 DCHECK(rl.wide);
647 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
648 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
649 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
650 DCHECK(pLow->pair);
651 nullifyRange(cUnit, pLow->defStart, pLow->defEnd, pLow->sReg, rl.sRegLow);
652 }
653 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
654 DCHECK(pHigh->pair);
655 }
656 oatResetDef(cUnit, rl.lowReg);
657 oatResetDef(cUnit, rl.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700658}
659
660extern void oatResetDefTracking(CompilationUnit* cUnit)
661{
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 int i;
663 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
664 resetDefBody(&cUnit->regPool->coreRegs[i]);
665 }
666 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
667 resetDefBody(&cUnit->regPool->FPRegs[i]);
668 }
buzbee67bf8852011-08-17 17:51:35 -0700669}
670
671extern void oatClobberAllRegs(CompilationUnit* cUnit)
672{
Bill Buzbeea114add2012-05-03 15:00:40 -0700673 int i;
674 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
675 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
676 }
677 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
678 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
679 }
buzbee67bf8852011-08-17 17:51:35 -0700680}
681
buzbee67bf8852011-08-17 17:51:35 -0700682// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800683void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 int numRegs)
buzbee67bf8852011-08-17 17:51:35 -0700685{
Bill Buzbeea114add2012-05-03 15:00:40 -0700686 int i;
687 for (i=0; i < numRegs; i++) {
688 if (info[i].live && info[i].dirty) {
689 if (info[i].pair) {
690 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
691 } else {
692 oatFlushReg(cUnit, info[i].reg);
693 }
buzbee67bf8852011-08-17 17:51:35 -0700694 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700695 }
buzbee67bf8852011-08-17 17:51:35 -0700696}
697
698extern void oatFlushAllRegs(CompilationUnit* cUnit)
699{
Bill Buzbeea114add2012-05-03 15:00:40 -0700700 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
701 cUnit->regPool->numCoreRegs);
702 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
703 cUnit->regPool->numFPRegs);
704 oatClobberAllRegs(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700705}
706
707
708//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800709bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700710{
Bill Buzbeea114add2012-05-03 15:00:40 -0700711 if (regClass == kAnyReg) {
712 return true;
713 } else if (regClass == kCoreReg) {
714 return !oatIsFpReg(reg);
715 } else {
716 return oatIsFpReg(reg);
717 }
buzbee67bf8852011-08-17 17:51:35 -0700718}
719
720extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
721{
Bill Buzbeea114add2012-05-03 15:00:40 -0700722 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
723 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
724 return; /* already live */
725 } else if (sReg != INVALID_SREG) {
726 oatClobberSReg(cUnit, sReg);
727 if (info->isTemp) {
728 info->live = true;
buzbee67bf8852011-08-17 17:51:35 -0700729 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700730 } else {
731 /* Can't be live if no associated sReg */
732 DCHECK(info->isTemp);
733 info->live = false;
734 }
735 info->sReg = sReg;
buzbee67bf8852011-08-17 17:51:35 -0700736}
737
738extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
739{
Bill Buzbeea114add2012-05-03 15:00:40 -0700740 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
741 info->isTemp = true;
buzbee67bf8852011-08-17 17:51:35 -0700742}
743
buzbee9e0f9b02011-08-24 15:32:46 -0700744extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
745{
Bill Buzbeea114add2012-05-03 15:00:40 -0700746 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
747 info->isTemp = false;
buzbee9e0f9b02011-08-24 15:32:46 -0700748}
749
buzbee67bf8852011-08-17 17:51:35 -0700750extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
751{
Bill Buzbeea114add2012-05-03 15:00:40 -0700752 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
753 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
754 infoLo->pair = infoHi->pair = true;
755 infoLo->partner = highReg;
756 infoHi->partner = lowReg;
buzbee67bf8852011-08-17 17:51:35 -0700757}
758
759extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
760{
Bill Buzbeea114add2012-05-03 15:00:40 -0700761 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
762 info->dirty = false;
763 if (loc.wide) {
764 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700765 info->dirty = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700766 }
buzbee67bf8852011-08-17 17:51:35 -0700767}
768
769extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
770{
Bill Buzbeea114add2012-05-03 15:00:40 -0700771 if (loc.home) {
772 // If already home, can't be dirty
773 return;
774 }
775 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
776 info->dirty = true;
777 if (loc.wide) {
778 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700779 info->dirty = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700780 }
buzbee67bf8852011-08-17 17:51:35 -0700781}
782
783extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
784{
Bill Buzbeea114add2012-05-03 15:00:40 -0700785 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
786 info->inUse = true;
buzbee67bf8852011-08-17 17:51:35 -0700787}
788
buzbee31a4a6f2012-02-28 15:36:15 -0800789void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700790{
Bill Buzbeea114add2012-05-03 15:00:40 -0700791 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
792 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
793 // Target temp status must not change
794 bool isTemp = newInfo->isTemp;
795 *newInfo = *oldInfo;
796 // Restore target's temp status
797 newInfo->isTemp = isTemp;
798 newInfo->reg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700799}
800
801/*
802 * Return an updated location record with current in-register status.
803 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700804 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700805 * clobber both low and high.
806 * TUNING: clobbering both is a bit heavy-handed, but the alternative
807 * is a bit complex when dealing with FP regs. Examine code to see
808 * if it's worthwhile trying to be more clever here.
809 */
810
811extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
812{
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 DCHECK(!loc.wide);
814 DCHECK(oatCheckCorePoolSanity(cUnit));
815 if (loc.location != kLocPhysReg) {
816 DCHECK((loc.location == kLocDalvikFrame) ||
817 (loc.location == kLocCompilerTemp));
818 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
819 if (infoLo) {
820 if (infoLo->pair) {
821 oatClobber(cUnit, infoLo->reg);
822 oatClobber(cUnit, infoLo->partner);
823 oatFreeTemp(cUnit, infoLo->reg);
824 } else {
825 loc.lowReg = infoLo->reg;
826 loc.location = kLocPhysReg;
827 }
buzbee67bf8852011-08-17 17:51:35 -0700828 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700829 }
buzbee67bf8852011-08-17 17:51:35 -0700830
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700832}
833
buzbee6181f792011-09-29 11:14:04 -0700834bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
835{
836 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 if (cUnit->regPool->coreRegs[i].pair) {
838 static int myReg = cUnit->regPool->coreRegs[i].reg;
839 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
840 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
841 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
842 DCHECK(partner != NULL);
843 DCHECK(partner->pair);
844 DCHECK_EQ(myReg, partner->partner);
845 static int partnerSreg = partner->sReg;
846 if (mySreg == INVALID_SREG) {
847 DCHECK_EQ(partnerSreg, INVALID_SREG);
848 } else {
849 int diff = mySreg - partnerSreg;
850 DCHECK((diff == -1) || (diff == 1));
buzbee6181f792011-09-29 11:14:04 -0700851 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700852 }
853 if (!cUnit->regPool->coreRegs[i].live) {
854 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
855 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
856 }
buzbee6181f792011-09-29 11:14:04 -0700857 }
858 return true;
859}
860
buzbee67bf8852011-08-17 17:51:35 -0700861/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800862extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700863{
Bill Buzbeea114add2012-05-03 15:00:40 -0700864 DCHECK(loc.wide);
865 DCHECK(oatCheckCorePoolSanity(cUnit));
866 if (loc.location != kLocPhysReg) {
867 DCHECK((loc.location == kLocDalvikFrame) ||
868 (loc.location == kLocCompilerTemp));
869 // Are the dalvik regs already live in physical registers?
870 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
871 RegisterInfo* infoHi = allocLive(cUnit,
872 oatSRegHi(loc.sRegLow), kAnyReg);
873 bool match = true;
874 match = match && (infoLo != NULL);
875 match = match && (infoHi != NULL);
876 // Are they both core or both FP?
877 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
878 // If a pair of floating point singles, are they properly aligned?
879 if (match && oatIsFpReg(infoLo->reg)) {
880 match &= ((infoLo->reg & 0x1) == 0);
881 match &= ((infoHi->reg - infoLo->reg) == 1);
buzbee67bf8852011-08-17 17:51:35 -0700882 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 // If previously used as a pair, it is the same pair?
884 if (match && (infoLo->pair || infoHi->pair)) {
885 match = (infoLo->pair == infoHi->pair);
886 match &= ((infoLo->reg == infoHi->partner) &&
887 (infoHi->reg == infoLo->partner));
888 }
889 if (match) {
890 // Can reuse - update the register usage info
891 loc.lowReg = infoLo->reg;
892 loc.highReg = infoHi->reg;
893 loc.location = kLocPhysReg;
894 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
895 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
896 return loc;
897 }
898 // Can't easily reuse - clobber and free any overlaps
899 if (infoLo) {
900 oatClobber(cUnit, infoLo->reg);
901 oatFreeTemp(cUnit, infoLo->reg);
902 if (infoLo->pair)
903 oatClobber(cUnit, infoLo->partner);
904 }
905 if (infoHi) {
906 oatClobber(cUnit, infoHi->reg);
907 oatFreeTemp(cUnit, infoHi->reg);
908 if (infoHi->pair)
909 oatClobber(cUnit, infoHi->partner);
910 }
911 }
912 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700913}
914
buzbeeed3e9302011-09-23 17:34:19 -0700915
916/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800917extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700918{
Bill Buzbeea114add2012-05-03 15:00:40 -0700919 if (loc.wide)
920 return oatUpdateLocWide(cUnit, loc);
921 else
922 return oatUpdateLoc(cUnit, loc);
buzbeeed3e9302011-09-23 17:34:19 -0700923}
924
buzbee31a4a6f2012-02-28 15:36:15 -0800925RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700926 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700927{
Bill Buzbeea114add2012-05-03 15:00:40 -0700928 DCHECK(loc.wide);
929 int newRegs;
930 int lowReg;
931 int highReg;
buzbee67bf8852011-08-17 17:51:35 -0700932
Bill Buzbeea114add2012-05-03 15:00:40 -0700933 loc = oatUpdateLocWide(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700934
Bill Buzbeea114add2012-05-03 15:00:40 -0700935 /* If already in registers, we can assume proper form. Right reg class? */
936 if (loc.location == kLocPhysReg) {
937 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
buzbeee3acd072012-02-25 17:03:10 -0800938 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700939 if (!regClassMatches(regClass, loc.lowReg)) {
940 /* Wrong register class. Reallocate and copy */
941 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
942 lowReg = newRegs & 0xff;
943 highReg = (newRegs >> 8) & 0xff;
944 oatRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
945 loc.highReg);
946 copyRegInfo(cUnit, lowReg, loc.lowReg);
947 copyRegInfo(cUnit, highReg, loc.highReg);
948 oatClobber(cUnit, loc.lowReg);
949 oatClobber(cUnit, loc.highReg);
950 loc.lowReg = lowReg;
951 loc.highReg = highReg;
952 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
953 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
954 }
buzbee67bf8852011-08-17 17:51:35 -0700955 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700956 }
957
958 DCHECK_NE(loc.sRegLow, INVALID_SREG);
959 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
960
961 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
962 loc.lowReg = newRegs & 0xff;
963 loc.highReg = (newRegs >> 8) & 0xff;
964
965 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
966 if (update) {
967 loc.location = kLocPhysReg;
968 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
969 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
970 }
971 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
972 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700973}
974
975extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700976 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700977{
Bill Buzbeea114add2012-05-03 15:00:40 -0700978 int newReg;
buzbee67bf8852011-08-17 17:51:35 -0700979
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 if (loc.wide)
981 return evalLocWide(cUnit, loc, regClass, update);
buzbee67bf8852011-08-17 17:51:35 -0700982
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 loc = oatUpdateLoc(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700984
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 if (loc.location == kLocPhysReg) {
986 if (!regClassMatches(regClass, loc.lowReg)) {
987 /* Wrong register class. Realloc, copy and transfer ownership */
988 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
989 oatRegCopy(cUnit, newReg, loc.lowReg);
990 copyRegInfo(cUnit, newReg, loc.lowReg);
991 oatClobber(cUnit, loc.lowReg);
992 loc.lowReg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700993 }
994 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 }
996
997 DCHECK_NE(loc.sRegLow, INVALID_SREG);
998
999 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
1000 loc.lowReg = newReg;
1001
1002 if (update) {
1003 loc.location = kLocPhysReg;
1004 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1005 }
1006 return loc;
buzbee67bf8852011-08-17 17:51:35 -07001007}
1008
buzbee15bf9802012-06-12 17:49:27 -07001009extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
buzbee67bf8852011-08-17 17:51:35 -07001010{
buzbee15bf9802012-06-12 17:49:27 -07001011 DCHECK(num < mir->ssaRep->numUses);
1012 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbee15bf9802012-06-12 17:49:27 -07001013 return res;
1014}
1015extern RegLocation oatGetRawDest(CompilationUnit* cUnit, MIR* mir)
1016{
Elliott Hughes74847412012-06-20 18:10:21 -07001017 DCHECK_GT(mir->ssaRep->numDefs, 0);
buzbee15bf9802012-06-12 17:49:27 -07001018 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[0]];
buzbee15bf9802012-06-12 17:49:27 -07001019 return res;
1020}
1021extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir)
1022{
1023 RegLocation res = oatGetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 DCHECK(!res.wide);
1025 return res;
buzbee67bf8852011-08-17 17:51:35 -07001026}
1027extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1028{
buzbee15bf9802012-06-12 17:49:27 -07001029 RegLocation res = oatGetRawSrc(cUnit, mir, num);
Bill Buzbeea114add2012-05-03 15:00:40 -07001030 DCHECK(!res.wide);
1031 return res;
buzbeee9a72f62011-09-04 17:59:07 -07001032}
buzbee15bf9802012-06-12 17:49:27 -07001033extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir)
buzbeee9a72f62011-09-04 17:59:07 -07001034{
buzbee15bf9802012-06-12 17:49:27 -07001035 RegLocation res = oatGetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001036 DCHECK(res.wide);
1037 return res;
buzbee67bf8852011-08-17 17:51:35 -07001038}
1039
1040extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
buzbee15bf9802012-06-12 17:49:27 -07001041 int low)
buzbee67bf8852011-08-17 17:51:35 -07001042{
buzbee15bf9802012-06-12 17:49:27 -07001043 RegLocation res = oatGetRawSrc(cUnit, mir, low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001044 DCHECK(res.wide);
1045 return res;
buzbee67bf8852011-08-17 17:51:35 -07001046}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001047
buzbeee3acd072012-02-25 17:03:10 -08001048/* USE SSA names to count references of base Dalvik vRegs. */
1049void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
Bill Buzbeea114add2012-05-03 15:00:40 -07001050 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001051{
Bill Buzbeea114add2012-05-03 15:00:40 -07001052 if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
1053 !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
1054 (bb->blockType == kDalvikByteCode))) {
1055 return;
1056 }
1057 for (int i = 0; i < cUnit->numSSARegs;) {
1058 RegLocation loc = cUnit->regLocation[i];
1059 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
1060 int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
1061 if (loc.defined) {
1062 counts[pMapIdx].count += cUnit->useCounts.elemList[i];
buzbee239c4e72012-03-16 08:42:29 -07001063 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001064 if (loc.wide) {
1065 if (loc.defined) {
1066 if (loc.fp) {
1067 counts[pMapIdx].doubleStart = true;
1068 counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
buzbee239c4e72012-03-16 08:42:29 -07001069 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001070 }
1071 i += 2;
1072 } else {
1073 i++;
buzbeee3acd072012-02-25 17:03:10 -08001074 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001075 }
buzbeee3acd072012-02-25 17:03:10 -08001076}
1077
1078/* qsort callback function, sort descending */
1079int oatSortCounts(const void *val1, const void *val2)
1080{
Bill Buzbeea114add2012-05-03 15:00:40 -07001081 const RefCounts* op1 = (const RefCounts*)val1;
1082 const RefCounts* op2 = (const RefCounts*)val2;
1083 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
buzbeee3acd072012-02-25 17:03:10 -08001084}
1085
1086void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
1087{
Bill Buzbeea114add2012-05-03 15:00:40 -07001088 LOG(INFO) << msg;
1089 for (int i = 0; i < size; i++) {
1090 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1091 }
buzbeee3acd072012-02-25 17:03:10 -08001092}
1093
1094/*
1095 * Note: some portions of this code required even if the kPromoteRegs
1096 * optimization is disabled.
1097 */
1098extern void oatDoPromotion(CompilationUnit* cUnit)
1099{
Bill Buzbeea114add2012-05-03 15:00:40 -07001100 int regBias = cUnit->numCompilerTemps + 1;
1101 int dalvikRegs = cUnit->numDalvikRegisters;
1102 int numRegs = dalvikRegs + regBias;
1103 const int promotionThreshold = 2;
buzbeee3acd072012-02-25 17:03:10 -08001104
Bill Buzbeea114add2012-05-03 15:00:40 -07001105 // Allow target code to add any special registers
1106 oatAdjustSpillMask(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001107
Bill Buzbeea114add2012-05-03 15:00:40 -07001108 /*
1109 * Simple register promotion. Just do a static count of the uses
1110 * of Dalvik registers. Note that we examine the SSA names, but
1111 * count based on original Dalvik register name. Count refs
1112 * separately based on type in order to give allocation
1113 * preference to fp doubles - which must be allocated sequential
1114 * physical single fp registers started with an even-numbered
1115 * reg.
1116 * TUNING: replace with linear scan once we have the ability
1117 * to describe register live ranges for GC.
1118 */
1119 RefCounts *coreRegs = (RefCounts *)
1120 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1121 RefCounts *fpRegs = (RefCounts *)
1122 oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
1123 // Set ssa names for original Dalvik registers
1124 for (int i = 0; i < dalvikRegs; i++) {
1125 coreRegs[i].sReg = fpRegs[i].sReg = i;
1126 }
1127 // Set ssa name for Method*
1128 coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
1129 fpRegs[dalvikRegs].sReg = cUnit->methodSReg; // For consistecy
1130 // Set ssa names for compilerTemps
1131 for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
1132 CompilerTemp* ct = (CompilerTemp*)cUnit->compilerTemps.elemList[i];
1133 coreRegs[dalvikRegs + i].sReg = ct->sReg;
1134 fpRegs[dalvikRegs + i].sReg = ct->sReg;
1135 }
1136
1137 GrowableListIterator iterator;
1138 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1139 while (true) {
1140 BasicBlock* bb;
1141 bb = (BasicBlock*)oatGrowableListIteratorNext(&iterator);
1142 if (bb == NULL) break;
1143 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1144 }
1145
1146 /*
1147 * Ideally, we'd allocate doubles starting with an even-numbered
1148 * register. Bias the counts to try to allocate any vreg that's
1149 * used as the start of a pair first.
1150 */
1151 for (int i = 0; i < numRegs; i++) {
1152 if (fpRegs[i].doubleStart) {
1153 fpRegs[i].count *= 2;
buzbeee3acd072012-02-25 17:03:10 -08001154 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001155 }
1156
1157 // Sort the count arrays
1158 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1159 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1160
1161 if (cUnit->printMe) {
1162 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1163 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1164 }
1165
1166 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1167 // Promote fpRegs
1168 for (int i = 0; (i < numRegs) &&
1169 (fpRegs[i].count >= promotionThreshold ); i++) {
1170 int pMapIdx = SRegToPMap(cUnit, fpRegs[i].sReg);
1171 if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
1172 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1173 fpRegs[i].doubleStart);
1174 if (reg < 0) {
1175 break; // No more left
1176 }
1177 }
buzbee239c4e72012-03-16 08:42:29 -07001178 }
buzbee9c044ce2012-03-18 13:24:07 -07001179
Bill Buzbeea114add2012-05-03 15:00:40 -07001180 // Promote core regs
1181 for (int i = 0; (i < numRegs) &&
1182 (coreRegs[i].count > promotionThreshold); i++) {
1183 int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
1184 if (cUnit->promotionMap[pMapIdx].coreLocation !=
1185 kLocPhysReg) {
1186 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1187 if (reg < 0) {
1188 break; // No more left
1189 }
1190 }
buzbeee3acd072012-02-25 17:03:10 -08001191 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001192 } else if (cUnit->qdMode) {
1193 oatAllocPreservedCoreReg(cUnit, cUnit->methodSReg);
buzbeee3acd072012-02-25 17:03:10 -08001194 for (int i = 0; i < numRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001195 int reg = oatAllocPreservedCoreReg(cUnit, i);
1196 if (reg < 0) {
1197 break; // No more left
1198 }
buzbeee3acd072012-02-25 17:03:10 -08001199 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001200 }
buzbeee3acd072012-02-25 17:03:10 -08001201
buzbeee3acd072012-02-25 17:03:10 -08001202
Bill Buzbeea114add2012-05-03 15:00:40 -07001203 // Now, update SSA names to new home locations
1204 for (int i = 0; i < cUnit->numSSARegs; i++) {
1205 RegLocation *curr = &cUnit->regLocation[i];
1206 int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
1207 if (!curr->wide) {
1208 if (curr->fp) {
1209 if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
1210 curr->location = kLocPhysReg;
1211 curr->lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1212 curr->home = true;
1213 }
1214 } else {
1215 if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
1216 curr->location = kLocPhysReg;
1217 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1218 curr->home = true;
1219 }
1220 }
1221 curr->highReg = INVALID_REG;
1222 } else {
1223 if (curr->highWord) {
1224 continue;
1225 }
1226 if (curr->fp) {
1227 if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
1228 (cUnit->promotionMap[pMapIdx+1].fpLocation ==
1229 kLocPhysReg)) {
1230 int lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1231 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
1232 // Doubles require pair of singles starting at even reg
1233 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1234 curr->location = kLocPhysReg;
1235 curr->lowReg = lowReg;
1236 curr->highReg = highReg;
1237 curr->home = true;
1238 }
1239 }
1240 } else {
1241 if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
1242 && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
1243 kLocPhysReg)) {
1244 curr->location = kLocPhysReg;
1245 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1246 curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
1247 curr->home = true;
1248 }
1249 }
buzbeee3acd072012-02-25 17:03:10 -08001250 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001251 }
buzbeeca7a5e42012-08-20 11:12:18 -07001252 if (cUnit->printMe) {
1253 oatDumpPromotionMap(cUnit);
1254 }
buzbeee3acd072012-02-25 17:03:10 -08001255}
1256
1257/* Returns sp-relative offset in bytes for a VReg */
1258extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1259{
Ian Rogers0399dde2012-06-06 17:09:28 -07001260 return StackVisitor::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1261 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001262}
1263
1264/* Returns sp-relative offset in bytes for a SReg */
1265extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1266{
Bill Buzbeea114add2012-05-03 15:00:40 -07001267 return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001268}
1269
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001270} // namespace art