blob: efdbd32daab2b0edcb5f4eb9f270df3d47f55d0a [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
buzbeeb046e162012-10-30 15:48:42 -070017/* This file contains register alloction support. */
buzbee67bf8852011-08-17 17:51:35 -070018
buzbeeefc63692012-11-14 16:31:52 -080019#include "../compiler_utility.h"
20#include "../compiler_ir.h"
21#include "../dataflow.h"
buzbeeeaf09bc2012-11-15 14:51:41 -080022#include "ralloc_util.h"
23#include "codegen_util.h"
buzbee67bf8852011-08-17 17:51:35 -070024
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080025namespace art {
26
buzbee67bf8852011-08-17 17:51:35 -070027/*
28 * Free all allocated temps in the temp pools. Note that this does
29 * not affect the "liveness" of a temp register, which will stay
30 * live until it is either explicitly killed or reallocated.
31 */
32extern void oatResetRegPool(CompilationUnit* cUnit)
33{
Bill Buzbeea114add2012-05-03 15:00:40 -070034 int i;
35 for (i=0; i < cUnit->regPool->numCoreRegs; i++) {
36 if (cUnit->regPool->coreRegs[i].isTemp)
37 cUnit->regPool->coreRegs[i].inUse = false;
38 }
39 for (i=0; i < cUnit->regPool->numFPRegs; i++) {
40 if (cUnit->regPool->FPRegs[i].isTemp)
41 cUnit->regPool->FPRegs[i].inUse = false;
42 }
buzbee67bf8852011-08-17 17:51:35 -070043}
44
buzbeee3acd072012-02-25 17:03:10 -080045 /*
46 * Set up temp & preserved register pools specialized by target.
47 * Note: numRegs may be zero.
48 */
buzbee67bf8852011-08-17 17:51:35 -070049extern void oatInitPool(RegisterInfo* regs, int* regNums, int num)
50{
Bill Buzbeea114add2012-05-03 15:00:40 -070051 int i;
52 for (i=0; i < num; i++) {
53 regs[i].reg = regNums[i];
54 regs[i].inUse = false;
55 regs[i].isTemp = false;
56 regs[i].pair = false;
57 regs[i].live = false;
58 regs[i].dirty = false;
59 regs[i].sReg = INVALID_SREG;
60 }
buzbee67bf8852011-08-17 17:51:35 -070061}
62
buzbee31a4a6f2012-02-28 15:36:15 -080063void dumpRegPool(RegisterInfo* p, int numRegs)
buzbee67bf8852011-08-17 17:51:35 -070064{
Bill Buzbeea114add2012-05-03 15:00:40 -070065 LOG(INFO) << "================================================";
66 for (int i = 0; i < numRegs; i++) {
67 LOG(INFO) << StringPrintf(
68 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
69 p[i].reg, p[i].isTemp, p[i].inUse, p[i].pair, p[i].partner,
buzbeecbd6d442012-11-17 14:11:25 -080070 p[i].live, p[i].dirty, p[i].sReg, reinterpret_cast<uintptr_t>(p[i].defStart),
71 reinterpret_cast<uintptr_t>(p[i].defEnd));
Bill Buzbeea114add2012-05-03 15:00:40 -070072 }
73 LOG(INFO) << "================================================";
buzbee67bf8852011-08-17 17:51:35 -070074}
75
buzbee6181f792011-09-29 11:14:04 -070076void oatDumpCoreRegPool(CompilationUnit* cUnit)
77{
Bill Buzbeea114add2012-05-03 15:00:40 -070078 dumpRegPool(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs);
buzbee6181f792011-09-29 11:14:04 -070079}
80
81void oatDumpFpRegPool(CompilationUnit* cUnit)
82{
Bill Buzbeea114add2012-05-03 15:00:40 -070083 dumpRegPool(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs);
buzbee6181f792011-09-29 11:14:04 -070084}
85
buzbee67bf8852011-08-17 17:51:35 -070086/* Mark a temp register as dead. Does not affect allocation state. */
buzbee5abfa3e2012-01-31 17:01:43 -080087static inline void clobberBody(CompilationUnit *cUnit, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -070088{
Bill Buzbeea114add2012-05-03 15:00:40 -070089 if (p->isTemp) {
90 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
91 p->live = false;
92 p->sReg = INVALID_SREG;
93 p->defStart = NULL;
94 p->defEnd = NULL;
95 if (p->pair) {
96 p->pair = false;
97 oatClobber(cUnit, p->partner);
buzbee67bf8852011-08-17 17:51:35 -070098 }
Bill Buzbeea114add2012-05-03 15:00:40 -070099 }
buzbee67bf8852011-08-17 17:51:35 -0700100}
101
buzbee5abfa3e2012-01-31 17:01:43 -0800102/* Mark a temp register as dead. Does not affect allocation state. */
103void oatClobber(CompilationUnit* cUnit, int reg)
104{
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 clobberBody(cUnit, oatGetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800106}
107
buzbee31a4a6f2012-02-28 15:36:15 -0800108void clobberSRegBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700109{
Bill Buzbeea114add2012-05-03 15:00:40 -0700110 int i;
111 for (i=0; i< numRegs; i++) {
112 if (p[i].sReg == sReg) {
113 if (p[i].isTemp) {
114 p[i].live = false;
115 }
116 p[i].defStart = NULL;
117 p[i].defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700118 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700119 }
buzbee67bf8852011-08-17 17:51:35 -0700120}
121
122/* Clobber any temp associated with an sReg. Could be in either class */
123extern void oatClobberSReg(CompilationUnit* cUnit, int sReg)
124{
buzbee3d661942012-03-14 17:37:27 -0700125#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700126 /* Reset live temp tracking sanity checker */
127 if (sReg == cUnit->liveSReg) {
128 cUnit->liveSReg = INVALID_SREG;
129 }
buzbee3d661942012-03-14 17:37:27 -0700130#endif
Bill Buzbeea114add2012-05-03 15:00:40 -0700131 clobberSRegBody(cUnit->regPool->coreRegs, cUnit->regPool->numCoreRegs, sReg);
132 clobberSRegBody(cUnit->regPool->FPRegs, cUnit->regPool->numFPRegs, sReg);
buzbee67bf8852011-08-17 17:51:35 -0700133}
134
buzbee9c044ce2012-03-18 13:24:07 -0700135/*
136 * SSA names associated with the initial definitions of Dalvik
137 * registers are the same as the Dalvik register number (and
138 * thus take the same position in the promotionMap. However,
139 * the special Method* and compiler temp resisters use negative
Elliott Hughesbdf6c3d2012-03-20 13:43:53 -0700140 * vReg numbers to distinguish them and can have an arbitrary
buzbee9c044ce2012-03-18 13:24:07 -0700141 * ssa name (above the last original Dalvik register). This function
142 * maps SSA names to positions in the promotionMap array.
143 */
144int SRegToPMap(CompilationUnit* cUnit, int sReg)
buzbeee1965672012-03-11 18:39:19 -0700145{
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 DCHECK_LT(sReg, cUnit->numSSARegs);
147 DCHECK_GE(sReg, 0);
148 int vReg = SRegToVReg(cUnit, sReg);
149 if (vReg >= 0) {
150 DCHECK_LT(vReg, cUnit->numDalvikRegisters);
151 return vReg;
152 } else {
153 int pos = std::abs(vReg) - std::abs(SSA_METHOD_BASEREG);
154 DCHECK_LE(pos, cUnit->numCompilerTemps);
155 return cUnit->numDalvikRegisters + pos;
156 }
buzbeee1965672012-03-11 18:39:19 -0700157}
158
buzbeeca7a5e42012-08-20 11:12:18 -0700159void oatRecordCorePromotion(CompilationUnit* cUnit, int reg, int sReg)
160{
161 int pMapIdx = SRegToPMap(cUnit, sReg);
162 int vReg = SRegToVReg(cUnit, sReg);
163 oatGetRegInfo(cUnit, reg)->inUse = true;
164 cUnit->coreSpillMask |= (1 << reg);
165 // Include reg for later sort
166 cUnit->coreVmapTable.push_back(reg << VREG_NUM_WIDTH |
167 (vReg & ((1 << VREG_NUM_WIDTH) - 1)));
168 cUnit->numCoreSpills++;
169 cUnit->promotionMap[pMapIdx].coreLocation = kLocPhysReg;
170 cUnit->promotionMap[pMapIdx].coreReg = reg;
171}
172
buzbee67bf8852011-08-17 17:51:35 -0700173/* Reserve a callee-save register. Return -1 if none available */
174extern int oatAllocPreservedCoreReg(CompilationUnit* cUnit, int sReg)
175{
Bill Buzbeea114add2012-05-03 15:00:40 -0700176 int res = -1;
177 RegisterInfo* coreRegs = cUnit->regPool->coreRegs;
178 for (int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
179 if (!coreRegs[i].isTemp && !coreRegs[i].inUse) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700180 res = coreRegs[i].reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700181 oatRecordCorePromotion(cUnit, res, sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 break;
buzbee67bf8852011-08-17 17:51:35 -0700183 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700184 }
185 return res;
buzbee67bf8852011-08-17 17:51:35 -0700186}
187
buzbeeca7a5e42012-08-20 11:12:18 -0700188void oatRecordFpPromotion(CompilationUnit* cUnit, int reg, int sReg)
189{
190 int pMapIdx = SRegToPMap(cUnit, sReg);
191 int vReg = SRegToVReg(cUnit, sReg);
192 oatGetRegInfo(cUnit, reg)->inUse = true;
193 oatMarkPreservedSingle(cUnit, vReg, reg);
194 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
195 cUnit->promotionMap[pMapIdx].fpReg = reg;
196}
197
buzbee67bf8852011-08-17 17:51:35 -0700198/*
199 * Reserve a callee-save fp single register. Try to fullfill request for
200 * even/odd allocation, but go ahead and allocate anything if not
201 * available. If nothing's available, return -1.
202 */
buzbee31a4a6f2012-02-28 15:36:15 -0800203int allocPreservedSingle(CompilationUnit* cUnit, int sReg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700204{
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 int res = -1;
206 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
207 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
208 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
209 ((FPRegs[i].reg & 0x1) == 0) == even) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 res = FPRegs[i].reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700211 oatRecordFpPromotion(cUnit, res, sReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 break;
buzbee67bf8852011-08-17 17:51:35 -0700213 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 }
215 return res;
buzbee67bf8852011-08-17 17:51:35 -0700216}
217
218/*
219 * Somewhat messy code here. We want to allocate a pair of contiguous
220 * physical single-precision floating point registers starting with
221 * an even numbered reg. It is possible that the paired sReg (sReg+1)
222 * has already been allocated - try to fit if possible. Fail to
223 * allocate if we can't meet the requirements for the pair of
224 * sReg<=sX[even] & (sReg+1)<= sX+1.
225 */
buzbee31a4a6f2012-02-28 15:36:15 -0800226int allocPreservedDouble(CompilationUnit* cUnit, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700227{
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 int res = -1; // Assume failure
229 int vReg = SRegToVReg(cUnit, sReg);
230 int pMapIdx = SRegToPMap(cUnit, sReg);
231 if (cUnit->promotionMap[pMapIdx+1].fpLocation == kLocPhysReg) {
232 // Upper reg is already allocated. Can we fit?
233 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
234 if ((highReg & 1) == 0) {
235 // High reg is even - fail.
236 return res;
237 }
238 // Is the low reg of the pair free?
239 RegisterInfo* p = oatGetRegInfo(cUnit, highReg-1);
240 if (p->inUse || p->isTemp) {
241 // Already allocated or not preserved - fail.
242 return res;
243 }
244 // OK - good to go.
245 res = p->reg;
246 p->inUse = true;
247 DCHECK_EQ((res & 1), 0);
248 oatMarkPreservedSingle(cUnit, vReg, res);
249 } else {
250 RegisterInfo* FPRegs = cUnit->regPool->FPRegs;
251 for (int i = 0; i < cUnit->regPool->numFPRegs; i++) {
252 if (!FPRegs[i].isTemp && !FPRegs[i].inUse &&
253 ((FPRegs[i].reg & 0x1) == 0x0) &&
254 !FPRegs[i+1].isTemp && !FPRegs[i+1].inUse &&
255 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
256 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
257 res = FPRegs[i].reg;
258 FPRegs[i].inUse = true;
buzbee9c044ce2012-03-18 13:24:07 -0700259 oatMarkPreservedSingle(cUnit, vReg, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 FPRegs[i+1].inUse = true;
261 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
262 oatMarkPreservedSingle(cUnit, vReg+1, res+1);
263 break;
264 }
buzbee67bf8852011-08-17 17:51:35 -0700265 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 }
267 if (res != -1) {
268 cUnit->promotionMap[pMapIdx].fpLocation = kLocPhysReg;
269 cUnit->promotionMap[pMapIdx].fpReg = res;
270 cUnit->promotionMap[pMapIdx+1].fpLocation = kLocPhysReg;
271 cUnit->promotionMap[pMapIdx+1].fpReg = res + 1;
272 }
273 return res;
buzbee67bf8852011-08-17 17:51:35 -0700274}
275
276
277/*
278 * Reserve a callee-save fp register. If this register can be used
279 * as the first of a double, attempt to allocate an even pair of fp
280 * single regs (but if can't still attempt to allocate a single, preferring
281 * first to allocate an odd register.
282 */
283extern int oatAllocPreservedFPReg(CompilationUnit* cUnit, int sReg,
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 bool doubleStart)
buzbee67bf8852011-08-17 17:51:35 -0700285{
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 int res = -1;
287 if (doubleStart) {
288 res = allocPreservedDouble(cUnit, sReg);
289 }
290 if (res == -1) {
291 res = allocPreservedSingle(cUnit, sReg, false /* try odd # */);
292 }
293 if (res == -1)
294 res = allocPreservedSingle(cUnit, sReg, true /* try even # */);
295 return res;
buzbee67bf8852011-08-17 17:51:35 -0700296}
297
buzbee31a4a6f2012-02-28 15:36:15 -0800298int allocTempBody(CompilationUnit* cUnit, RegisterInfo* p, int numRegs,
Bill Buzbeea114add2012-05-03 15:00:40 -0700299 int* nextTemp, bool required)
buzbee67bf8852011-08-17 17:51:35 -0700300{
Bill Buzbeea114add2012-05-03 15:00:40 -0700301 int i;
302 int next = *nextTemp;
303 for (i=0; i< numRegs; i++) {
304 if (next >= numRegs)
305 next = 0;
306 if (p[next].isTemp && !p[next].inUse && !p[next].live) {
307 oatClobber(cUnit, p[next].reg);
308 p[next].inUse = true;
309 p[next].pair = false;
310 *nextTemp = next + 1;
311 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700312 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700313 next++;
314 }
315 next = *nextTemp;
316 for (i=0; i< numRegs; i++) {
317 if (next >= numRegs)
318 next = 0;
319 if (p[next].isTemp && !p[next].inUse) {
320 oatClobber(cUnit, p[next].reg);
321 p[next].inUse = true;
322 p[next].pair = false;
323 *nextTemp = next + 1;
324 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700325 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 next++;
327 }
328 if (required) {
329 oatCodegenDump(cUnit);
330 dumpRegPool(cUnit->regPool->coreRegs,
331 cUnit->regPool->numCoreRegs);
332 LOG(FATAL) << "No free temp registers";
333 }
334 return -1; // No register available
buzbee67bf8852011-08-17 17:51:35 -0700335}
336
337//REDO: too many assumptions.
338extern int oatAllocTempDouble(CompilationUnit* cUnit)
339{
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 RegisterInfo* p = cUnit->regPool->FPRegs;
341 int numRegs = cUnit->regPool->numFPRegs;
342 /* Start looking at an even reg */
343 int next = cUnit->regPool->nextFPReg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700344
Bill Buzbeea114add2012-05-03 15:00:40 -0700345 // First try to avoid allocating live registers
346 for (int i=0; i < numRegs; i+=2) {
347 if (next >= numRegs)
348 next = 0;
349 if ((p[next].isTemp && !p[next].inUse && !p[next].live) &&
350 (p[next+1].isTemp && !p[next+1].inUse && !p[next+1].live)) {
351 oatClobber(cUnit, p[next].reg);
352 oatClobber(cUnit, p[next+1].reg);
353 p[next].inUse = true;
354 p[next+1].inUse = true;
355 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
356 DCHECK_EQ((p[next].reg & 0x1), 0);
357 cUnit->regPool->nextFPReg = next + 2;
358 if (cUnit->regPool->nextFPReg >= numRegs) {
359 cUnit->regPool->nextFPReg = 0;
360 }
361 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700362 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700363 next += 2;
364 }
365 next = cUnit->regPool->nextFPReg & ~0x1;
buzbeea50638b2011-11-02 15:15:06 -0700366
Bill Buzbeea114add2012-05-03 15:00:40 -0700367 // No choice - find a pair and kill it.
368 for (int i=0; i < numRegs; i+=2) {
369 if (next >= numRegs)
370 next = 0;
371 if (p[next].isTemp && !p[next].inUse && p[next+1].isTemp &&
372 !p[next+1].inUse) {
373 oatClobber(cUnit, p[next].reg);
374 oatClobber(cUnit, p[next+1].reg);
375 p[next].inUse = true;
376 p[next+1].inUse = true;
377 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
378 DCHECK_EQ((p[next].reg & 0x1), 0);
379 cUnit->regPool->nextFPReg = next + 2;
380 if (cUnit->regPool->nextFPReg >= numRegs) {
381 cUnit->regPool->nextFPReg = 0;
382 }
383 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700384 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 next += 2;
386 }
387 LOG(FATAL) << "No free temp registers (pair)";
388 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700389}
390
391/* Return a temp if one is available, -1 otherwise */
392extern int oatAllocFreeTemp(CompilationUnit* cUnit)
393{
Bill Buzbeea114add2012-05-03 15:00:40 -0700394 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
395 cUnit->regPool->numCoreRegs,
396 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700397}
398
399extern int oatAllocTemp(CompilationUnit* cUnit)
400{
Bill Buzbeea114add2012-05-03 15:00:40 -0700401 return allocTempBody(cUnit, cUnit->regPool->coreRegs,
402 cUnit->regPool->numCoreRegs,
403 &cUnit->regPool->nextCoreReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700404}
405
406extern int oatAllocTempFloat(CompilationUnit* cUnit)
407{
Bill Buzbeea114add2012-05-03 15:00:40 -0700408 return allocTempBody(cUnit, cUnit->regPool->FPRegs,
409 cUnit->regPool->numFPRegs,
410 &cUnit->regPool->nextFPReg, true);
buzbee67bf8852011-08-17 17:51:35 -0700411}
412
buzbee31a4a6f2012-02-28 15:36:15 -0800413RegisterInfo* allocLiveBody(RegisterInfo* p, int numRegs, int sReg)
buzbee67bf8852011-08-17 17:51:35 -0700414{
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 int i;
416 if (sReg == -1)
buzbee67bf8852011-08-17 17:51:35 -0700417 return NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700418 for (i=0; i < numRegs; i++) {
419 if (p[i].live && (p[i].sReg == sReg)) {
420 if (p[i].isTemp)
421 p[i].inUse = true;
422 return &p[i];
423 }
424 }
425 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700426}
427
buzbee31a4a6f2012-02-28 15:36:15 -0800428RegisterInfo* allocLive(CompilationUnit* cUnit, int sReg, int regClass)
buzbee67bf8852011-08-17 17:51:35 -0700429{
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 RegisterInfo* res = NULL;
431 switch (regClass) {
432 case kAnyReg:
433 res = allocLiveBody(cUnit->regPool->FPRegs,
434 cUnit->regPool->numFPRegs, sReg);
435 if (res)
436 break;
437 /* Intentional fallthrough */
438 case kCoreReg:
439 res = allocLiveBody(cUnit->regPool->coreRegs,
440 cUnit->regPool->numCoreRegs, sReg);
441 break;
442 case kFPReg:
443 res = allocLiveBody(cUnit->regPool->FPRegs,
444 cUnit->regPool->numFPRegs, sReg);
445 break;
446 default:
447 LOG(FATAL) << "Invalid register type";
448 }
449 return res;
buzbee67bf8852011-08-17 17:51:35 -0700450}
451
452extern void oatFreeTemp(CompilationUnit* cUnit, int reg)
453{
Bill Buzbeea114add2012-05-03 15:00:40 -0700454 RegisterInfo* p = cUnit->regPool->coreRegs;
455 int numRegs = cUnit->regPool->numCoreRegs;
456 int i;
457 for (i=0; i< numRegs; i++) {
458 if (p[i].reg == reg) {
459 if (p[i].isTemp) {
460 p[i].inUse = false;
461 }
462 p[i].pair = false;
463 return;
buzbee67bf8852011-08-17 17:51:35 -0700464 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 }
466 p = cUnit->regPool->FPRegs;
467 numRegs = cUnit->regPool->numFPRegs;
468 for (i=0; i< numRegs; i++) {
469 if (p[i].reg == reg) {
470 if (p[i].isTemp) {
471 p[i].inUse = false;
472 }
473 p[i].pair = false;
474 return;
buzbee67bf8852011-08-17 17:51:35 -0700475 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 }
477 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700478}
479
480extern RegisterInfo* oatIsLive(CompilationUnit* cUnit, int reg)
481{
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 RegisterInfo* p = cUnit->regPool->coreRegs;
483 int numRegs = cUnit->regPool->numCoreRegs;
484 int i;
485 for (i=0; i< numRegs; i++) {
486 if (p[i].reg == reg) {
487 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700488 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 }
490 p = cUnit->regPool->FPRegs;
491 numRegs = cUnit->regPool->numFPRegs;
492 for (i=0; i< numRegs; i++) {
493 if (p[i].reg == reg) {
494 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700495 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700496 }
497 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700498}
499
500extern RegisterInfo* oatIsTemp(CompilationUnit* cUnit, int reg)
501{
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
503 return (p->isTemp) ? p : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700504}
505
buzbeeb29e4d12011-09-26 15:05:48 -0700506extern RegisterInfo* oatIsPromoted(CompilationUnit* cUnit, int reg)
507{
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
509 return (p->isTemp) ? NULL : p;
buzbeeb29e4d12011-09-26 15:05:48 -0700510}
511
buzbee67bf8852011-08-17 17:51:35 -0700512extern bool oatIsDirty(CompilationUnit* cUnit, int reg)
513{
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 RegisterInfo* p = oatGetRegInfo(cUnit, reg);
515 return p->dirty;
buzbee67bf8852011-08-17 17:51:35 -0700516}
517
518/*
519 * Similar to oatAllocTemp(), but forces the allocation of a specific
520 * register. No check is made to see if the register was previously
521 * allocated. Use with caution.
522 */
523extern void oatLockTemp(CompilationUnit* cUnit, int reg)
524{
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 RegisterInfo* p = cUnit->regPool->coreRegs;
526 int numRegs = cUnit->regPool->numCoreRegs;
527 int i;
528 for (i=0; i< numRegs; i++) {
529 if (p[i].reg == reg) {
530 DCHECK(p[i].isTemp);
531 p[i].inUse = true;
532 p[i].live = false;
533 return;
buzbee67bf8852011-08-17 17:51:35 -0700534 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700535 }
536 p = cUnit->regPool->FPRegs;
537 numRegs = cUnit->regPool->numFPRegs;
538 for (i=0; i< numRegs; i++) {
539 if (p[i].reg == reg) {
540 DCHECK(p[i].isTemp);
541 p[i].inUse = true;
542 p[i].live = false;
543 return;
buzbee67bf8852011-08-17 17:51:35 -0700544 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700545 }
546 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700547}
548
buzbee5abfa3e2012-01-31 17:01:43 -0800549static inline void resetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700550{
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 p->defStart = NULL;
552 p->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700553}
554
buzbee5abfa3e2012-01-31 17:01:43 -0800555extern void oatResetDef(CompilationUnit* cUnit, int reg)
556{
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 resetDefBody(oatGetRegInfo(cUnit, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800558}
559
buzbee31a4a6f2012-02-28 15:36:15 -0800560void nullifyRange(CompilationUnit* cUnit, LIR *start, LIR *finish,
Bill Buzbeea114add2012-05-03 15:00:40 -0700561 int sReg1, int sReg2)
buzbee67bf8852011-08-17 17:51:35 -0700562{
Bill Buzbeea114add2012-05-03 15:00:40 -0700563 if (start && finish) {
564 LIR *p;
565 DCHECK_EQ(sReg1, sReg2);
566 for (p = start; ;p = p->next) {
567 oatNopLIR(p);
568 if (p == finish)
569 break;
buzbee67bf8852011-08-17 17:51:35 -0700570 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700571 }
buzbee67bf8852011-08-17 17:51:35 -0700572}
573
574/*
575 * Mark the beginning and end LIR of a def sequence. Note that
576 * on entry start points to the LIR prior to the beginning of the
577 * sequence.
578 */
579extern void oatMarkDef(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700581{
Bill Buzbeea114add2012-05-03 15:00:40 -0700582 DCHECK(!rl.wide);
583 DCHECK(start && start->next);
584 DCHECK(finish);
585 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
586 p->defStart = start->next;
587 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700588}
589
590/*
591 * Mark the beginning and end LIR of a def sequence. Note that
592 * on entry start points to the LIR prior to the beginning of the
593 * sequence.
594 */
595extern void oatMarkDefWide(CompilationUnit* cUnit, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700596 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700597{
Bill Buzbeea114add2012-05-03 15:00:40 -0700598 DCHECK(rl.wide);
599 DCHECK(start && start->next);
600 DCHECK(finish);
601 RegisterInfo* p = oatGetRegInfo(cUnit, rl.lowReg);
602 oatResetDef(cUnit, rl.highReg); // Only track low of pair
603 p->defStart = start->next;
604 p->defEnd = finish;
buzbee67bf8852011-08-17 17:51:35 -0700605}
606
buzbee31a4a6f2012-02-28 15:36:15 -0800607extern RegLocation oatWideToNarrow(CompilationUnit* cUnit, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700608{
Bill Buzbeea114add2012-05-03 15:00:40 -0700609 DCHECK(rl.wide);
610 if (rl.location == kLocPhysReg) {
611 RegisterInfo* infoLo = oatGetRegInfo(cUnit, rl.lowReg);
612 RegisterInfo* infoHi = oatGetRegInfo(cUnit, rl.highReg);
613 if (infoLo->isTemp) {
614 infoLo->pair = false;
615 infoLo->defStart = NULL;
616 infoLo->defEnd = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700617 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 if (infoHi->isTemp) {
619 infoHi->pair = false;
620 infoHi->defStart = NULL;
621 infoHi->defEnd = NULL;
622 }
623 }
624 rl.wide = false;
625 return rl;
buzbee67bf8852011-08-17 17:51:35 -0700626}
627
628extern void oatResetDefLoc(CompilationUnit* cUnit, RegLocation rl)
629{
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 DCHECK(!rl.wide);
631 RegisterInfo* p = oatIsTemp(cUnit, rl.lowReg);
632 if (p && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
633 DCHECK(!p->pair);
634 nullifyRange(cUnit, p->defStart, p->defEnd, p->sReg, rl.sRegLow);
635 }
636 oatResetDef(cUnit, rl.lowReg);
buzbee67bf8852011-08-17 17:51:35 -0700637}
638
639extern void oatResetDefLocWide(CompilationUnit* cUnit, RegLocation rl)
640{
Bill Buzbeea114add2012-05-03 15:00:40 -0700641 DCHECK(rl.wide);
642 RegisterInfo* pLow = oatIsTemp(cUnit, rl.lowReg);
643 RegisterInfo* pHigh = oatIsTemp(cUnit, rl.highReg);
644 if (pLow && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
645 DCHECK(pLow->pair);
646 nullifyRange(cUnit, pLow->defStart, pLow->defEnd, pLow->sReg, rl.sRegLow);
647 }
648 if (pHigh && !(cUnit->disableOpt & (1 << kSuppressLoads))) {
649 DCHECK(pHigh->pair);
650 }
651 oatResetDef(cUnit, rl.lowReg);
652 oatResetDef(cUnit, rl.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700653}
654
655extern void oatResetDefTracking(CompilationUnit* cUnit)
656{
Bill Buzbeea114add2012-05-03 15:00:40 -0700657 int i;
658 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
659 resetDefBody(&cUnit->regPool->coreRegs[i]);
660 }
661 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
662 resetDefBody(&cUnit->regPool->FPRegs[i]);
663 }
buzbee67bf8852011-08-17 17:51:35 -0700664}
665
666extern void oatClobberAllRegs(CompilationUnit* cUnit)
667{
Bill Buzbeea114add2012-05-03 15:00:40 -0700668 int i;
669 for (i=0; i< cUnit->regPool->numCoreRegs; i++) {
670 clobberBody(cUnit, &cUnit->regPool->coreRegs[i]);
671 }
672 for (i=0; i< cUnit->regPool->numFPRegs; i++) {
673 clobberBody(cUnit, &cUnit->regPool->FPRegs[i]);
674 }
buzbee67bf8852011-08-17 17:51:35 -0700675}
676
buzbee67bf8852011-08-17 17:51:35 -0700677// Make sure nothing is live and dirty
buzbee31a4a6f2012-02-28 15:36:15 -0800678void flushAllRegsBody(CompilationUnit* cUnit, RegisterInfo* info,
Bill Buzbeea114add2012-05-03 15:00:40 -0700679 int numRegs)
buzbee67bf8852011-08-17 17:51:35 -0700680{
Bill Buzbeea114add2012-05-03 15:00:40 -0700681 int i;
682 for (i=0; i < numRegs; i++) {
683 if (info[i].live && info[i].dirty) {
684 if (info[i].pair) {
685 oatFlushRegWide(cUnit, info[i].reg, info[i].partner);
686 } else {
687 oatFlushReg(cUnit, info[i].reg);
688 }
buzbee67bf8852011-08-17 17:51:35 -0700689 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700690 }
buzbee67bf8852011-08-17 17:51:35 -0700691}
692
693extern void oatFlushAllRegs(CompilationUnit* cUnit)
694{
Bill Buzbeea114add2012-05-03 15:00:40 -0700695 flushAllRegsBody(cUnit, cUnit->regPool->coreRegs,
696 cUnit->regPool->numCoreRegs);
697 flushAllRegsBody(cUnit, cUnit->regPool->FPRegs,
698 cUnit->regPool->numFPRegs);
699 oatClobberAllRegs(cUnit);
buzbee67bf8852011-08-17 17:51:35 -0700700}
701
702
703//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee31a4a6f2012-02-28 15:36:15 -0800704bool regClassMatches(int regClass, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700705{
Bill Buzbeea114add2012-05-03 15:00:40 -0700706 if (regClass == kAnyReg) {
707 return true;
708 } else if (regClass == kCoreReg) {
709 return !oatIsFpReg(reg);
710 } else {
711 return oatIsFpReg(reg);
712 }
buzbee67bf8852011-08-17 17:51:35 -0700713}
714
715extern void oatMarkLive(CompilationUnit* cUnit, int reg, int sReg)
716{
Bill Buzbeea114add2012-05-03 15:00:40 -0700717 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
718 if ((info->reg == reg) && (info->sReg == sReg) && info->live) {
719 return; /* already live */
720 } else if (sReg != INVALID_SREG) {
721 oatClobberSReg(cUnit, sReg);
722 if (info->isTemp) {
723 info->live = true;
buzbee67bf8852011-08-17 17:51:35 -0700724 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700725 } else {
726 /* Can't be live if no associated sReg */
727 DCHECK(info->isTemp);
728 info->live = false;
729 }
730 info->sReg = sReg;
buzbee67bf8852011-08-17 17:51:35 -0700731}
732
733extern void oatMarkTemp(CompilationUnit* cUnit, int reg)
734{
Bill Buzbeea114add2012-05-03 15:00:40 -0700735 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
736 info->isTemp = true;
buzbee67bf8852011-08-17 17:51:35 -0700737}
738
buzbee9e0f9b02011-08-24 15:32:46 -0700739extern void oatUnmarkTemp(CompilationUnit* cUnit, int reg)
740{
Bill Buzbeea114add2012-05-03 15:00:40 -0700741 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
742 info->isTemp = false;
buzbee9e0f9b02011-08-24 15:32:46 -0700743}
744
buzbee67bf8852011-08-17 17:51:35 -0700745extern void oatMarkPair(CompilationUnit* cUnit, int lowReg, int highReg)
746{
Bill Buzbeea114add2012-05-03 15:00:40 -0700747 RegisterInfo* infoLo = oatGetRegInfo(cUnit, lowReg);
748 RegisterInfo* infoHi = oatGetRegInfo(cUnit, highReg);
749 infoLo->pair = infoHi->pair = true;
750 infoLo->partner = highReg;
751 infoHi->partner = lowReg;
buzbee67bf8852011-08-17 17:51:35 -0700752}
753
754extern void oatMarkClean(CompilationUnit* cUnit, RegLocation loc)
755{
Bill Buzbeea114add2012-05-03 15:00:40 -0700756 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
757 info->dirty = false;
758 if (loc.wide) {
759 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700760 info->dirty = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700761 }
buzbee67bf8852011-08-17 17:51:35 -0700762}
763
764extern void oatMarkDirty(CompilationUnit* cUnit, RegLocation loc)
765{
Bill Buzbeea114add2012-05-03 15:00:40 -0700766 if (loc.home) {
767 // If already home, can't be dirty
768 return;
769 }
770 RegisterInfo* info = oatGetRegInfo(cUnit, loc.lowReg);
771 info->dirty = true;
772 if (loc.wide) {
773 info = oatGetRegInfo(cUnit, loc.highReg);
buzbee67bf8852011-08-17 17:51:35 -0700774 info->dirty = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 }
buzbee67bf8852011-08-17 17:51:35 -0700776}
777
778extern void oatMarkInUse(CompilationUnit* cUnit, int reg)
779{
Bill Buzbeea114add2012-05-03 15:00:40 -0700780 RegisterInfo* info = oatGetRegInfo(cUnit, reg);
781 info->inUse = true;
buzbee67bf8852011-08-17 17:51:35 -0700782}
783
buzbee31a4a6f2012-02-28 15:36:15 -0800784void copyRegInfo(CompilationUnit* cUnit, int newReg, int oldReg)
buzbee67bf8852011-08-17 17:51:35 -0700785{
Bill Buzbeea114add2012-05-03 15:00:40 -0700786 RegisterInfo* newInfo = oatGetRegInfo(cUnit, newReg);
787 RegisterInfo* oldInfo = oatGetRegInfo(cUnit, oldReg);
788 // Target temp status must not change
789 bool isTemp = newInfo->isTemp;
790 *newInfo = *oldInfo;
791 // Restore target's temp status
792 newInfo->isTemp = isTemp;
793 newInfo->reg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700794}
795
796/*
797 * Return an updated location record with current in-register status.
798 * If the value lives in live temps, reflect that fact. No code
buzbeeb29e4d12011-09-26 15:05:48 -0700799 * is generated. If the live value is part of an older pair,
buzbee67bf8852011-08-17 17:51:35 -0700800 * clobber both low and high.
801 * TUNING: clobbering both is a bit heavy-handed, but the alternative
802 * is a bit complex when dealing with FP regs. Examine code to see
803 * if it's worthwhile trying to be more clever here.
804 */
805
806extern RegLocation oatUpdateLoc(CompilationUnit* cUnit, RegLocation loc)
807{
Bill Buzbeea114add2012-05-03 15:00:40 -0700808 DCHECK(!loc.wide);
809 DCHECK(oatCheckCorePoolSanity(cUnit));
810 if (loc.location != kLocPhysReg) {
811 DCHECK((loc.location == kLocDalvikFrame) ||
812 (loc.location == kLocCompilerTemp));
813 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
814 if (infoLo) {
815 if (infoLo->pair) {
816 oatClobber(cUnit, infoLo->reg);
817 oatClobber(cUnit, infoLo->partner);
818 oatFreeTemp(cUnit, infoLo->reg);
819 } else {
820 loc.lowReg = infoLo->reg;
821 loc.location = kLocPhysReg;
822 }
buzbee67bf8852011-08-17 17:51:35 -0700823 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 }
buzbee67bf8852011-08-17 17:51:35 -0700825
Bill Buzbeea114add2012-05-03 15:00:40 -0700826 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700827}
828
buzbee6181f792011-09-29 11:14:04 -0700829bool oatCheckCorePoolSanity(CompilationUnit* cUnit)
830{
831 for (static int i = 0; i < cUnit->regPool->numCoreRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700832 if (cUnit->regPool->coreRegs[i].pair) {
833 static int myReg = cUnit->regPool->coreRegs[i].reg;
834 static int mySreg = cUnit->regPool->coreRegs[i].sReg;
835 static int partnerReg = cUnit->regPool->coreRegs[i].partner;
836 static RegisterInfo* partner = oatGetRegInfo(cUnit, partnerReg);
837 DCHECK(partner != NULL);
838 DCHECK(partner->pair);
839 DCHECK_EQ(myReg, partner->partner);
840 static int partnerSreg = partner->sReg;
841 if (mySreg == INVALID_SREG) {
842 DCHECK_EQ(partnerSreg, INVALID_SREG);
843 } else {
844 int diff = mySreg - partnerSreg;
845 DCHECK((diff == -1) || (diff == 1));
buzbee6181f792011-09-29 11:14:04 -0700846 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700847 }
848 if (!cUnit->regPool->coreRegs[i].live) {
849 DCHECK(cUnit->regPool->coreRegs[i].defStart == NULL);
850 DCHECK(cUnit->regPool->coreRegs[i].defEnd == NULL);
851 }
buzbee6181f792011-09-29 11:14:04 -0700852 }
853 return true;
854}
855
buzbee67bf8852011-08-17 17:51:35 -0700856/* see comments for updateLoc */
buzbee31a4a6f2012-02-28 15:36:15 -0800857extern RegLocation oatUpdateLocWide(CompilationUnit* cUnit, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700858{
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 DCHECK(loc.wide);
860 DCHECK(oatCheckCorePoolSanity(cUnit));
861 if (loc.location != kLocPhysReg) {
862 DCHECK((loc.location == kLocDalvikFrame) ||
863 (loc.location == kLocCompilerTemp));
864 // Are the dalvik regs already live in physical registers?
865 RegisterInfo* infoLo = allocLive(cUnit, loc.sRegLow, kAnyReg);
866 RegisterInfo* infoHi = allocLive(cUnit,
867 oatSRegHi(loc.sRegLow), kAnyReg);
868 bool match = true;
869 match = match && (infoLo != NULL);
870 match = match && (infoHi != NULL);
871 // Are they both core or both FP?
872 match = match && (oatIsFpReg(infoLo->reg) == oatIsFpReg(infoHi->reg));
873 // If a pair of floating point singles, are they properly aligned?
874 if (match && oatIsFpReg(infoLo->reg)) {
875 match &= ((infoLo->reg & 0x1) == 0);
876 match &= ((infoHi->reg - infoLo->reg) == 1);
buzbee67bf8852011-08-17 17:51:35 -0700877 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700878 // If previously used as a pair, it is the same pair?
879 if (match && (infoLo->pair || infoHi->pair)) {
880 match = (infoLo->pair == infoHi->pair);
881 match &= ((infoLo->reg == infoHi->partner) &&
882 (infoHi->reg == infoLo->partner));
883 }
884 if (match) {
885 // Can reuse - update the register usage info
886 loc.lowReg = infoLo->reg;
887 loc.highReg = infoHi->reg;
888 loc.location = kLocPhysReg;
889 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
890 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
891 return loc;
892 }
893 // Can't easily reuse - clobber and free any overlaps
894 if (infoLo) {
895 oatClobber(cUnit, infoLo->reg);
896 oatFreeTemp(cUnit, infoLo->reg);
897 if (infoLo->pair)
898 oatClobber(cUnit, infoLo->partner);
899 }
900 if (infoHi) {
901 oatClobber(cUnit, infoHi->reg);
902 oatFreeTemp(cUnit, infoHi->reg);
903 if (infoHi->pair)
904 oatClobber(cUnit, infoHi->partner);
905 }
906 }
907 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700908}
909
buzbeeed3e9302011-09-23 17:34:19 -0700910
911/* For use in cases we don't know (or care) width */
buzbee31a4a6f2012-02-28 15:36:15 -0800912extern RegLocation oatUpdateRawLoc(CompilationUnit* cUnit, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700913{
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 if (loc.wide)
915 return oatUpdateLocWide(cUnit, loc);
916 else
917 return oatUpdateLoc(cUnit, loc);
buzbeeed3e9302011-09-23 17:34:19 -0700918}
919
buzbee31a4a6f2012-02-28 15:36:15 -0800920RegLocation evalLocWide(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700921 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700922{
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 DCHECK(loc.wide);
924 int newRegs;
925 int lowReg;
926 int highReg;
buzbee67bf8852011-08-17 17:51:35 -0700927
Bill Buzbeea114add2012-05-03 15:00:40 -0700928 loc = oatUpdateLocWide(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700929
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 /* If already in registers, we can assume proper form. Right reg class? */
931 if (loc.location == kLocPhysReg) {
932 DCHECK_EQ(oatIsFpReg(loc.lowReg), oatIsFpReg(loc.highReg));
buzbeee3acd072012-02-25 17:03:10 -0800933 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700934 if (!regClassMatches(regClass, loc.lowReg)) {
935 /* Wrong register class. Reallocate and copy */
936 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
937 lowReg = newRegs & 0xff;
938 highReg = (newRegs >> 8) & 0xff;
buzbeeeaf09bc2012-11-15 14:51:41 -0800939 opRegCopyWide(cUnit, lowReg, highReg, loc.lowReg,
940 loc.highReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700941 copyRegInfo(cUnit, lowReg, loc.lowReg);
942 copyRegInfo(cUnit, highReg, loc.highReg);
943 oatClobber(cUnit, loc.lowReg);
944 oatClobber(cUnit, loc.highReg);
945 loc.lowReg = lowReg;
946 loc.highReg = highReg;
947 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
948 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
949 }
buzbee67bf8852011-08-17 17:51:35 -0700950 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 }
952
953 DCHECK_NE(loc.sRegLow, INVALID_SREG);
954 DCHECK_NE(oatSRegHi(loc.sRegLow), INVALID_SREG);
955
956 newRegs = oatAllocTypedTempPair(cUnit, loc.fp, regClass);
957 loc.lowReg = newRegs & 0xff;
958 loc.highReg = (newRegs >> 8) & 0xff;
959
960 oatMarkPair(cUnit, loc.lowReg, loc.highReg);
961 if (update) {
962 loc.location = kLocPhysReg;
963 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
964 oatMarkLive(cUnit, loc.highReg, oatSRegHi(loc.sRegLow));
965 }
966 DCHECK(!oatIsFpReg(loc.lowReg) || ((loc.lowReg & 0x1) == 0));
967 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700968}
969
970extern RegLocation oatEvalLoc(CompilationUnit* cUnit, RegLocation loc,
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 int regClass, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700972{
Bill Buzbeea114add2012-05-03 15:00:40 -0700973 int newReg;
buzbee67bf8852011-08-17 17:51:35 -0700974
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 if (loc.wide)
976 return evalLocWide(cUnit, loc, regClass, update);
buzbee67bf8852011-08-17 17:51:35 -0700977
Bill Buzbeea114add2012-05-03 15:00:40 -0700978 loc = oatUpdateLoc(cUnit, loc);
buzbee67bf8852011-08-17 17:51:35 -0700979
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 if (loc.location == kLocPhysReg) {
981 if (!regClassMatches(regClass, loc.lowReg)) {
982 /* Wrong register class. Realloc, copy and transfer ownership */
983 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
buzbeeeaf09bc2012-11-15 14:51:41 -0800984 opRegCopy(cUnit, newReg, loc.lowReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 copyRegInfo(cUnit, newReg, loc.lowReg);
986 oatClobber(cUnit, loc.lowReg);
987 loc.lowReg = newReg;
buzbee67bf8852011-08-17 17:51:35 -0700988 }
989 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700990 }
991
992 DCHECK_NE(loc.sRegLow, INVALID_SREG);
993
994 newReg = oatAllocTypedTemp(cUnit, loc.fp, regClass);
995 loc.lowReg = newReg;
996
997 if (update) {
998 loc.location = kLocPhysReg;
999 oatMarkLive(cUnit, loc.lowReg, loc.sRegLow);
1000 }
1001 return loc;
buzbee67bf8852011-08-17 17:51:35 -07001002}
1003
buzbee15bf9802012-06-12 17:49:27 -07001004extern RegLocation oatGetRawSrc(CompilationUnit* cUnit, MIR* mir, int num)
buzbee67bf8852011-08-17 17:51:35 -07001005{
buzbee15bf9802012-06-12 17:49:27 -07001006 DCHECK(num < mir->ssaRep->numUses);
1007 RegLocation res = cUnit->regLocation[mir->ssaRep->uses[num]];
buzbee15bf9802012-06-12 17:49:27 -07001008 return res;
1009}
buzbeeeaf09bc2012-11-15 14:51:41 -08001010
buzbee15bf9802012-06-12 17:49:27 -07001011extern RegLocation oatGetRawDest(CompilationUnit* cUnit, MIR* mir)
1012{
Elliott Hughes74847412012-06-20 18:10:21 -07001013 DCHECK_GT(mir->ssaRep->numDefs, 0);
buzbee15bf9802012-06-12 17:49:27 -07001014 RegLocation res = cUnit->regLocation[mir->ssaRep->defs[0]];
buzbee15bf9802012-06-12 17:49:27 -07001015 return res;
1016}
buzbeeeaf09bc2012-11-15 14:51:41 -08001017
buzbee15bf9802012-06-12 17:49:27 -07001018extern RegLocation oatGetDest(CompilationUnit* cUnit, MIR* mir)
1019{
1020 RegLocation res = oatGetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001021 DCHECK(!res.wide);
1022 return res;
buzbee67bf8852011-08-17 17:51:35 -07001023}
buzbeeeaf09bc2012-11-15 14:51:41 -08001024
buzbee67bf8852011-08-17 17:51:35 -07001025extern RegLocation oatGetSrc(CompilationUnit* cUnit, MIR* mir, int num)
1026{
buzbee15bf9802012-06-12 17:49:27 -07001027 RegLocation res = oatGetRawSrc(cUnit, mir, num);
Bill Buzbeea114add2012-05-03 15:00:40 -07001028 DCHECK(!res.wide);
1029 return res;
buzbeee9a72f62011-09-04 17:59:07 -07001030}
buzbeeeaf09bc2012-11-15 14:51:41 -08001031
buzbee15bf9802012-06-12 17:49:27 -07001032extern RegLocation oatGetDestWide(CompilationUnit* cUnit, MIR* mir)
buzbeee9a72f62011-09-04 17:59:07 -07001033{
buzbee15bf9802012-06-12 17:49:27 -07001034 RegLocation res = oatGetRawDest(cUnit, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001035 DCHECK(res.wide);
1036 return res;
buzbee67bf8852011-08-17 17:51:35 -07001037}
1038
1039extern RegLocation oatGetSrcWide(CompilationUnit* cUnit, MIR* mir,
buzbee15bf9802012-06-12 17:49:27 -07001040 int low)
buzbee67bf8852011-08-17 17:51:35 -07001041{
buzbee15bf9802012-06-12 17:49:27 -07001042 RegLocation res = oatGetRawSrc(cUnit, mir, low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001043 DCHECK(res.wide);
1044 return res;
buzbee67bf8852011-08-17 17:51:35 -07001045}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001046
buzbeee3acd072012-02-25 17:03:10 -08001047/* USE SSA names to count references of base Dalvik vRegs. */
1048void oatCountRefs(CompilationUnit *cUnit, BasicBlock* bb,
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 RefCounts* coreCounts, RefCounts* fpCounts)
buzbeee3acd072012-02-25 17:03:10 -08001050{
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 if ((cUnit->disableOpt & (1 << kPromoteRegs)) ||
1052 !((bb->blockType == kEntryBlock) || (bb->blockType == kExitBlock) ||
1053 (bb->blockType == kDalvikByteCode))) {
1054 return;
1055 }
1056 for (int i = 0; i < cUnit->numSSARegs;) {
1057 RegLocation loc = cUnit->regLocation[i];
1058 RefCounts* counts = loc.fp ? fpCounts : coreCounts;
1059 int pMapIdx = SRegToPMap(cUnit, loc.sRegLow);
1060 if (loc.defined) {
1061 counts[pMapIdx].count += cUnit->useCounts.elemList[i];
buzbee239c4e72012-03-16 08:42:29 -07001062 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001063 if (loc.wide) {
1064 if (loc.defined) {
1065 if (loc.fp) {
1066 counts[pMapIdx].doubleStart = true;
1067 counts[pMapIdx+1].count += cUnit->useCounts.elemList[i+1];
buzbee239c4e72012-03-16 08:42:29 -07001068 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001069 }
1070 i += 2;
1071 } else {
1072 i++;
buzbeee3acd072012-02-25 17:03:10 -08001073 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001074 }
buzbeee3acd072012-02-25 17:03:10 -08001075}
1076
1077/* qsort callback function, sort descending */
1078int oatSortCounts(const void *val1, const void *val2)
1079{
buzbeecbd6d442012-11-17 14:11:25 -08001080 const RefCounts* op1 = reinterpret_cast<const RefCounts*>(val1);
1081 const RefCounts* op2 = reinterpret_cast<const RefCounts*>(val2);
Bill Buzbeea114add2012-05-03 15:00:40 -07001082 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
buzbeee3acd072012-02-25 17:03:10 -08001083}
1084
1085void oatDumpCounts(const RefCounts* arr, int size, const char* msg)
1086{
Bill Buzbeea114add2012-05-03 15:00:40 -07001087 LOG(INFO) << msg;
1088 for (int i = 0; i < size; i++) {
1089 LOG(INFO) << "sReg[" << arr[i].sReg << "]: " << arr[i].count;
1090 }
buzbeee3acd072012-02-25 17:03:10 -08001091}
1092
1093/*
1094 * Note: some portions of this code required even if the kPromoteRegs
1095 * optimization is disabled.
1096 */
1097extern void oatDoPromotion(CompilationUnit* cUnit)
1098{
Bill Buzbeea114add2012-05-03 15:00:40 -07001099 int regBias = cUnit->numCompilerTemps + 1;
1100 int dalvikRegs = cUnit->numDalvikRegisters;
1101 int numRegs = dalvikRegs + regBias;
1102 const int promotionThreshold = 2;
buzbeee3acd072012-02-25 17:03:10 -08001103
Bill Buzbeea114add2012-05-03 15:00:40 -07001104 // Allow target code to add any special registers
1105 oatAdjustSpillMask(cUnit);
buzbeee3acd072012-02-25 17:03:10 -08001106
Bill Buzbeea114add2012-05-03 15:00:40 -07001107 /*
1108 * Simple register promotion. Just do a static count of the uses
1109 * of Dalvik registers. Note that we examine the SSA names, but
1110 * count based on original Dalvik register name. Count refs
1111 * separately based on type in order to give allocation
1112 * preference to fp doubles - which must be allocated sequential
1113 * physical single fp registers started with an even-numbered
1114 * reg.
1115 * TUNING: replace with linear scan once we have the ability
1116 * to describe register live ranges for GC.
1117 */
buzbeecbd6d442012-11-17 14:11:25 -08001118 RefCounts *coreRegs = static_cast<RefCounts*>(oatNew(cUnit, sizeof(RefCounts) * numRegs,
1119 true, kAllocRegAlloc));
1120 RefCounts *fpRegs = static_cast<RefCounts *>(oatNew(cUnit, sizeof(RefCounts) * numRegs,
1121 true, kAllocRegAlloc));
Bill Buzbeea114add2012-05-03 15:00:40 -07001122 // Set ssa names for original Dalvik registers
1123 for (int i = 0; i < dalvikRegs; i++) {
1124 coreRegs[i].sReg = fpRegs[i].sReg = i;
1125 }
1126 // Set ssa name for Method*
1127 coreRegs[dalvikRegs].sReg = cUnit->methodSReg;
1128 fpRegs[dalvikRegs].sReg = cUnit->methodSReg; // For consistecy
1129 // Set ssa names for compilerTemps
1130 for (int i = 1; i <= cUnit->numCompilerTemps; i++) {
buzbeecbd6d442012-11-17 14:11:25 -08001131 CompilerTemp* ct = reinterpret_cast<CompilerTemp*>(cUnit->compilerTemps.elemList[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -07001132 coreRegs[dalvikRegs + i].sReg = ct->sReg;
1133 fpRegs[dalvikRegs + i].sReg = ct->sReg;
1134 }
1135
1136 GrowableListIterator iterator;
1137 oatGrowableListIteratorInit(&cUnit->blockList, &iterator);
1138 while (true) {
1139 BasicBlock* bb;
buzbeecbd6d442012-11-17 14:11:25 -08001140 bb = reinterpret_cast<BasicBlock*>(oatGrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -07001141 if (bb == NULL) break;
1142 oatCountRefs(cUnit, bb, coreRegs, fpRegs);
1143 }
1144
1145 /*
1146 * Ideally, we'd allocate doubles starting with an even-numbered
1147 * register. Bias the counts to try to allocate any vreg that's
1148 * used as the start of a pair first.
1149 */
1150 for (int i = 0; i < numRegs; i++) {
1151 if (fpRegs[i].doubleStart) {
1152 fpRegs[i].count *= 2;
buzbeee3acd072012-02-25 17:03:10 -08001153 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001154 }
1155
1156 // Sort the count arrays
1157 qsort(coreRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1158 qsort(fpRegs, numRegs, sizeof(RefCounts), oatSortCounts);
1159
1160 if (cUnit->printMe) {
1161 oatDumpCounts(coreRegs, numRegs, "Core regs after sort");
1162 oatDumpCounts(fpRegs, numRegs, "Fp regs after sort");
1163 }
1164
1165 if (!(cUnit->disableOpt & (1 << kPromoteRegs))) {
1166 // Promote fpRegs
1167 for (int i = 0; (i < numRegs) &&
1168 (fpRegs[i].count >= promotionThreshold ); i++) {
1169 int pMapIdx = SRegToPMap(cUnit, fpRegs[i].sReg);
1170 if (cUnit->promotionMap[pMapIdx].fpLocation != kLocPhysReg) {
1171 int reg = oatAllocPreservedFPReg(cUnit, fpRegs[i].sReg,
1172 fpRegs[i].doubleStart);
1173 if (reg < 0) {
1174 break; // No more left
1175 }
1176 }
buzbee239c4e72012-03-16 08:42:29 -07001177 }
buzbee9c044ce2012-03-18 13:24:07 -07001178
Bill Buzbeea114add2012-05-03 15:00:40 -07001179 // Promote core regs
1180 for (int i = 0; (i < numRegs) &&
1181 (coreRegs[i].count > promotionThreshold); i++) {
1182 int pMapIdx = SRegToPMap(cUnit, coreRegs[i].sReg);
1183 if (cUnit->promotionMap[pMapIdx].coreLocation !=
1184 kLocPhysReg) {
1185 int reg = oatAllocPreservedCoreReg(cUnit, coreRegs[i].sReg);
1186 if (reg < 0) {
1187 break; // No more left
1188 }
1189 }
buzbeee3acd072012-02-25 17:03:10 -08001190 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001191 } else if (cUnit->qdMode) {
1192 oatAllocPreservedCoreReg(cUnit, cUnit->methodSReg);
buzbeee3acd072012-02-25 17:03:10 -08001193 for (int i = 0; i < numRegs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001194 int reg = oatAllocPreservedCoreReg(cUnit, i);
1195 if (reg < 0) {
1196 break; // No more left
1197 }
buzbeee3acd072012-02-25 17:03:10 -08001198 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001199 }
buzbeee3acd072012-02-25 17:03:10 -08001200
buzbeee3acd072012-02-25 17:03:10 -08001201
Bill Buzbeea114add2012-05-03 15:00:40 -07001202 // Now, update SSA names to new home locations
1203 for (int i = 0; i < cUnit->numSSARegs; i++) {
1204 RegLocation *curr = &cUnit->regLocation[i];
1205 int pMapIdx = SRegToPMap(cUnit, curr->sRegLow);
1206 if (!curr->wide) {
1207 if (curr->fp) {
1208 if (cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) {
1209 curr->location = kLocPhysReg;
1210 curr->lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1211 curr->home = true;
1212 }
1213 } else {
1214 if (cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg) {
1215 curr->location = kLocPhysReg;
1216 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1217 curr->home = true;
1218 }
1219 }
1220 curr->highReg = INVALID_REG;
1221 } else {
1222 if (curr->highWord) {
1223 continue;
1224 }
1225 if (curr->fp) {
1226 if ((cUnit->promotionMap[pMapIdx].fpLocation == kLocPhysReg) &&
1227 (cUnit->promotionMap[pMapIdx+1].fpLocation ==
1228 kLocPhysReg)) {
1229 int lowReg = cUnit->promotionMap[pMapIdx].fpReg;
1230 int highReg = cUnit->promotionMap[pMapIdx+1].fpReg;
1231 // Doubles require pair of singles starting at even reg
1232 if (((lowReg & 0x1) == 0) && ((lowReg + 1) == highReg)) {
1233 curr->location = kLocPhysReg;
1234 curr->lowReg = lowReg;
1235 curr->highReg = highReg;
1236 curr->home = true;
1237 }
1238 }
1239 } else {
1240 if ((cUnit->promotionMap[pMapIdx].coreLocation == kLocPhysReg)
1241 && (cUnit->promotionMap[pMapIdx+1].coreLocation ==
1242 kLocPhysReg)) {
1243 curr->location = kLocPhysReg;
1244 curr->lowReg = cUnit->promotionMap[pMapIdx].coreReg;
1245 curr->highReg = cUnit->promotionMap[pMapIdx+1].coreReg;
1246 curr->home = true;
1247 }
1248 }
buzbeee3acd072012-02-25 17:03:10 -08001249 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001250 }
buzbeeca7a5e42012-08-20 11:12:18 -07001251 if (cUnit->printMe) {
1252 oatDumpPromotionMap(cUnit);
1253 }
buzbeee3acd072012-02-25 17:03:10 -08001254}
1255
1256/* Returns sp-relative offset in bytes for a VReg */
1257extern int oatVRegOffset(CompilationUnit* cUnit, int vReg)
1258{
Ian Rogers0399dde2012-06-06 17:09:28 -07001259 return StackVisitor::GetVRegOffset(cUnit->code_item, cUnit->coreSpillMask,
1260 cUnit->fpSpillMask, cUnit->frameSize, vReg);
buzbeee3acd072012-02-25 17:03:10 -08001261}
1262
1263/* Returns sp-relative offset in bytes for a SReg */
1264extern int oatSRegOffset(CompilationUnit* cUnit, int sReg)
1265{
Bill Buzbeea114add2012-05-03 15:00:40 -07001266 return oatVRegOffset(cUnit, SRegToVReg(cUnit, sReg));
buzbeee3acd072012-02-25 17:03:10 -08001267}
1268
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001269} // namespace art