blob: 18c77141e149ed6da600bbfb524545a10597b032 [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
buzbee395116c2013-02-27 14:30:25 -080019#include "compiler/dex/compiler_ir.h"
buzbee311ca162013-02-28 15:56:43 -080020#include "compiler/dex/compiler_internals.h"
buzbee395116c2013-02-27 14:30:25 -080021#include "compiler/dex/compiler_utility.h"
buzbee311ca162013-02-28 15:56:43 -080022//#include "compiler/dex/dataflow.h"
Brian Carlstrom265091e2013-01-30 14:08:26 -080023#include "compiler/dex/quick/codegen_util.h"
Brian Carlstrom641ce032013-01-31 15:21:37 -080024#include "ralloc_util.h"
buzbee67bf8852011-08-17 17:51:35 -070025
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080026namespace art {
27
buzbee02031b12012-11-23 09:41:35 -080028static const RegLocation bad_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
29 INVALID_REG, INVALID_REG, INVALID_SREG,
30 INVALID_SREG};
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 */
buzbeefa57c472012-11-21 12:06:18 -080037void ResetRegPool(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -070038{
Bill Buzbeea114add2012-05-03 15:00:40 -070039 int i;
buzbeefa57c472012-11-21 12:06:18 -080040 for (i=0; i < cu->reg_pool->num_core_regs; i++) {
41 if (cu->reg_pool->core_regs[i].is_temp)
42 cu->reg_pool->core_regs[i].in_use = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070043 }
buzbeefa57c472012-11-21 12:06:18 -080044 for (i=0; i < cu->reg_pool->num_fp_regs; i++) {
45 if (cu->reg_pool->FPRegs[i].is_temp)
46 cu->reg_pool->FPRegs[i].in_use = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070047 }
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.
buzbeefa57c472012-11-21 12:06:18 -080052 * Note: num_regs may be zero.
buzbeee3acd072012-02-25 17:03:10 -080053 */
buzbeefa57c472012-11-21 12:06:18 -080054void CompilerInitPool(RegisterInfo* regs, int* reg_nums, int num)
buzbee67bf8852011-08-17 17:51:35 -070055{
Bill Buzbeea114add2012-05-03 15:00:40 -070056 int i;
57 for (i=0; i < num; i++) {
buzbeefa57c472012-11-21 12:06:18 -080058 regs[i].reg = reg_nums[i];
59 regs[i].in_use = false;
60 regs[i].is_temp = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070061 regs[i].pair = false;
62 regs[i].live = false;
63 regs[i].dirty = false;
buzbeefa57c472012-11-21 12:06:18 -080064 regs[i].s_reg = INVALID_SREG;
Bill Buzbeea114add2012-05-03 15:00:40 -070065 }
buzbee67bf8852011-08-17 17:51:35 -070066}
67
buzbee4ef3e452012-12-14 13:35:28 -080068void DumpRegPool(RegisterInfo* p, int num_regs)
buzbee67bf8852011-08-17 17:51:35 -070069{
Bill Buzbeea114add2012-05-03 15:00:40 -070070 LOG(INFO) << "================================================";
buzbeefa57c472012-11-21 12:06:18 -080071 for (int i = 0; i < num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -070072 LOG(INFO) << StringPrintf(
73 "R[%d]: T:%d, U:%d, P:%d, p:%d, LV:%d, D:%d, SR:%d, ST:%x, EN:%x",
buzbeefa57c472012-11-21 12:06:18 -080074 p[i].reg, p[i].is_temp, p[i].in_use, p[i].pair, p[i].partner,
75 p[i].live, p[i].dirty, p[i].s_reg, reinterpret_cast<uintptr_t>(p[i].def_start),
76 reinterpret_cast<uintptr_t>(p[i].def_end));
Bill Buzbeea114add2012-05-03 15:00:40 -070077 }
78 LOG(INFO) << "================================================";
buzbee67bf8852011-08-17 17:51:35 -070079}
80
buzbeefa57c472012-11-21 12:06:18 -080081void DumpCoreRegPool(CompilationUnit* cu)
buzbee6181f792011-09-29 11:14:04 -070082{
buzbeefa57c472012-11-21 12:06:18 -080083 DumpRegPool(cu->reg_pool->core_regs, cu->reg_pool->num_core_regs);
buzbee6181f792011-09-29 11:14:04 -070084}
85
buzbeefa57c472012-11-21 12:06:18 -080086void DumpFpRegPool(CompilationUnit* cu)
buzbee6181f792011-09-29 11:14:04 -070087{
buzbeefa57c472012-11-21 12:06:18 -080088 DumpRegPool(cu->reg_pool->FPRegs, cu->reg_pool->num_fp_regs);
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. */
buzbeefa57c472012-11-21 12:06:18 -080092static void ClobberBody(CompilationUnit *cu, RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -070093{
buzbeefa57c472012-11-21 12:06:18 -080094 if (p->is_temp) {
Bill Buzbeea114add2012-05-03 15:00:40 -070095 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
96 p->live = false;
buzbeefa57c472012-11-21 12:06:18 -080097 p->s_reg = INVALID_SREG;
98 p->def_start = NULL;
99 p->def_end = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700100 if (p->pair) {
101 p->pair = false;
buzbeefa57c472012-11-21 12:06:18 -0800102 Clobber(cu, 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. */
buzbeefa57c472012-11-21 12:06:18 -0800108void Clobber(CompilationUnit* cu, int reg)
buzbee5abfa3e2012-01-31 17:01:43 -0800109{
buzbee02031b12012-11-23 09:41:35 -0800110 Codegen* cg = cu->cg.get();
111 ClobberBody(cu, cg->GetRegInfo(cu, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800112}
113
buzbeefa57c472012-11-21 12:06:18 -0800114static void ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700115{
Bill Buzbeea114add2012-05-03 15:00:40 -0700116 int i;
buzbeefa57c472012-11-21 12:06:18 -0800117 for (i=0; i< num_regs; i++) {
118 if (p[i].s_reg == s_reg) {
119 if (p[i].is_temp) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 p[i].live = false;
121 }
buzbeefa57c472012-11-21 12:06:18 -0800122 p[i].def_start = NULL;
123 p[i].def_end = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700124 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700125 }
buzbee67bf8852011-08-17 17:51:35 -0700126}
127
buzbee078fa452012-12-03 15:51:33 -0800128/*
129 * Break the association between a Dalvik vreg and a physical temp register of either register
130 * class.
131 * TODO: Ideally, the public version of this code should not exist. Besides its local usage
132 * in the register utilities, is is also used by code gen routines to work around a deficiency in
133 * local register allocation, which fails to distinguish between the "in" and "out" identities
134 * of Dalvik vregs. This can result in useless register copies when the same Dalvik vreg
135 * is used both as the source and destination register of an operation in which the type
136 * changes (for example: INT_TO_FLOAT v1, v1). Revisit when improved register allocation is
137 * addressed.
138 */
buzbeefa57c472012-11-21 12:06:18 -0800139void ClobberSReg(CompilationUnit* cu, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700140{
Bill Buzbeea114add2012-05-03 15:00:40 -0700141 /* Reset live temp tracking sanity checker */
buzbee311ca162013-02-28 15:56:43 -0800142 if (kIsDebugBuild) {
143 if (s_reg == cu->live_sreg) {
144 cu->live_sreg = INVALID_SREG;
145 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 }
buzbeefa57c472012-11-21 12:06:18 -0800147 ClobberSRegBody(cu->reg_pool->core_regs, cu->reg_pool->num_core_regs, s_reg);
148 ClobberSRegBody(cu->reg_pool->FPRegs, cu->reg_pool->num_fp_regs, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700149}
150
buzbee9c044ce2012-03-18 13:24:07 -0700151/*
152 * SSA names associated with the initial definitions of Dalvik
153 * registers are the same as the Dalvik register number (and
buzbeefa57c472012-11-21 12:06:18 -0800154 * thus take the same position in the promotion_map. However,
buzbee9c044ce2012-03-18 13:24:07 -0700155 * the special Method* and compiler temp resisters use negative
buzbeefa57c472012-11-21 12:06:18 -0800156 * v_reg numbers to distinguish them and can have an arbitrary
buzbee9c044ce2012-03-18 13:24:07 -0700157 * ssa name (above the last original Dalvik register). This function
buzbeefa57c472012-11-21 12:06:18 -0800158 * maps SSA names to positions in the promotion_map array.
buzbee9c044ce2012-03-18 13:24:07 -0700159 */
buzbee5f61f672012-11-28 17:22:17 -0800160int SRegToPMap(CompilationUnit* cu, int s_reg)
buzbeee1965672012-03-11 18:39:19 -0700161{
buzbee311ca162013-02-28 15:56:43 -0800162 DCHECK_LT(s_reg, cu->mir_graph->GetNumSSARegs());
buzbeefa57c472012-11-21 12:06:18 -0800163 DCHECK_GE(s_reg, 0);
buzbee311ca162013-02-28 15:56:43 -0800164 int v_reg = cu->mir_graph->SRegToVReg(s_reg);
buzbeefa57c472012-11-21 12:06:18 -0800165 if (v_reg >= 0) {
166 DCHECK_LT(v_reg, cu->num_dalvik_registers);
167 return v_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700168 } else {
buzbeefa57c472012-11-21 12:06:18 -0800169 int pos = std::abs(v_reg) - std::abs(SSA_METHOD_BASEREG);
170 DCHECK_LE(pos, cu->num_compiler_temps);
171 return cu->num_dalvik_registers + pos;
Bill Buzbeea114add2012-05-03 15:00:40 -0700172 }
buzbeee1965672012-03-11 18:39:19 -0700173}
174
buzbeefa57c472012-11-21 12:06:18 -0800175void RecordCorePromotion(CompilationUnit* cu, int reg, int s_reg)
buzbeeca7a5e42012-08-20 11:12:18 -0700176{
buzbee02031b12012-11-23 09:41:35 -0800177 Codegen* cg = cu->cg.get();
buzbeefa57c472012-11-21 12:06:18 -0800178 int p_map_idx = SRegToPMap(cu, s_reg);
buzbee311ca162013-02-28 15:56:43 -0800179 int v_reg = cu->mir_graph->SRegToVReg(s_reg);
buzbee02031b12012-11-23 09:41:35 -0800180 cg->GetRegInfo(cu, reg)->in_use = true;
buzbeefa57c472012-11-21 12:06:18 -0800181 cu->core_spill_mask |= (1 << reg);
buzbeeca7a5e42012-08-20 11:12:18 -0700182 // Include reg for later sort
buzbeefa57c472012-11-21 12:06:18 -0800183 cu->core_vmap_table.push_back(reg << VREG_NUM_WIDTH |
184 (v_reg & ((1 << VREG_NUM_WIDTH) - 1)));
185 cu->num_core_spills++;
186 cu->promotion_map[p_map_idx].core_location = kLocPhysReg;
187 cu->promotion_map[p_map_idx].core_reg = reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700188}
189
buzbee67bf8852011-08-17 17:51:35 -0700190/* Reserve a callee-save register. Return -1 if none available */
buzbeefa57c472012-11-21 12:06:18 -0800191static int AllocPreservedCoreReg(CompilationUnit* cu, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700192{
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 int res = -1;
buzbeefa57c472012-11-21 12:06:18 -0800194 RegisterInfo* core_regs = cu->reg_pool->core_regs;
195 for (int i = 0; i < cu->reg_pool->num_core_regs; i++) {
196 if (!core_regs[i].is_temp && !core_regs[i].in_use) {
197 res = core_regs[i].reg;
198 RecordCorePromotion(cu, res, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700199 break;
buzbee67bf8852011-08-17 17:51:35 -0700200 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 }
202 return res;
buzbee67bf8852011-08-17 17:51:35 -0700203}
204
buzbeefa57c472012-11-21 12:06:18 -0800205void RecordFpPromotion(CompilationUnit* cu, int reg, int s_reg)
buzbeeca7a5e42012-08-20 11:12:18 -0700206{
buzbee02031b12012-11-23 09:41:35 -0800207 Codegen* cg = cu->cg.get();
buzbeefa57c472012-11-21 12:06:18 -0800208 int p_map_idx = SRegToPMap(cu, s_reg);
buzbee311ca162013-02-28 15:56:43 -0800209 int v_reg = cu->mir_graph->SRegToVReg(s_reg);
buzbee02031b12012-11-23 09:41:35 -0800210 cg->GetRegInfo(cu, reg)->in_use = true;
211 cg->MarkPreservedSingle(cu, v_reg, reg);
buzbeefa57c472012-11-21 12:06:18 -0800212 cu->promotion_map[p_map_idx].fp_location = kLocPhysReg;
213 cu->promotion_map[p_map_idx].FpReg = reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700214}
215
buzbee67bf8852011-08-17 17:51:35 -0700216/*
217 * Reserve a callee-save fp single register. Try to fullfill request for
218 * even/odd allocation, but go ahead and allocate anything if not
219 * available. If nothing's available, return -1.
220 */
buzbeefa57c472012-11-21 12:06:18 -0800221static int AllocPreservedSingle(CompilationUnit* cu, int s_reg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700222{
Bill Buzbeea114add2012-05-03 15:00:40 -0700223 int res = -1;
buzbeefa57c472012-11-21 12:06:18 -0800224 RegisterInfo* FPRegs = cu->reg_pool->FPRegs;
225 for (int i = 0; i < cu->reg_pool->num_fp_regs; i++) {
226 if (!FPRegs[i].is_temp && !FPRegs[i].in_use &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700227 ((FPRegs[i].reg & 0x1) == 0) == even) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 res = FPRegs[i].reg;
buzbeefa57c472012-11-21 12:06:18 -0800229 RecordFpPromotion(cu, res, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700230 break;
buzbee67bf8852011-08-17 17:51:35 -0700231 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700232 }
233 return res;
buzbee67bf8852011-08-17 17:51:35 -0700234}
235
236/*
237 * Somewhat messy code here. We want to allocate a pair of contiguous
238 * physical single-precision floating point registers starting with
buzbeefa57c472012-11-21 12:06:18 -0800239 * an even numbered reg. It is possible that the paired s_reg (s_reg+1)
buzbee67bf8852011-08-17 17:51:35 -0700240 * has already been allocated - try to fit if possible. Fail to
241 * allocate if we can't meet the requirements for the pair of
buzbeefa57c472012-11-21 12:06:18 -0800242 * s_reg<=sX[even] & (s_reg+1)<= sX+1.
buzbee67bf8852011-08-17 17:51:35 -0700243 */
buzbeefa57c472012-11-21 12:06:18 -0800244static int AllocPreservedDouble(CompilationUnit* cu, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700245{
buzbee02031b12012-11-23 09:41:35 -0800246 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 int res = -1; // Assume failure
buzbee311ca162013-02-28 15:56:43 -0800248 int v_reg = cu->mir_graph->SRegToVReg(s_reg);
buzbeefa57c472012-11-21 12:06:18 -0800249 int p_map_idx = SRegToPMap(cu, s_reg);
250 if (cu->promotion_map[p_map_idx+1].fp_location == kLocPhysReg) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700251 // Upper reg is already allocated. Can we fit?
buzbeefa57c472012-11-21 12:06:18 -0800252 int high_reg = cu->promotion_map[p_map_idx+1].FpReg;
253 if ((high_reg & 1) == 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 // High reg is even - fail.
255 return res;
256 }
257 // Is the low reg of the pair free?
buzbee02031b12012-11-23 09:41:35 -0800258 RegisterInfo* p = cg->GetRegInfo(cu, high_reg-1);
buzbeefa57c472012-11-21 12:06:18 -0800259 if (p->in_use || p->is_temp) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 // Already allocated or not preserved - fail.
261 return res;
262 }
263 // OK - good to go.
264 res = p->reg;
buzbeefa57c472012-11-21 12:06:18 -0800265 p->in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 DCHECK_EQ((res & 1), 0);
buzbee02031b12012-11-23 09:41:35 -0800267 cg->MarkPreservedSingle(cu, v_reg, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 } else {
buzbeefa57c472012-11-21 12:06:18 -0800269 RegisterInfo* FPRegs = cu->reg_pool->FPRegs;
270 for (int i = 0; i < cu->reg_pool->num_fp_regs; i++) {
271 if (!FPRegs[i].is_temp && !FPRegs[i].in_use &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700272 ((FPRegs[i].reg & 0x1) == 0x0) &&
buzbeefa57c472012-11-21 12:06:18 -0800273 !FPRegs[i+1].is_temp && !FPRegs[i+1].in_use &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700274 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
275 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
276 res = FPRegs[i].reg;
buzbeefa57c472012-11-21 12:06:18 -0800277 FPRegs[i].in_use = true;
buzbee02031b12012-11-23 09:41:35 -0800278 cg->MarkPreservedSingle(cu, v_reg, res);
buzbeefa57c472012-11-21 12:06:18 -0800279 FPRegs[i+1].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
buzbee02031b12012-11-23 09:41:35 -0800281 cg->MarkPreservedSingle(cu, v_reg+1, res+1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 break;
283 }
buzbee67bf8852011-08-17 17:51:35 -0700284 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700285 }
286 if (res != -1) {
buzbeefa57c472012-11-21 12:06:18 -0800287 cu->promotion_map[p_map_idx].fp_location = kLocPhysReg;
288 cu->promotion_map[p_map_idx].FpReg = res;
289 cu->promotion_map[p_map_idx+1].fp_location = kLocPhysReg;
290 cu->promotion_map[p_map_idx+1].FpReg = res + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700291 }
292 return res;
buzbee67bf8852011-08-17 17:51:35 -0700293}
294
295
296/*
297 * Reserve a callee-save fp register. If this register can be used
298 * as the first of a double, attempt to allocate an even pair of fp
299 * single regs (but if can't still attempt to allocate a single, preferring
300 * first to allocate an odd register.
301 */
buzbeefa57c472012-11-21 12:06:18 -0800302static int AllocPreservedFPReg(CompilationUnit* cu, int s_reg, bool double_start)
buzbee67bf8852011-08-17 17:51:35 -0700303{
Bill Buzbeea114add2012-05-03 15:00:40 -0700304 int res = -1;
buzbeefa57c472012-11-21 12:06:18 -0800305 if (double_start) {
306 res = AllocPreservedDouble(cu, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 }
308 if (res == -1) {
buzbeefa57c472012-11-21 12:06:18 -0800309 res = AllocPreservedSingle(cu, s_reg, false /* try odd # */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700310 }
311 if (res == -1)
buzbeefa57c472012-11-21 12:06:18 -0800312 res = AllocPreservedSingle(cu, s_reg, true /* try even # */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700313 return res;
buzbee67bf8852011-08-17 17:51:35 -0700314}
315
buzbeefa57c472012-11-21 12:06:18 -0800316static int AllocTempBody(CompilationUnit* cu, RegisterInfo* p, int num_regs, int* next_temp,
buzbeeaad94382012-11-21 07:40:50 -0800317 bool required)
buzbee67bf8852011-08-17 17:51:35 -0700318{
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 int i;
buzbeefa57c472012-11-21 12:06:18 -0800320 int next = *next_temp;
321 for (i=0; i< num_regs; i++) {
322 if (next >= num_regs)
Bill Buzbeea114add2012-05-03 15:00:40 -0700323 next = 0;
buzbeefa57c472012-11-21 12:06:18 -0800324 if (p[next].is_temp && !p[next].in_use && !p[next].live) {
325 Clobber(cu, p[next].reg);
326 p[next].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700327 p[next].pair = false;
buzbeefa57c472012-11-21 12:06:18 -0800328 *next_temp = next + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700329 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700330 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 next++;
332 }
buzbeefa57c472012-11-21 12:06:18 -0800333 next = *next_temp;
334 for (i=0; i< num_regs; i++) {
335 if (next >= num_regs)
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 next = 0;
buzbeefa57c472012-11-21 12:06:18 -0800337 if (p[next].is_temp && !p[next].in_use) {
338 Clobber(cu, p[next].reg);
339 p[next].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 p[next].pair = false;
buzbeefa57c472012-11-21 12:06:18 -0800341 *next_temp = next + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700343 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700344 next++;
345 }
346 if (required) {
buzbeefa57c472012-11-21 12:06:18 -0800347 CodegenDump(cu);
348 DumpRegPool(cu->reg_pool->core_regs,
349 cu->reg_pool->num_core_regs);
Bill Buzbeea114add2012-05-03 15:00:40 -0700350 LOG(FATAL) << "No free temp registers";
351 }
352 return -1; // No register available
buzbee67bf8852011-08-17 17:51:35 -0700353}
354
355//REDO: too many assumptions.
buzbeefa57c472012-11-21 12:06:18 -0800356int AllocTempDouble(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700357{
buzbeefa57c472012-11-21 12:06:18 -0800358 RegisterInfo* p = cu->reg_pool->FPRegs;
359 int num_regs = cu->reg_pool->num_fp_regs;
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 /* Start looking at an even reg */
buzbeefa57c472012-11-21 12:06:18 -0800361 int next = cu->reg_pool->next_fp_reg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700362
Bill Buzbeea114add2012-05-03 15:00:40 -0700363 // First try to avoid allocating live registers
buzbeefa57c472012-11-21 12:06:18 -0800364 for (int i=0; i < num_regs; i+=2) {
365 if (next >= num_regs)
Bill Buzbeea114add2012-05-03 15:00:40 -0700366 next = 0;
buzbeefa57c472012-11-21 12:06:18 -0800367 if ((p[next].is_temp && !p[next].in_use && !p[next].live) &&
368 (p[next+1].is_temp && !p[next+1].in_use && !p[next+1].live)) {
369 Clobber(cu, p[next].reg);
370 Clobber(cu, p[next+1].reg);
371 p[next].in_use = true;
372 p[next+1].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700373 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
374 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800375 cu->reg_pool->next_fp_reg = next + 2;
376 if (cu->reg_pool->next_fp_reg >= num_regs) {
377 cu->reg_pool->next_fp_reg = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 }
379 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700380 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700381 next += 2;
382 }
buzbeefa57c472012-11-21 12:06:18 -0800383 next = cu->reg_pool->next_fp_reg & ~0x1;
buzbeea50638b2011-11-02 15:15:06 -0700384
Bill Buzbeea114add2012-05-03 15:00:40 -0700385 // No choice - find a pair and kill it.
buzbeefa57c472012-11-21 12:06:18 -0800386 for (int i=0; i < num_regs; i+=2) {
387 if (next >= num_regs)
Bill Buzbeea114add2012-05-03 15:00:40 -0700388 next = 0;
buzbeefa57c472012-11-21 12:06:18 -0800389 if (p[next].is_temp && !p[next].in_use && p[next+1].is_temp &&
390 !p[next+1].in_use) {
391 Clobber(cu, p[next].reg);
392 Clobber(cu, p[next+1].reg);
393 p[next].in_use = true;
394 p[next+1].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700395 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
396 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800397 cu->reg_pool->next_fp_reg = next + 2;
398 if (cu->reg_pool->next_fp_reg >= num_regs) {
399 cu->reg_pool->next_fp_reg = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700400 }
401 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700402 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700403 next += 2;
404 }
405 LOG(FATAL) << "No free temp registers (pair)";
406 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700407}
408
409/* Return a temp if one is available, -1 otherwise */
buzbeefa57c472012-11-21 12:06:18 -0800410int AllocFreeTemp(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700411{
buzbeefa57c472012-11-21 12:06:18 -0800412 return AllocTempBody(cu, cu->reg_pool->core_regs,
413 cu->reg_pool->num_core_regs,
414 &cu->reg_pool->next_core_reg, true);
buzbee67bf8852011-08-17 17:51:35 -0700415}
416
buzbeefa57c472012-11-21 12:06:18 -0800417int AllocTemp(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700418{
buzbeefa57c472012-11-21 12:06:18 -0800419 return AllocTempBody(cu, cu->reg_pool->core_regs,
420 cu->reg_pool->num_core_regs,
421 &cu->reg_pool->next_core_reg, true);
buzbee67bf8852011-08-17 17:51:35 -0700422}
423
buzbeefa57c472012-11-21 12:06:18 -0800424int AllocTempFloat(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700425{
buzbeefa57c472012-11-21 12:06:18 -0800426 return AllocTempBody(cu, cu->reg_pool->FPRegs,
427 cu->reg_pool->num_fp_regs,
428 &cu->reg_pool->next_fp_reg, true);
buzbee67bf8852011-08-17 17:51:35 -0700429}
430
buzbeefa57c472012-11-21 12:06:18 -0800431static RegisterInfo* AllocLiveBody(RegisterInfo* p, int num_regs, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700432{
Bill Buzbeea114add2012-05-03 15:00:40 -0700433 int i;
buzbeefa57c472012-11-21 12:06:18 -0800434 if (s_reg == -1)
buzbee67bf8852011-08-17 17:51:35 -0700435 return NULL;
buzbeefa57c472012-11-21 12:06:18 -0800436 for (i=0; i < num_regs; i++) {
437 if (p[i].live && (p[i].s_reg == s_reg)) {
438 if (p[i].is_temp)
439 p[i].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 return &p[i];
441 }
442 }
443 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700444}
445
buzbeefa57c472012-11-21 12:06:18 -0800446RegisterInfo* AllocLive(CompilationUnit* cu, int s_reg, int reg_class)
buzbee67bf8852011-08-17 17:51:35 -0700447{
Bill Buzbeea114add2012-05-03 15:00:40 -0700448 RegisterInfo* res = NULL;
buzbeefa57c472012-11-21 12:06:18 -0800449 switch (reg_class) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700450 case kAnyReg:
buzbeefa57c472012-11-21 12:06:18 -0800451 res = AllocLiveBody(cu->reg_pool->FPRegs,
452 cu->reg_pool->num_fp_regs, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 if (res)
454 break;
455 /* Intentional fallthrough */
456 case kCoreReg:
buzbeefa57c472012-11-21 12:06:18 -0800457 res = AllocLiveBody(cu->reg_pool->core_regs,
458 cu->reg_pool->num_core_regs, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 break;
460 case kFPReg:
buzbeefa57c472012-11-21 12:06:18 -0800461 res = AllocLiveBody(cu->reg_pool->FPRegs,
462 cu->reg_pool->num_fp_regs, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700463 break;
464 default:
465 LOG(FATAL) << "Invalid register type";
466 }
467 return res;
buzbee67bf8852011-08-17 17:51:35 -0700468}
469
buzbeefa57c472012-11-21 12:06:18 -0800470void FreeTemp(CompilationUnit* cu, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700471{
buzbeefa57c472012-11-21 12:06:18 -0800472 RegisterInfo* p = cu->reg_pool->core_regs;
473 int num_regs = cu->reg_pool->num_core_regs;
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 int i;
buzbeefa57c472012-11-21 12:06:18 -0800475 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 if (p[i].reg == reg) {
buzbeefa57c472012-11-21 12:06:18 -0800477 if (p[i].is_temp) {
478 p[i].in_use = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 }
480 p[i].pair = false;
481 return;
buzbee67bf8852011-08-17 17:51:35 -0700482 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 }
buzbeefa57c472012-11-21 12:06:18 -0800484 p = cu->reg_pool->FPRegs;
485 num_regs = cu->reg_pool->num_fp_regs;
486 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700487 if (p[i].reg == reg) {
buzbeefa57c472012-11-21 12:06:18 -0800488 if (p[i].is_temp) {
489 p[i].in_use = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700490 }
491 p[i].pair = false;
492 return;
buzbee67bf8852011-08-17 17:51:35 -0700493 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 }
495 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700496}
497
buzbeefa57c472012-11-21 12:06:18 -0800498RegisterInfo* IsLive(CompilationUnit* cu, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700499{
buzbeefa57c472012-11-21 12:06:18 -0800500 RegisterInfo* p = cu->reg_pool->core_regs;
501 int num_regs = cu->reg_pool->num_core_regs;
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 int i;
buzbeefa57c472012-11-21 12:06:18 -0800503 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 if (p[i].reg == reg) {
505 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700506 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 }
buzbeefa57c472012-11-21 12:06:18 -0800508 p = cu->reg_pool->FPRegs;
509 num_regs = cu->reg_pool->num_fp_regs;
510 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700511 if (p[i].reg == reg) {
512 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700513 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 }
515 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700516}
517
buzbeefa57c472012-11-21 12:06:18 -0800518RegisterInfo* IsTemp(CompilationUnit* cu, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700519{
buzbee02031b12012-11-23 09:41:35 -0800520 Codegen* cg = cu->cg.get();
521 RegisterInfo* p = cg->GetRegInfo(cu, reg);
buzbeefa57c472012-11-21 12:06:18 -0800522 return (p->is_temp) ? p : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700523}
524
buzbeefa57c472012-11-21 12:06:18 -0800525RegisterInfo* IsPromoted(CompilationUnit* cu, int reg)
buzbeeb29e4d12011-09-26 15:05:48 -0700526{
buzbee02031b12012-11-23 09:41:35 -0800527 Codegen* cg = cu->cg.get();
528 RegisterInfo* p = cg->GetRegInfo(cu, reg);
buzbeefa57c472012-11-21 12:06:18 -0800529 return (p->is_temp) ? NULL : p;
buzbeeb29e4d12011-09-26 15:05:48 -0700530}
531
buzbeefa57c472012-11-21 12:06:18 -0800532bool IsDirty(CompilationUnit* cu, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700533{
buzbee02031b12012-11-23 09:41:35 -0800534 Codegen* cg = cu->cg.get();
535 RegisterInfo* p = cg->GetRegInfo(cu, reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700536 return p->dirty;
buzbee67bf8852011-08-17 17:51:35 -0700537}
538
539/*
buzbee52a77fc2012-11-20 19:50:46 -0800540 * Similar to AllocTemp(), but forces the allocation of a specific
buzbee67bf8852011-08-17 17:51:35 -0700541 * register. No check is made to see if the register was previously
542 * allocated. Use with caution.
543 */
buzbeefa57c472012-11-21 12:06:18 -0800544void LockTemp(CompilationUnit* cu, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700545{
buzbeefa57c472012-11-21 12:06:18 -0800546 RegisterInfo* p = cu->reg_pool->core_regs;
547 int num_regs = cu->reg_pool->num_core_regs;
Bill Buzbeea114add2012-05-03 15:00:40 -0700548 int i;
buzbeefa57c472012-11-21 12:06:18 -0800549 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 if (p[i].reg == reg) {
buzbeefa57c472012-11-21 12:06:18 -0800551 DCHECK(p[i].is_temp);
552 p[i].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700553 p[i].live = false;
554 return;
buzbee67bf8852011-08-17 17:51:35 -0700555 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 }
buzbeefa57c472012-11-21 12:06:18 -0800557 p = cu->reg_pool->FPRegs;
558 num_regs = cu->reg_pool->num_fp_regs;
559 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700560 if (p[i].reg == reg) {
buzbeefa57c472012-11-21 12:06:18 -0800561 DCHECK(p[i].is_temp);
562 p[i].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700563 p[i].live = false;
564 return;
buzbee67bf8852011-08-17 17:51:35 -0700565 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 }
567 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700568}
569
buzbeeaad94382012-11-21 07:40:50 -0800570static void ResetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700571{
buzbeefa57c472012-11-21 12:06:18 -0800572 p->def_start = NULL;
573 p->def_end = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700574}
575
buzbeefa57c472012-11-21 12:06:18 -0800576void ResetDef(CompilationUnit* cu, int reg)
buzbee5abfa3e2012-01-31 17:01:43 -0800577{
buzbee02031b12012-11-23 09:41:35 -0800578 Codegen* cg = cu->cg.get();
579 ResetDefBody(cg->GetRegInfo(cu, reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800580}
581
buzbeefa57c472012-11-21 12:06:18 -0800582static void NullifyRange(CompilationUnit* cu, LIR *start, LIR *finish, int s_reg1, int s_reg2)
buzbee67bf8852011-08-17 17:51:35 -0700583{
Bill Buzbeea114add2012-05-03 15:00:40 -0700584 if (start && finish) {
585 LIR *p;
buzbeefa57c472012-11-21 12:06:18 -0800586 DCHECK_EQ(s_reg1, s_reg2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700587 for (p = start; ;p = p->next) {
buzbee52a77fc2012-11-20 19:50:46 -0800588 NopLIR(p);
Bill Buzbeea114add2012-05-03 15:00:40 -0700589 if (p == finish)
590 break;
buzbee67bf8852011-08-17 17:51:35 -0700591 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700592 }
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 */
buzbeefa57c472012-11-21 12:06:18 -0800600void MarkDef(CompilationUnit* cu, 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);
buzbee02031b12012-11-23 09:41:35 -0800606 Codegen* cg = cu->cg.get();
607 RegisterInfo* p = cg->GetRegInfo(cu, rl.low_reg);
buzbeefa57c472012-11-21 12:06:18 -0800608 p->def_start = start->next;
609 p->def_end = finish;
buzbee67bf8852011-08-17 17:51:35 -0700610}
611
612/*
613 * Mark the beginning and end LIR of a def sequence. Note that
614 * on entry start points to the LIR prior to the beginning of the
615 * sequence.
616 */
buzbeefa57c472012-11-21 12:06:18 -0800617void MarkDefWide(CompilationUnit* cu, RegLocation rl,
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700619{
Bill Buzbeea114add2012-05-03 15:00:40 -0700620 DCHECK(rl.wide);
621 DCHECK(start && start->next);
622 DCHECK(finish);
buzbee02031b12012-11-23 09:41:35 -0800623 Codegen* cg = cu->cg.get();
624 RegisterInfo* p = cg->GetRegInfo(cu, rl.low_reg);
buzbeefa57c472012-11-21 12:06:18 -0800625 ResetDef(cu, rl.high_reg); // Only track low of pair
626 p->def_start = start->next;
627 p->def_end = finish;
buzbee67bf8852011-08-17 17:51:35 -0700628}
629
buzbeefa57c472012-11-21 12:06:18 -0800630RegLocation WideToNarrow(CompilationUnit* cu, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700631{
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 DCHECK(rl.wide);
buzbee02031b12012-11-23 09:41:35 -0800633 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700634 if (rl.location == kLocPhysReg) {
buzbee02031b12012-11-23 09:41:35 -0800635 RegisterInfo* info_lo = cg->GetRegInfo(cu, rl.low_reg);
636 RegisterInfo* info_hi = cg->GetRegInfo(cu, rl.high_reg);
buzbeefa57c472012-11-21 12:06:18 -0800637 if (info_lo->is_temp) {
638 info_lo->pair = false;
639 info_lo->def_start = NULL;
640 info_lo->def_end = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700641 }
buzbeefa57c472012-11-21 12:06:18 -0800642 if (info_hi->is_temp) {
643 info_hi->pair = false;
644 info_hi->def_start = NULL;
645 info_hi->def_end = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700646 }
647 }
648 rl.wide = false;
649 return rl;
buzbee67bf8852011-08-17 17:51:35 -0700650}
651
buzbeefa57c472012-11-21 12:06:18 -0800652void ResetDefLoc(CompilationUnit* cu, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700653{
Bill Buzbeea114add2012-05-03 15:00:40 -0700654 DCHECK(!rl.wide);
buzbeefa57c472012-11-21 12:06:18 -0800655 RegisterInfo* p = IsTemp(cu, rl.low_reg);
656 if (p && !(cu->disable_opt & (1 << kSuppressLoads))) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700657 DCHECK(!p->pair);
buzbeefa57c472012-11-21 12:06:18 -0800658 NullifyRange(cu, p->def_start, p->def_end, p->s_reg, rl.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 }
buzbeefa57c472012-11-21 12:06:18 -0800660 ResetDef(cu, rl.low_reg);
buzbee67bf8852011-08-17 17:51:35 -0700661}
662
buzbeefa57c472012-11-21 12:06:18 -0800663void ResetDefLocWide(CompilationUnit* cu, RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700664{
Bill Buzbeea114add2012-05-03 15:00:40 -0700665 DCHECK(rl.wide);
buzbeefa57c472012-11-21 12:06:18 -0800666 RegisterInfo* p_low = IsTemp(cu, rl.low_reg);
667 RegisterInfo* p_high = IsTemp(cu, rl.high_reg);
668 if (p_low && !(cu->disable_opt & (1 << kSuppressLoads))) {
669 DCHECK(p_low->pair);
670 NullifyRange(cu, p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700671 }
buzbeefa57c472012-11-21 12:06:18 -0800672 if (p_high && !(cu->disable_opt & (1 << kSuppressLoads))) {
673 DCHECK(p_high->pair);
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 }
buzbeefa57c472012-11-21 12:06:18 -0800675 ResetDef(cu, rl.low_reg);
676 ResetDef(cu, rl.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700677}
678
buzbeefa57c472012-11-21 12:06:18 -0800679void ResetDefTracking(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700680{
Bill Buzbeea114add2012-05-03 15:00:40 -0700681 int i;
buzbeefa57c472012-11-21 12:06:18 -0800682 for (i=0; i< cu->reg_pool->num_core_regs; i++) {
683 ResetDefBody(&cu->reg_pool->core_regs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 }
buzbeefa57c472012-11-21 12:06:18 -0800685 for (i=0; i< cu->reg_pool->num_fp_regs; i++) {
686 ResetDefBody(&cu->reg_pool->FPRegs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700687 }
buzbee67bf8852011-08-17 17:51:35 -0700688}
689
buzbeefa57c472012-11-21 12:06:18 -0800690void ClobberAllRegs(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700691{
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 int i;
buzbeefa57c472012-11-21 12:06:18 -0800693 for (i=0; i< cu->reg_pool->num_core_regs; i++) {
694 ClobberBody(cu, &cu->reg_pool->core_regs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700695 }
buzbeefa57c472012-11-21 12:06:18 -0800696 for (i=0; i< cu->reg_pool->num_fp_regs; i++) {
697 ClobberBody(cu, &cu->reg_pool->FPRegs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 }
buzbee67bf8852011-08-17 17:51:35 -0700699}
700
buzbee67bf8852011-08-17 17:51:35 -0700701// Make sure nothing is live and dirty
buzbeefa57c472012-11-21 12:06:18 -0800702static void FlushAllRegsBody(CompilationUnit* cu, RegisterInfo* info, int num_regs)
buzbee67bf8852011-08-17 17:51:35 -0700703{
buzbee02031b12012-11-23 09:41:35 -0800704 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700705 int i;
buzbeefa57c472012-11-21 12:06:18 -0800706 for (i=0; i < num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700707 if (info[i].live && info[i].dirty) {
708 if (info[i].pair) {
buzbee02031b12012-11-23 09:41:35 -0800709 cg->FlushRegWide(cu, info[i].reg, info[i].partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 } else {
buzbee02031b12012-11-23 09:41:35 -0800711 cg->FlushReg(cu, info[i].reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700712 }
buzbee67bf8852011-08-17 17:51:35 -0700713 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700714 }
buzbee67bf8852011-08-17 17:51:35 -0700715}
716
buzbeefa57c472012-11-21 12:06:18 -0800717void FlushAllRegs(CompilationUnit* cu)
buzbee67bf8852011-08-17 17:51:35 -0700718{
buzbeefa57c472012-11-21 12:06:18 -0800719 FlushAllRegsBody(cu, cu->reg_pool->core_regs,
720 cu->reg_pool->num_core_regs);
721 FlushAllRegsBody(cu, cu->reg_pool->FPRegs,
722 cu->reg_pool->num_fp_regs);
723 ClobberAllRegs(cu);
buzbee67bf8852011-08-17 17:51:35 -0700724}
725
726
727//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee02031b12012-11-23 09:41:35 -0800728static bool RegClassMatches(CompilationUnit* cu, int reg_class, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700729{
buzbee02031b12012-11-23 09:41:35 -0800730 Codegen* cg = cu->cg.get();
buzbeefa57c472012-11-21 12:06:18 -0800731 if (reg_class == kAnyReg) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700732 return true;
buzbeefa57c472012-11-21 12:06:18 -0800733 } else if (reg_class == kCoreReg) {
buzbee02031b12012-11-23 09:41:35 -0800734 return !cg->IsFpReg(reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700735 } else {
buzbee02031b12012-11-23 09:41:35 -0800736 return cg->IsFpReg(reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700737 }
buzbee67bf8852011-08-17 17:51:35 -0700738}
739
buzbeefa57c472012-11-21 12:06:18 -0800740void MarkLive(CompilationUnit* cu, int reg, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700741{
buzbee02031b12012-11-23 09:41:35 -0800742 Codegen* cg = cu->cg.get();
743 RegisterInfo* info = cg->GetRegInfo(cu, reg);
buzbeefa57c472012-11-21 12:06:18 -0800744 if ((info->reg == reg) && (info->s_reg == s_reg) && info->live) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700745 return; /* already live */
buzbeefa57c472012-11-21 12:06:18 -0800746 } else if (s_reg != INVALID_SREG) {
747 ClobberSReg(cu, s_reg);
748 if (info->is_temp) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700749 info->live = true;
buzbee67bf8852011-08-17 17:51:35 -0700750 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700751 } else {
buzbeefa57c472012-11-21 12:06:18 -0800752 /* Can't be live if no associated s_reg */
753 DCHECK(info->is_temp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 info->live = false;
755 }
buzbeefa57c472012-11-21 12:06:18 -0800756 info->s_reg = s_reg;
buzbee67bf8852011-08-17 17:51:35 -0700757}
758
buzbeefa57c472012-11-21 12:06:18 -0800759void MarkTemp(CompilationUnit* cu, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700760{
buzbee02031b12012-11-23 09:41:35 -0800761 Codegen* cg = cu->cg.get();
762 RegisterInfo* info = cg->GetRegInfo(cu, reg);
buzbeefa57c472012-11-21 12:06:18 -0800763 info->is_temp = true;
buzbee67bf8852011-08-17 17:51:35 -0700764}
765
buzbeefa57c472012-11-21 12:06:18 -0800766void UnmarkTemp(CompilationUnit* cu, int reg)
buzbee9e0f9b02011-08-24 15:32:46 -0700767{
buzbee02031b12012-11-23 09:41:35 -0800768 Codegen* cg = cu->cg.get();
769 RegisterInfo* info = cg->GetRegInfo(cu, reg);
buzbeefa57c472012-11-21 12:06:18 -0800770 info->is_temp = false;
buzbee9e0f9b02011-08-24 15:32:46 -0700771}
772
buzbeefa57c472012-11-21 12:06:18 -0800773void MarkPair(CompilationUnit* cu, int low_reg, int high_reg)
buzbee67bf8852011-08-17 17:51:35 -0700774{
buzbee02031b12012-11-23 09:41:35 -0800775 Codegen* cg = cu->cg.get();
776 RegisterInfo* info_lo = cg->GetRegInfo(cu, low_reg);
777 RegisterInfo* info_hi = cg->GetRegInfo(cu, high_reg);
buzbeefa57c472012-11-21 12:06:18 -0800778 info_lo->pair = info_hi->pair = true;
779 info_lo->partner = high_reg;
780 info_hi->partner = low_reg;
buzbee67bf8852011-08-17 17:51:35 -0700781}
782
buzbeefa57c472012-11-21 12:06:18 -0800783void MarkClean(CompilationUnit* cu, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700784{
buzbee02031b12012-11-23 09:41:35 -0800785 Codegen* cg = cu->cg.get();
786 RegisterInfo* info = cg->GetRegInfo(cu, loc.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700787 info->dirty = false;
788 if (loc.wide) {
buzbee02031b12012-11-23 09:41:35 -0800789 info = cg->GetRegInfo(cu, loc.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700790 info->dirty = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700791 }
buzbee67bf8852011-08-17 17:51:35 -0700792}
793
buzbeefa57c472012-11-21 12:06:18 -0800794void MarkDirty(CompilationUnit* cu, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700795{
Bill Buzbeea114add2012-05-03 15:00:40 -0700796 if (loc.home) {
797 // If already home, can't be dirty
798 return;
799 }
buzbee02031b12012-11-23 09:41:35 -0800800 Codegen* cg = cu->cg.get();
801 RegisterInfo* info = cg->GetRegInfo(cu, loc.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700802 info->dirty = true;
803 if (loc.wide) {
buzbee02031b12012-11-23 09:41:35 -0800804 info = cg->GetRegInfo(cu, loc.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700805 info->dirty = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700806 }
buzbee67bf8852011-08-17 17:51:35 -0700807}
808
buzbeefa57c472012-11-21 12:06:18 -0800809void MarkInUse(CompilationUnit* cu, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700810{
buzbee02031b12012-11-23 09:41:35 -0800811 Codegen* cg = cu->cg.get();
812 RegisterInfo* info = cg->GetRegInfo(cu, reg);
buzbeefa57c472012-11-21 12:06:18 -0800813 info->in_use = true;
buzbee67bf8852011-08-17 17:51:35 -0700814}
815
buzbeefa57c472012-11-21 12:06:18 -0800816static void CopyRegInfo(CompilationUnit* cu, int new_reg, int old_reg)
buzbee67bf8852011-08-17 17:51:35 -0700817{
buzbee02031b12012-11-23 09:41:35 -0800818 Codegen* cg = cu->cg.get();
819 RegisterInfo* new_info = cg->GetRegInfo(cu, new_reg);
820 RegisterInfo* old_info = cg->GetRegInfo(cu, old_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700821 // Target temp status must not change
buzbeefa57c472012-11-21 12:06:18 -0800822 bool is_temp = new_info->is_temp;
823 *new_info = *old_info;
Bill Buzbeea114add2012-05-03 15:00:40 -0700824 // Restore target's temp status
buzbeefa57c472012-11-21 12:06:18 -0800825 new_info->is_temp = is_temp;
826 new_info->reg = new_reg;
buzbee67bf8852011-08-17 17:51:35 -0700827}
828
buzbeefa57c472012-11-21 12:06:18 -0800829static bool CheckCorePoolSanity(CompilationUnit* cu)
buzbee6181f792011-09-29 11:14:04 -0700830{
buzbee02031b12012-11-23 09:41:35 -0800831 Codegen* cg = cu->cg.get();
buzbeefa57c472012-11-21 12:06:18 -0800832 for (static int i = 0; i < cu->reg_pool->num_core_regs; i++) {
833 if (cu->reg_pool->core_regs[i].pair) {
834 static int my_reg = cu->reg_pool->core_regs[i].reg;
835 static int my_sreg = cu->reg_pool->core_regs[i].s_reg;
836 static int partner_reg = cu->reg_pool->core_regs[i].partner;
buzbee02031b12012-11-23 09:41:35 -0800837 static RegisterInfo* partner = cg->GetRegInfo(cu, partner_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700838 DCHECK(partner != NULL);
839 DCHECK(partner->pair);
buzbeefa57c472012-11-21 12:06:18 -0800840 DCHECK_EQ(my_reg, partner->partner);
841 static int partner_sreg = partner->s_reg;
842 if (my_sreg == INVALID_SREG) {
843 DCHECK_EQ(partner_sreg, INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -0700844 } else {
buzbeefa57c472012-11-21 12:06:18 -0800845 int diff = my_sreg - partner_sreg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700846 DCHECK((diff == -1) || (diff == 1));
buzbee6181f792011-09-29 11:14:04 -0700847 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700848 }
buzbeefa57c472012-11-21 12:06:18 -0800849 if (!cu->reg_pool->core_regs[i].live) {
850 DCHECK(cu->reg_pool->core_regs[i].def_start == NULL);
851 DCHECK(cu->reg_pool->core_regs[i].def_end == NULL);
Bill Buzbeea114add2012-05-03 15:00:40 -0700852 }
buzbee6181f792011-09-29 11:14:04 -0700853 }
854 return true;
855}
856
buzbeeaad94382012-11-21 07:40:50 -0800857/*
858 * Return an updated location record with current in-register status.
859 * If the value lives in live temps, reflect that fact. No code
860 * is generated. If the live value is part of an older pair,
861 * clobber both low and high.
862 * TUNING: clobbering both is a bit heavy-handed, but the alternative
863 * is a bit complex when dealing with FP regs. Examine code to see
864 * if it's worthwhile trying to be more clever here.
865 */
866
buzbeefa57c472012-11-21 12:06:18 -0800867RegLocation UpdateLoc(CompilationUnit* cu, RegLocation loc)
buzbeeaad94382012-11-21 07:40:50 -0800868{
869 DCHECK(!loc.wide);
buzbeefa57c472012-11-21 12:06:18 -0800870 DCHECK(CheckCorePoolSanity(cu));
buzbeeaad94382012-11-21 07:40:50 -0800871 if (loc.location != kLocPhysReg) {
872 DCHECK((loc.location == kLocDalvikFrame) ||
873 (loc.location == kLocCompilerTemp));
buzbeefa57c472012-11-21 12:06:18 -0800874 RegisterInfo* info_lo = AllocLive(cu, loc.s_reg_low, kAnyReg);
875 if (info_lo) {
876 if (info_lo->pair) {
877 Clobber(cu, info_lo->reg);
878 Clobber(cu, info_lo->partner);
879 FreeTemp(cu, info_lo->reg);
buzbeeaad94382012-11-21 07:40:50 -0800880 } else {
buzbeefa57c472012-11-21 12:06:18 -0800881 loc.low_reg = info_lo->reg;
buzbeeaad94382012-11-21 07:40:50 -0800882 loc.location = kLocPhysReg;
883 }
884 }
885 }
886
887 return loc;
888}
889
buzbeefa57c472012-11-21 12:06:18 -0800890/* see comments for update_loc */
891RegLocation UpdateLocWide(CompilationUnit* cu, RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700892{
Bill Buzbeea114add2012-05-03 15:00:40 -0700893 DCHECK(loc.wide);
buzbeefa57c472012-11-21 12:06:18 -0800894 DCHECK(CheckCorePoolSanity(cu));
buzbee02031b12012-11-23 09:41:35 -0800895 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700896 if (loc.location != kLocPhysReg) {
897 DCHECK((loc.location == kLocDalvikFrame) ||
898 (loc.location == kLocCompilerTemp));
899 // Are the dalvik regs already live in physical registers?
buzbeefa57c472012-11-21 12:06:18 -0800900 RegisterInfo* info_lo = AllocLive(cu, loc.s_reg_low, kAnyReg);
901 RegisterInfo* info_hi = AllocLive(cu,
902 GetSRegHi(loc.s_reg_low), kAnyReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700903 bool match = true;
buzbeefa57c472012-11-21 12:06:18 -0800904 match = match && (info_lo != NULL);
905 match = match && (info_hi != NULL);
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 // Are they both core or both FP?
buzbee02031b12012-11-23 09:41:35 -0800907 match = match && (cg->IsFpReg(info_lo->reg) == cg->IsFpReg(info_hi->reg));
Bill Buzbeea114add2012-05-03 15:00:40 -0700908 // If a pair of floating point singles, are they properly aligned?
buzbee02031b12012-11-23 09:41:35 -0800909 if (match && cg->IsFpReg(info_lo->reg)) {
buzbeefa57c472012-11-21 12:06:18 -0800910 match &= ((info_lo->reg & 0x1) == 0);
911 match &= ((info_hi->reg - info_lo->reg) == 1);
buzbee67bf8852011-08-17 17:51:35 -0700912 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700913 // If previously used as a pair, it is the same pair?
buzbeefa57c472012-11-21 12:06:18 -0800914 if (match && (info_lo->pair || info_hi->pair)) {
915 match = (info_lo->pair == info_hi->pair);
916 match &= ((info_lo->reg == info_hi->partner) &&
917 (info_hi->reg == info_lo->partner));
Bill Buzbeea114add2012-05-03 15:00:40 -0700918 }
919 if (match) {
920 // Can reuse - update the register usage info
buzbeefa57c472012-11-21 12:06:18 -0800921 loc.low_reg = info_lo->reg;
922 loc.high_reg = info_hi->reg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700923 loc.location = kLocPhysReg;
buzbeefa57c472012-11-21 12:06:18 -0800924 MarkPair(cu, loc.low_reg, loc.high_reg);
buzbee02031b12012-11-23 09:41:35 -0800925 DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700926 return loc;
927 }
928 // Can't easily reuse - clobber and free any overlaps
buzbeefa57c472012-11-21 12:06:18 -0800929 if (info_lo) {
930 Clobber(cu, info_lo->reg);
931 FreeTemp(cu, info_lo->reg);
932 if (info_lo->pair)
933 Clobber(cu, info_lo->partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700934 }
buzbeefa57c472012-11-21 12:06:18 -0800935 if (info_hi) {
936 Clobber(cu, info_hi->reg);
937 FreeTemp(cu, info_hi->reg);
938 if (info_hi->pair)
939 Clobber(cu, info_hi->partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700940 }
941 }
942 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700943}
944
buzbeeed3e9302011-09-23 17:34:19 -0700945
946/* For use in cases we don't know (or care) width */
buzbeefa57c472012-11-21 12:06:18 -0800947RegLocation UpdateRawLoc(CompilationUnit* cu, RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700948{
Bill Buzbeea114add2012-05-03 15:00:40 -0700949 if (loc.wide)
buzbeefa57c472012-11-21 12:06:18 -0800950 return UpdateLocWide(cu, loc);
Bill Buzbeea114add2012-05-03 15:00:40 -0700951 else
buzbeefa57c472012-11-21 12:06:18 -0800952 return UpdateLoc(cu, loc);
buzbeeed3e9302011-09-23 17:34:19 -0700953}
954
buzbeefa57c472012-11-21 12:06:18 -0800955RegLocation EvalLocWide(CompilationUnit* cu, RegLocation loc, int reg_class, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700956{
Bill Buzbeea114add2012-05-03 15:00:40 -0700957 DCHECK(loc.wide);
buzbeefa57c472012-11-21 12:06:18 -0800958 int new_regs;
959 int low_reg;
960 int high_reg;
buzbee02031b12012-11-23 09:41:35 -0800961 Codegen* cg = cu->cg.get();
buzbee67bf8852011-08-17 17:51:35 -0700962
buzbeefa57c472012-11-21 12:06:18 -0800963 loc = UpdateLocWide(cu, loc);
buzbee67bf8852011-08-17 17:51:35 -0700964
Bill Buzbeea114add2012-05-03 15:00:40 -0700965 /* If already in registers, we can assume proper form. Right reg class? */
966 if (loc.location == kLocPhysReg) {
buzbee02031b12012-11-23 09:41:35 -0800967 DCHECK_EQ(cg->IsFpReg(loc.low_reg), cg->IsFpReg(loc.high_reg));
968 DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
969 if (!RegClassMatches(cu, reg_class, loc.low_reg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 /* Wrong register class. Reallocate and copy */
buzbee02031b12012-11-23 09:41:35 -0800971 new_regs = cg->AllocTypedTempPair(cu, loc.fp, reg_class);
buzbeefa57c472012-11-21 12:06:18 -0800972 low_reg = new_regs & 0xff;
973 high_reg = (new_regs >> 8) & 0xff;
buzbee02031b12012-11-23 09:41:35 -0800974 cg->OpRegCopyWide(cu, low_reg, high_reg, loc.low_reg, loc.high_reg);
buzbeefa57c472012-11-21 12:06:18 -0800975 CopyRegInfo(cu, low_reg, loc.low_reg);
976 CopyRegInfo(cu, high_reg, loc.high_reg);
977 Clobber(cu, loc.low_reg);
978 Clobber(cu, loc.high_reg);
979 loc.low_reg = low_reg;
980 loc.high_reg = high_reg;
981 MarkPair(cu, loc.low_reg, loc.high_reg);
buzbee02031b12012-11-23 09:41:35 -0800982 DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 }
buzbee67bf8852011-08-17 17:51:35 -0700984 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 }
986
buzbeefa57c472012-11-21 12:06:18 -0800987 DCHECK_NE(loc.s_reg_low, INVALID_SREG);
988 DCHECK_NE(GetSRegHi(loc.s_reg_low), INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -0700989
buzbee02031b12012-11-23 09:41:35 -0800990 new_regs = cg->AllocTypedTempPair(cu, loc.fp, reg_class);
buzbeefa57c472012-11-21 12:06:18 -0800991 loc.low_reg = new_regs & 0xff;
992 loc.high_reg = (new_regs >> 8) & 0xff;
Bill Buzbeea114add2012-05-03 15:00:40 -0700993
buzbeefa57c472012-11-21 12:06:18 -0800994 MarkPair(cu, loc.low_reg, loc.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 if (update) {
996 loc.location = kLocPhysReg;
buzbeefa57c472012-11-21 12:06:18 -0800997 MarkLive(cu, loc.low_reg, loc.s_reg_low);
998 MarkLive(cu, loc.high_reg, GetSRegHi(loc.s_reg_low));
Bill Buzbeea114add2012-05-03 15:00:40 -0700999 }
buzbee02031b12012-11-23 09:41:35 -08001000 DCHECK(!cg->IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -07001001 return loc;
buzbee67bf8852011-08-17 17:51:35 -07001002}
1003
buzbeefa57c472012-11-21 12:06:18 -08001004RegLocation EvalLoc(CompilationUnit* cu, RegLocation loc,
1005 int reg_class, bool update)
buzbee67bf8852011-08-17 17:51:35 -07001006{
buzbeefa57c472012-11-21 12:06:18 -08001007 int new_reg;
buzbee67bf8852011-08-17 17:51:35 -07001008
Bill Buzbeea114add2012-05-03 15:00:40 -07001009 if (loc.wide)
buzbeefa57c472012-11-21 12:06:18 -08001010 return EvalLocWide(cu, loc, reg_class, update);
buzbee67bf8852011-08-17 17:51:35 -07001011
buzbee02031b12012-11-23 09:41:35 -08001012 Codegen* cg = cu->cg.get();
buzbeefa57c472012-11-21 12:06:18 -08001013 loc = UpdateLoc(cu, loc);
buzbee67bf8852011-08-17 17:51:35 -07001014
Bill Buzbeea114add2012-05-03 15:00:40 -07001015 if (loc.location == kLocPhysReg) {
buzbee02031b12012-11-23 09:41:35 -08001016 if (!RegClassMatches(cu, reg_class, loc.low_reg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001017 /* Wrong register class. Realloc, copy and transfer ownership */
buzbee02031b12012-11-23 09:41:35 -08001018 new_reg = cg->AllocTypedTemp(cu, loc.fp, reg_class);
1019 cg->OpRegCopy(cu, new_reg, loc.low_reg);
buzbeefa57c472012-11-21 12:06:18 -08001020 CopyRegInfo(cu, new_reg, loc.low_reg);
1021 Clobber(cu, loc.low_reg);
1022 loc.low_reg = new_reg;
buzbee67bf8852011-08-17 17:51:35 -07001023 }
1024 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -07001025 }
1026
buzbeefa57c472012-11-21 12:06:18 -08001027 DCHECK_NE(loc.s_reg_low, INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -07001028
buzbee02031b12012-11-23 09:41:35 -08001029 new_reg = cg->AllocTypedTemp(cu, loc.fp, reg_class);
buzbeefa57c472012-11-21 12:06:18 -08001030 loc.low_reg = new_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001031
1032 if (update) {
1033 loc.location = kLocPhysReg;
buzbeefa57c472012-11-21 12:06:18 -08001034 MarkLive(cu, loc.low_reg, loc.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001035 }
1036 return loc;
buzbee67bf8852011-08-17 17:51:35 -07001037}
1038
buzbeefa57c472012-11-21 12:06:18 -08001039RegLocation GetRawSrc(CompilationUnit* cu, MIR* mir, int num)
buzbee67bf8852011-08-17 17:51:35 -07001040{
buzbeefa57c472012-11-21 12:06:18 -08001041 DCHECK(num < mir->ssa_rep->num_uses);
1042 RegLocation res = cu->reg_location[mir->ssa_rep->uses[num]];
buzbee15bf9802012-06-12 17:49:27 -07001043 return res;
1044}
buzbeeeaf09bc2012-11-15 14:51:41 -08001045
buzbeefa57c472012-11-21 12:06:18 -08001046RegLocation GetRawDest(CompilationUnit* cu, MIR* mir)
buzbee15bf9802012-06-12 17:49:27 -07001047{
buzbeefa57c472012-11-21 12:06:18 -08001048 DCHECK_GT(mir->ssa_rep->num_defs, 0);
1049 RegLocation res = cu->reg_location[mir->ssa_rep->defs[0]];
buzbee15bf9802012-06-12 17:49:27 -07001050 return res;
1051}
buzbeeeaf09bc2012-11-15 14:51:41 -08001052
buzbeefa57c472012-11-21 12:06:18 -08001053RegLocation GetDest(CompilationUnit* cu, MIR* mir)
buzbee15bf9802012-06-12 17:49:27 -07001054{
buzbeefa57c472012-11-21 12:06:18 -08001055 RegLocation res = GetRawDest(cu, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001056 DCHECK(!res.wide);
1057 return res;
buzbee67bf8852011-08-17 17:51:35 -07001058}
buzbeeeaf09bc2012-11-15 14:51:41 -08001059
buzbeefa57c472012-11-21 12:06:18 -08001060RegLocation GetSrc(CompilationUnit* cu, MIR* mir, int num)
buzbee67bf8852011-08-17 17:51:35 -07001061{
buzbeefa57c472012-11-21 12:06:18 -08001062 RegLocation res = GetRawSrc(cu, mir, num);
Bill Buzbeea114add2012-05-03 15:00:40 -07001063 DCHECK(!res.wide);
1064 return res;
buzbeee9a72f62011-09-04 17:59:07 -07001065}
buzbeeeaf09bc2012-11-15 14:51:41 -08001066
buzbeefa57c472012-11-21 12:06:18 -08001067RegLocation GetDestWide(CompilationUnit* cu, MIR* mir)
buzbeee9a72f62011-09-04 17:59:07 -07001068{
buzbeefa57c472012-11-21 12:06:18 -08001069 RegLocation res = GetRawDest(cu, mir);
Bill Buzbeea114add2012-05-03 15:00:40 -07001070 DCHECK(res.wide);
1071 return res;
buzbee67bf8852011-08-17 17:51:35 -07001072}
1073
buzbeefa57c472012-11-21 12:06:18 -08001074RegLocation GetSrcWide(CompilationUnit* cu, MIR* mir,
buzbee15bf9802012-06-12 17:49:27 -07001075 int low)
buzbee67bf8852011-08-17 17:51:35 -07001076{
buzbeefa57c472012-11-21 12:06:18 -08001077 RegLocation res = GetRawSrc(cu, mir, low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001078 DCHECK(res.wide);
1079 return res;
buzbee67bf8852011-08-17 17:51:35 -07001080}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001081
buzbeefa57c472012-11-21 12:06:18 -08001082/* USE SSA names to count references of base Dalvik v_regs. */
1083static void CountRefs(CompilationUnit *cu, BasicBlock* bb, RefCounts* core_counts,
1084 RefCounts* fp_counts)
buzbeee3acd072012-02-25 17:03:10 -08001085{
buzbeec7d1f912013-02-07 15:22:39 -08001086 // TUNING: this routine could use some tweaking.
buzbeefa57c472012-11-21 12:06:18 -08001087 if ((cu->disable_opt & (1 << kPromoteRegs)) ||
1088 !((bb->block_type == kEntryBlock) || (bb->block_type == kExitBlock) ||
1089 (bb->block_type == kDalvikByteCode))) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001090 return;
1091 }
buzbee311ca162013-02-28 15:56:43 -08001092 for (int i = 0; i < cu->mir_graph->GetNumSSARegs(); i++) {
buzbeefa57c472012-11-21 12:06:18 -08001093 RegLocation loc = cu->reg_location[i];
1094 RefCounts* counts = loc.fp ? fp_counts : core_counts;
1095 int p_map_idx = SRegToPMap(cu, loc.s_reg_low);
buzbee4ef3e452012-12-14 13:35:28 -08001096 //Don't count easily regenerated immediates
buzbeec7d1f912013-02-07 15:22:39 -08001097 if (loc.fp || !IsInexpensiveConstant(cu, loc)) {
buzbee311ca162013-02-28 15:56:43 -08001098 counts[p_map_idx].count += cu->mir_graph->GetUseCount(i);
buzbee239c4e72012-03-16 08:42:29 -07001099 }
buzbeec7d1f912013-02-07 15:22:39 -08001100 if (loc.wide && loc.fp && !loc.high_word) {
1101 counts[p_map_idx].double_start = true;
buzbeee3acd072012-02-25 17:03:10 -08001102 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001103 }
buzbeee3acd072012-02-25 17:03:10 -08001104}
1105
1106/* qsort callback function, sort descending */
buzbeeaad94382012-11-21 07:40:50 -08001107static int SortCounts(const void *val1, const void *val2)
buzbeee3acd072012-02-25 17:03:10 -08001108{
buzbeecbd6d442012-11-17 14:11:25 -08001109 const RefCounts* op1 = reinterpret_cast<const RefCounts*>(val1);
1110 const RefCounts* op2 = reinterpret_cast<const RefCounts*>(val2);
Bill Buzbeea114add2012-05-03 15:00:40 -07001111 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
buzbeee3acd072012-02-25 17:03:10 -08001112}
1113
buzbeeaad94382012-11-21 07:40:50 -08001114static void DumpCounts(const RefCounts* arr, int size, const char* msg)
buzbeee3acd072012-02-25 17:03:10 -08001115{
Bill Buzbeea114add2012-05-03 15:00:40 -07001116 LOG(INFO) << msg;
1117 for (int i = 0; i < size; i++) {
buzbeefa57c472012-11-21 12:06:18 -08001118 LOG(INFO) << "s_reg[" << arr[i].s_reg << "]: " << arr[i].count;
Bill Buzbeea114add2012-05-03 15:00:40 -07001119 }
buzbeee3acd072012-02-25 17:03:10 -08001120}
1121
1122/*
1123 * Note: some portions of this code required even if the kPromoteRegs
1124 * optimization is disabled.
1125 */
buzbeefa57c472012-11-21 12:06:18 -08001126void DoPromotion(CompilationUnit* cu)
buzbeee3acd072012-02-25 17:03:10 -08001127{
buzbee02031b12012-11-23 09:41:35 -08001128 Codegen* cg = cu->cg.get();
buzbeefa57c472012-11-21 12:06:18 -08001129 int reg_bias = cu->num_compiler_temps + 1;
1130 int dalvik_regs = cu->num_dalvik_registers;
1131 int num_regs = dalvik_regs + reg_bias;
1132 const int promotion_threshold = 2;
buzbeee3acd072012-02-25 17:03:10 -08001133
Bill Buzbeea114add2012-05-03 15:00:40 -07001134 // Allow target code to add any special registers
buzbee02031b12012-11-23 09:41:35 -08001135 cg->AdjustSpillMask(cu);
buzbeee3acd072012-02-25 17:03:10 -08001136
Bill Buzbeea114add2012-05-03 15:00:40 -07001137 /*
1138 * Simple register promotion. Just do a static count of the uses
1139 * of Dalvik registers. Note that we examine the SSA names, but
1140 * count based on original Dalvik register name. Count refs
1141 * separately based on type in order to give allocation
1142 * preference to fp doubles - which must be allocated sequential
1143 * physical single fp registers started with an even-numbered
1144 * reg.
1145 * TUNING: replace with linear scan once we have the ability
1146 * to describe register live ranges for GC.
1147 */
buzbeefa57c472012-11-21 12:06:18 -08001148 RefCounts *core_regs = static_cast<RefCounts*>(NewMem(cu, sizeof(RefCounts) * num_regs,
buzbeecbd6d442012-11-17 14:11:25 -08001149 true, kAllocRegAlloc));
buzbeefa57c472012-11-21 12:06:18 -08001150 RefCounts *FpRegs = static_cast<RefCounts *>(NewMem(cu, sizeof(RefCounts) * num_regs,
buzbeecbd6d442012-11-17 14:11:25 -08001151 true, kAllocRegAlloc));
Bill Buzbeea114add2012-05-03 15:00:40 -07001152 // Set ssa names for original Dalvik registers
buzbeefa57c472012-11-21 12:06:18 -08001153 for (int i = 0; i < dalvik_regs; i++) {
1154 core_regs[i].s_reg = FpRegs[i].s_reg = i;
Bill Buzbeea114add2012-05-03 15:00:40 -07001155 }
1156 // Set ssa name for Method*
buzbeefa57c472012-11-21 12:06:18 -08001157 core_regs[dalvik_regs].s_reg = cu->method_sreg;
1158 FpRegs[dalvik_regs].s_reg = cu->method_sreg; // For consistecy
1159 // Set ssa names for compiler_temps
1160 for (int i = 1; i <= cu->num_compiler_temps; i++) {
1161 CompilerTemp* ct = reinterpret_cast<CompilerTemp*>(cu->compiler_temps.elem_list[i]);
1162 core_regs[dalvik_regs + i].s_reg = ct->s_reg;
1163 FpRegs[dalvik_regs + i].s_reg = ct->s_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001164 }
1165
buzbee311ca162013-02-28 15:56:43 -08001166 GrowableListIterator iterator = cu->mir_graph->GetBasicBlockIterator();
Bill Buzbeea114add2012-05-03 15:00:40 -07001167 while (true) {
1168 BasicBlock* bb;
buzbee52a77fc2012-11-20 19:50:46 -08001169 bb = reinterpret_cast<BasicBlock*>(GrowableListIteratorNext(&iterator));
Bill Buzbeea114add2012-05-03 15:00:40 -07001170 if (bb == NULL) break;
buzbeefa57c472012-11-21 12:06:18 -08001171 CountRefs(cu, bb, core_regs, FpRegs);
Bill Buzbeea114add2012-05-03 15:00:40 -07001172 }
1173
1174 /*
1175 * Ideally, we'd allocate doubles starting with an even-numbered
1176 * register. Bias the counts to try to allocate any vreg that's
1177 * used as the start of a pair first.
1178 */
buzbeefa57c472012-11-21 12:06:18 -08001179 for (int i = 0; i < num_regs; i++) {
1180 if (FpRegs[i].double_start) {
buzbee52a77fc2012-11-20 19:50:46 -08001181 FpRegs[i].count *= 2;
buzbeee3acd072012-02-25 17:03:10 -08001182 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001183 }
1184
1185 // Sort the count arrays
buzbeefa57c472012-11-21 12:06:18 -08001186 qsort(core_regs, num_regs, sizeof(RefCounts), SortCounts);
1187 qsort(FpRegs, num_regs, sizeof(RefCounts), SortCounts);
Bill Buzbeea114add2012-05-03 15:00:40 -07001188
buzbeefa57c472012-11-21 12:06:18 -08001189 if (cu->verbose) {
1190 DumpCounts(core_regs, num_regs, "Core regs after sort");
1191 DumpCounts(FpRegs, num_regs, "Fp regs after sort");
Bill Buzbeea114add2012-05-03 15:00:40 -07001192 }
1193
buzbeefa57c472012-11-21 12:06:18 -08001194 if (!(cu->disable_opt & (1 << kPromoteRegs))) {
buzbee52a77fc2012-11-20 19:50:46 -08001195 // Promote FpRegs
buzbeefa57c472012-11-21 12:06:18 -08001196 for (int i = 0; (i < num_regs) &&
1197 (FpRegs[i].count >= promotion_threshold ); i++) {
1198 int p_map_idx = SRegToPMap(cu, FpRegs[i].s_reg);
1199 if (cu->promotion_map[p_map_idx].fp_location != kLocPhysReg) {
1200 int reg = AllocPreservedFPReg(cu, FpRegs[i].s_reg,
1201 FpRegs[i].double_start);
Bill Buzbeea114add2012-05-03 15:00:40 -07001202 if (reg < 0) {
1203 break; // No more left
1204 }
1205 }
buzbee239c4e72012-03-16 08:42:29 -07001206 }
buzbee9c044ce2012-03-18 13:24:07 -07001207
Bill Buzbeea114add2012-05-03 15:00:40 -07001208 // Promote core regs
buzbeefa57c472012-11-21 12:06:18 -08001209 for (int i = 0; (i < num_regs) &&
1210 (core_regs[i].count > promotion_threshold); i++) {
1211 int p_map_idx = SRegToPMap(cu, core_regs[i].s_reg);
1212 if (cu->promotion_map[p_map_idx].core_location !=
Bill Buzbeea114add2012-05-03 15:00:40 -07001213 kLocPhysReg) {
buzbeefa57c472012-11-21 12:06:18 -08001214 int reg = AllocPreservedCoreReg(cu, core_regs[i].s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -07001215 if (reg < 0) {
1216 break; // No more left
1217 }
1218 }
buzbeee3acd072012-02-25 17:03:10 -08001219 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001220 }
buzbeee3acd072012-02-25 17:03:10 -08001221
Bill Buzbeea114add2012-05-03 15:00:40 -07001222 // Now, update SSA names to new home locations
buzbee311ca162013-02-28 15:56:43 -08001223 for (int i = 0; i < cu->mir_graph->GetNumSSARegs(); i++) {
buzbeefa57c472012-11-21 12:06:18 -08001224 RegLocation *curr = &cu->reg_location[i];
1225 int p_map_idx = SRegToPMap(cu, curr->s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001226 if (!curr->wide) {
1227 if (curr->fp) {
buzbeefa57c472012-11-21 12:06:18 -08001228 if (cu->promotion_map[p_map_idx].fp_location == kLocPhysReg) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001229 curr->location = kLocPhysReg;
buzbeefa57c472012-11-21 12:06:18 -08001230 curr->low_reg = cu->promotion_map[p_map_idx].FpReg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001231 curr->home = true;
1232 }
1233 } else {
buzbeefa57c472012-11-21 12:06:18 -08001234 if (cu->promotion_map[p_map_idx].core_location == kLocPhysReg) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001235 curr->location = kLocPhysReg;
buzbeefa57c472012-11-21 12:06:18 -08001236 curr->low_reg = cu->promotion_map[p_map_idx].core_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001237 curr->home = true;
1238 }
1239 }
buzbeefa57c472012-11-21 12:06:18 -08001240 curr->high_reg = INVALID_REG;
Bill Buzbeea114add2012-05-03 15:00:40 -07001241 } else {
buzbeefa57c472012-11-21 12:06:18 -08001242 if (curr->high_word) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001243 continue;
1244 }
1245 if (curr->fp) {
buzbeefa57c472012-11-21 12:06:18 -08001246 if ((cu->promotion_map[p_map_idx].fp_location == kLocPhysReg) &&
1247 (cu->promotion_map[p_map_idx+1].fp_location ==
Bill Buzbeea114add2012-05-03 15:00:40 -07001248 kLocPhysReg)) {
buzbeefa57c472012-11-21 12:06:18 -08001249 int low_reg = cu->promotion_map[p_map_idx].FpReg;
1250 int high_reg = cu->promotion_map[p_map_idx+1].FpReg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001251 // Doubles require pair of singles starting at even reg
buzbeefa57c472012-11-21 12:06:18 -08001252 if (((low_reg & 0x1) == 0) && ((low_reg + 1) == high_reg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001253 curr->location = kLocPhysReg;
buzbeefa57c472012-11-21 12:06:18 -08001254 curr->low_reg = low_reg;
1255 curr->high_reg = high_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001256 curr->home = true;
1257 }
1258 }
1259 } else {
buzbeefa57c472012-11-21 12:06:18 -08001260 if ((cu->promotion_map[p_map_idx].core_location == kLocPhysReg)
1261 && (cu->promotion_map[p_map_idx+1].core_location ==
Bill Buzbeea114add2012-05-03 15:00:40 -07001262 kLocPhysReg)) {
1263 curr->location = kLocPhysReg;
buzbeefa57c472012-11-21 12:06:18 -08001264 curr->low_reg = cu->promotion_map[p_map_idx].core_reg;
1265 curr->high_reg = cu->promotion_map[p_map_idx+1].core_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001266 curr->home = true;
1267 }
1268 }
buzbeee3acd072012-02-25 17:03:10 -08001269 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001270 }
buzbeefa57c472012-11-21 12:06:18 -08001271 if (cu->verbose) {
1272 DumpPromotionMap(cu);
buzbeeca7a5e42012-08-20 11:12:18 -07001273 }
buzbeee3acd072012-02-25 17:03:10 -08001274}
1275
1276/* Returns sp-relative offset in bytes for a VReg */
buzbeefa57c472012-11-21 12:06:18 -08001277int VRegOffset(CompilationUnit* cu, int v_reg)
buzbeee3acd072012-02-25 17:03:10 -08001278{
buzbeefa57c472012-11-21 12:06:18 -08001279 return StackVisitor::GetVRegOffset(cu->code_item, cu->core_spill_mask,
1280 cu->fp_spill_mask, cu->frame_size, v_reg);
buzbeee3acd072012-02-25 17:03:10 -08001281}
1282
1283/* Returns sp-relative offset in bytes for a SReg */
buzbeefa57c472012-11-21 12:06:18 -08001284int SRegOffset(CompilationUnit* cu, int s_reg)
buzbeee3acd072012-02-25 17:03:10 -08001285{
buzbee311ca162013-02-28 15:56:43 -08001286 return VRegOffset(cu, cu->mir_graph->SRegToVReg(s_reg));
buzbeee3acd072012-02-25 17:03:10 -08001287}
1288
buzbee02031b12012-11-23 09:41:35 -08001289RegLocation GetBadLoc()
1290{
1291 RegLocation res = bad_loc;
1292 return res;
1293}
1294
1295/* Mark register usage state and return long retloc */
1296RegLocation GetReturnWide(CompilationUnit* cu, bool is_double)
1297{
1298 Codegen* cg = cu->cg.get();
1299 RegLocation gpr_res = cg->LocCReturnWide();
1300 RegLocation fpr_res = cg->LocCReturnDouble();
1301 RegLocation res = is_double ? fpr_res : gpr_res;
1302 Clobber(cu, res.low_reg);
1303 Clobber(cu, res.high_reg);
1304 LockTemp(cu, res.low_reg);
1305 LockTemp(cu, res.high_reg);
1306 MarkPair(cu, res.low_reg, res.high_reg);
1307 return res;
1308}
1309
1310RegLocation GetReturn(CompilationUnit* cu, bool is_float)
1311{
1312 Codegen* cg = cu->cg.get();
1313 RegLocation gpr_res = cg->LocCReturn();
1314 RegLocation fpr_res = cg->LocCReturnFloat();
1315 RegLocation res = is_float ? fpr_res : gpr_res;
1316 Clobber(cu, res.low_reg);
1317 if (cu->instruction_set == kMips) {
1318 MarkInUse(cu, res.low_reg);
1319 } else {
1320 LockTemp(cu, res.low_reg);
1321 }
1322 return res;
1323}
1324
buzbee311ca162013-02-28 15:56:43 -08001325void Codegen::SimpleRegAlloc(CompilationUnit* cu)
1326{
1327 DoPromotion(cu);
1328
1329 /* Get easily-accessable post-promotion copy of RegLocation for Method* */
1330 cu->method_loc = cu->reg_location[cu->method_sreg];
1331
1332 if (cu->verbose && !(cu->disable_opt & (1 << kPromoteRegs))) {
1333 LOG(INFO) << "After Promotion";
1334 cu->mir_graph->DumpRegLocTable(cu->reg_location, cu->mir_graph->GetNumSSARegs());
1335 }
1336
1337 /* Set the frame size */
1338 cu->frame_size = cu->mir_graph->ComputeFrameSize();
1339}
1340
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001341} // namespace art