blob: dd389146ad7076277c5d906c40b7c58cf7288a28 [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"
buzbee67bf8852011-08-17 17:51:35 -070021
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080022namespace art {
23
buzbee67bf8852011-08-17 17:51:35 -070024/*
25 * Free all allocated temps in the temp pools. Note that this does
26 * not affect the "liveness" of a temp register, which will stay
27 * live until it is either explicitly killed or reallocated.
28 */
buzbee1fd33462013-03-25 13:40:45 -070029void Mir2Lir::ResetRegPool()
buzbee67bf8852011-08-17 17:51:35 -070030{
Bill Buzbeea114add2012-05-03 15:00:40 -070031 int i;
buzbee1fd33462013-03-25 13:40:45 -070032 for (i=0; i < reg_pool_->num_core_regs; i++) {
33 if (reg_pool_->core_regs[i].is_temp)
34 reg_pool_->core_regs[i].in_use = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070035 }
buzbee1fd33462013-03-25 13:40:45 -070036 for (i=0; i < reg_pool_->num_fp_regs; i++) {
37 if (reg_pool_->FPRegs[i].is_temp)
38 reg_pool_->FPRegs[i].in_use = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070039 }
buzbee67bf8852011-08-17 17:51:35 -070040}
41
buzbeee3acd072012-02-25 17:03:10 -080042 /*
43 * Set up temp & preserved register pools specialized by target.
buzbeefa57c472012-11-21 12:06:18 -080044 * Note: num_regs may be zero.
buzbeee3acd072012-02-25 17:03:10 -080045 */
buzbee1fd33462013-03-25 13:40:45 -070046void Mir2Lir::CompilerInitPool(RegisterInfo* regs, int* reg_nums, int num)
buzbee67bf8852011-08-17 17:51:35 -070047{
Bill Buzbeea114add2012-05-03 15:00:40 -070048 int i;
49 for (i=0; i < num; i++) {
buzbeefa57c472012-11-21 12:06:18 -080050 regs[i].reg = reg_nums[i];
51 regs[i].in_use = false;
52 regs[i].is_temp = false;
Bill Buzbeea114add2012-05-03 15:00:40 -070053 regs[i].pair = false;
54 regs[i].live = false;
55 regs[i].dirty = false;
buzbeefa57c472012-11-21 12:06:18 -080056 regs[i].s_reg = INVALID_SREG;
Bill Buzbeea114add2012-05-03 15:00:40 -070057 }
buzbee67bf8852011-08-17 17:51:35 -070058}
59
buzbee1fd33462013-03-25 13:40:45 -070060void Mir2Lir::DumpRegPool(RegisterInfo* p, int num_regs)
buzbee67bf8852011-08-17 17:51:35 -070061{
Bill Buzbeea114add2012-05-03 15:00:40 -070062 LOG(INFO) << "================================================";
buzbeefa57c472012-11-21 12:06:18 -080063 for (int i = 0; i < num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -070064 LOG(INFO) << StringPrintf(
65 "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 -080066 p[i].reg, p[i].is_temp, p[i].in_use, p[i].pair, p[i].partner,
67 p[i].live, p[i].dirty, p[i].s_reg, reinterpret_cast<uintptr_t>(p[i].def_start),
68 reinterpret_cast<uintptr_t>(p[i].def_end));
Bill Buzbeea114add2012-05-03 15:00:40 -070069 }
70 LOG(INFO) << "================================================";
buzbee67bf8852011-08-17 17:51:35 -070071}
72
buzbee1fd33462013-03-25 13:40:45 -070073void Mir2Lir::DumpCoreRegPool()
buzbee6181f792011-09-29 11:14:04 -070074{
buzbee1fd33462013-03-25 13:40:45 -070075 DumpRegPool(reg_pool_->core_regs, reg_pool_->num_core_regs);
buzbee6181f792011-09-29 11:14:04 -070076}
77
buzbee1fd33462013-03-25 13:40:45 -070078void Mir2Lir::DumpFpRegPool()
buzbee6181f792011-09-29 11:14:04 -070079{
buzbee1fd33462013-03-25 13:40:45 -070080 DumpRegPool(reg_pool_->FPRegs, reg_pool_->num_fp_regs);
buzbee6181f792011-09-29 11:14:04 -070081}
82
buzbee67bf8852011-08-17 17:51:35 -070083/* Mark a temp register as dead. Does not affect allocation state. */
buzbee1fd33462013-03-25 13:40:45 -070084void Mir2Lir::ClobberBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -070085{
buzbeefa57c472012-11-21 12:06:18 -080086 if (p->is_temp) {
Bill Buzbeea114add2012-05-03 15:00:40 -070087 DCHECK(!(p->live && p->dirty)) << "Live & dirty temp in clobber";
88 p->live = false;
buzbeefa57c472012-11-21 12:06:18 -080089 p->s_reg = INVALID_SREG;
90 p->def_start = NULL;
91 p->def_end = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -070092 if (p->pair) {
93 p->pair = false;
buzbee1fd33462013-03-25 13:40:45 -070094 Clobber(p->partner);
buzbee67bf8852011-08-17 17:51:35 -070095 }
Bill Buzbeea114add2012-05-03 15:00:40 -070096 }
buzbee67bf8852011-08-17 17:51:35 -070097}
98
buzbee5abfa3e2012-01-31 17:01:43 -080099/* Mark a temp register as dead. Does not affect allocation state. */
buzbee1fd33462013-03-25 13:40:45 -0700100void Mir2Lir::Clobber(int reg)
buzbee5abfa3e2012-01-31 17:01:43 -0800101{
buzbee1fd33462013-03-25 13:40:45 -0700102 ClobberBody(GetRegInfo(reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800103}
104
buzbee1fd33462013-03-25 13:40:45 -0700105void Mir2Lir::ClobberSRegBody(RegisterInfo* p, int num_regs, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700106{
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 int i;
buzbeefa57c472012-11-21 12:06:18 -0800108 for (i=0; i< num_regs; i++) {
109 if (p[i].s_reg == s_reg) {
110 if (p[i].is_temp) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 p[i].live = false;
112 }
buzbeefa57c472012-11-21 12:06:18 -0800113 p[i].def_start = NULL;
114 p[i].def_end = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700115 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700116 }
buzbee67bf8852011-08-17 17:51:35 -0700117}
118
buzbee078fa452012-12-03 15:51:33 -0800119/*
120 * Break the association between a Dalvik vreg and a physical temp register of either register
121 * class.
122 * TODO: Ideally, the public version of this code should not exist. Besides its local usage
123 * in the register utilities, is is also used by code gen routines to work around a deficiency in
124 * local register allocation, which fails to distinguish between the "in" and "out" identities
125 * of Dalvik vregs. This can result in useless register copies when the same Dalvik vreg
126 * is used both as the source and destination register of an operation in which the type
127 * changes (for example: INT_TO_FLOAT v1, v1). Revisit when improved register allocation is
128 * addressed.
129 */
buzbee1fd33462013-03-25 13:40:45 -0700130void Mir2Lir::ClobberSReg(int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700131{
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 /* Reset live temp tracking sanity checker */
buzbee311ca162013-02-28 15:56:43 -0800133 if (kIsDebugBuild) {
buzbee1fd33462013-03-25 13:40:45 -0700134 if (s_reg == live_sreg_) {
135 live_sreg_ = INVALID_SREG;
buzbee311ca162013-02-28 15:56:43 -0800136 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 }
buzbee1fd33462013-03-25 13:40:45 -0700138 ClobberSRegBody(reg_pool_->core_regs, reg_pool_->num_core_regs, s_reg);
139 ClobberSRegBody(reg_pool_->FPRegs, reg_pool_->num_fp_regs, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700140}
141
buzbee9c044ce2012-03-18 13:24:07 -0700142/*
143 * SSA names associated with the initial definitions of Dalvik
144 * registers are the same as the Dalvik register number (and
buzbeefa57c472012-11-21 12:06:18 -0800145 * thus take the same position in the promotion_map. However,
buzbee9c044ce2012-03-18 13:24:07 -0700146 * the special Method* and compiler temp resisters use negative
buzbeefa57c472012-11-21 12:06:18 -0800147 * v_reg numbers to distinguish them and can have an arbitrary
buzbee9c044ce2012-03-18 13:24:07 -0700148 * ssa name (above the last original Dalvik register). This function
buzbeefa57c472012-11-21 12:06:18 -0800149 * maps SSA names to positions in the promotion_map array.
buzbee9c044ce2012-03-18 13:24:07 -0700150 */
buzbee1fd33462013-03-25 13:40:45 -0700151int Mir2Lir::SRegToPMap(int s_reg)
buzbeee1965672012-03-11 18:39:19 -0700152{
buzbee1fd33462013-03-25 13:40:45 -0700153 DCHECK_LT(s_reg, mir_graph_->GetNumSSARegs());
buzbeefa57c472012-11-21 12:06:18 -0800154 DCHECK_GE(s_reg, 0);
buzbee1fd33462013-03-25 13:40:45 -0700155 int v_reg = mir_graph_->SRegToVReg(s_reg);
buzbeefa57c472012-11-21 12:06:18 -0800156 if (v_reg >= 0) {
buzbee1fd33462013-03-25 13:40:45 -0700157 DCHECK_LT(v_reg, cu_->num_dalvik_registers);
buzbeefa57c472012-11-21 12:06:18 -0800158 return v_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 } else {
buzbeefa57c472012-11-21 12:06:18 -0800160 int pos = std::abs(v_reg) - std::abs(SSA_METHOD_BASEREG);
buzbee1fd33462013-03-25 13:40:45 -0700161 DCHECK_LE(pos, cu_->num_compiler_temps);
162 return cu_->num_dalvik_registers + pos;
Bill Buzbeea114add2012-05-03 15:00:40 -0700163 }
buzbeee1965672012-03-11 18:39:19 -0700164}
165
buzbee1fd33462013-03-25 13:40:45 -0700166void Mir2Lir::RecordCorePromotion(int reg, int s_reg)
buzbeeca7a5e42012-08-20 11:12:18 -0700167{
buzbee1fd33462013-03-25 13:40:45 -0700168 int p_map_idx = SRegToPMap(s_reg);
169 int v_reg = mir_graph_->SRegToVReg(s_reg);
170 GetRegInfo(reg)->in_use = true;
171 core_spill_mask_ |= (1 << reg);
buzbeeca7a5e42012-08-20 11:12:18 -0700172 // Include reg for later sort
buzbee1fd33462013-03-25 13:40:45 -0700173 core_vmap_table_.push_back(reg << VREG_NUM_WIDTH | (v_reg & ((1 << VREG_NUM_WIDTH) - 1)));
174 num_core_spills_++;
175 promotion_map_[p_map_idx].core_location = kLocPhysReg;
176 promotion_map_[p_map_idx].core_reg = reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700177}
178
buzbee67bf8852011-08-17 17:51:35 -0700179/* Reserve a callee-save register. Return -1 if none available */
buzbee1fd33462013-03-25 13:40:45 -0700180int Mir2Lir::AllocPreservedCoreReg(int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700181{
Bill Buzbeea114add2012-05-03 15:00:40 -0700182 int res = -1;
buzbee1fd33462013-03-25 13:40:45 -0700183 RegisterInfo* core_regs = reg_pool_->core_regs;
184 for (int i = 0; i < reg_pool_->num_core_regs; i++) {
buzbeefa57c472012-11-21 12:06:18 -0800185 if (!core_regs[i].is_temp && !core_regs[i].in_use) {
186 res = core_regs[i].reg;
buzbee1fd33462013-03-25 13:40:45 -0700187 RecordCorePromotion(res, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700188 break;
buzbee67bf8852011-08-17 17:51:35 -0700189 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 }
191 return res;
buzbee67bf8852011-08-17 17:51:35 -0700192}
193
buzbee1fd33462013-03-25 13:40:45 -0700194void Mir2Lir::RecordFpPromotion(int reg, int s_reg)
buzbeeca7a5e42012-08-20 11:12:18 -0700195{
buzbee1fd33462013-03-25 13:40:45 -0700196 int p_map_idx = SRegToPMap(s_reg);
197 int v_reg = mir_graph_->SRegToVReg(s_reg);
198 GetRegInfo(reg)->in_use = true;
199 MarkPreservedSingle(v_reg, reg);
200 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
201 promotion_map_[p_map_idx].FpReg = reg;
buzbeeca7a5e42012-08-20 11:12:18 -0700202}
203
buzbee67bf8852011-08-17 17:51:35 -0700204/*
205 * Reserve a callee-save fp single register. Try to fullfill request for
206 * even/odd allocation, but go ahead and allocate anything if not
207 * available. If nothing's available, return -1.
208 */
buzbee1fd33462013-03-25 13:40:45 -0700209int Mir2Lir::AllocPreservedSingle(int s_reg, bool even)
buzbee67bf8852011-08-17 17:51:35 -0700210{
Bill Buzbeea114add2012-05-03 15:00:40 -0700211 int res = -1;
buzbee1fd33462013-03-25 13:40:45 -0700212 RegisterInfo* FPRegs = reg_pool_->FPRegs;
213 for (int i = 0; i < reg_pool_->num_fp_regs; i++) {
buzbeefa57c472012-11-21 12:06:18 -0800214 if (!FPRegs[i].is_temp && !FPRegs[i].in_use &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 ((FPRegs[i].reg & 0x1) == 0) == even) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700216 res = FPRegs[i].reg;
buzbee1fd33462013-03-25 13:40:45 -0700217 RecordFpPromotion(res, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 break;
buzbee67bf8852011-08-17 17:51:35 -0700219 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700220 }
221 return res;
buzbee67bf8852011-08-17 17:51:35 -0700222}
223
224/*
225 * Somewhat messy code here. We want to allocate a pair of contiguous
226 * physical single-precision floating point registers starting with
buzbeefa57c472012-11-21 12:06:18 -0800227 * an even numbered reg. It is possible that the paired s_reg (s_reg+1)
buzbee67bf8852011-08-17 17:51:35 -0700228 * has already been allocated - try to fit if possible. Fail to
229 * allocate if we can't meet the requirements for the pair of
buzbeefa57c472012-11-21 12:06:18 -0800230 * s_reg<=sX[even] & (s_reg+1)<= sX+1.
buzbee67bf8852011-08-17 17:51:35 -0700231 */
buzbee1fd33462013-03-25 13:40:45 -0700232int Mir2Lir::AllocPreservedDouble(int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700233{
Bill Buzbeea114add2012-05-03 15:00:40 -0700234 int res = -1; // Assume failure
buzbee1fd33462013-03-25 13:40:45 -0700235 int v_reg = mir_graph_->SRegToVReg(s_reg);
236 int p_map_idx = SRegToPMap(s_reg);
237 if (promotion_map_[p_map_idx+1].fp_location == kLocPhysReg) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700238 // Upper reg is already allocated. Can we fit?
buzbee1fd33462013-03-25 13:40:45 -0700239 int high_reg = promotion_map_[p_map_idx+1].FpReg;
buzbeefa57c472012-11-21 12:06:18 -0800240 if ((high_reg & 1) == 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 // High reg is even - fail.
242 return res;
243 }
244 // Is the low reg of the pair free?
buzbee1fd33462013-03-25 13:40:45 -0700245 RegisterInfo* p = GetRegInfo(high_reg-1);
buzbeefa57c472012-11-21 12:06:18 -0800246 if (p->in_use || p->is_temp) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 // Already allocated or not preserved - fail.
248 return res;
249 }
250 // OK - good to go.
251 res = p->reg;
buzbeefa57c472012-11-21 12:06:18 -0800252 p->in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700253 DCHECK_EQ((res & 1), 0);
buzbee1fd33462013-03-25 13:40:45 -0700254 MarkPreservedSingle(v_reg, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 } else {
buzbee1fd33462013-03-25 13:40:45 -0700256 RegisterInfo* FPRegs = reg_pool_->FPRegs;
257 for (int i = 0; i < reg_pool_->num_fp_regs; i++) {
buzbeefa57c472012-11-21 12:06:18 -0800258 if (!FPRegs[i].is_temp && !FPRegs[i].in_use &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700259 ((FPRegs[i].reg & 0x1) == 0x0) &&
buzbeefa57c472012-11-21 12:06:18 -0800260 !FPRegs[i+1].is_temp && !FPRegs[i+1].in_use &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700261 ((FPRegs[i+1].reg & 0x1) == 0x1) &&
262 (FPRegs[i].reg + 1) == FPRegs[i+1].reg) {
263 res = FPRegs[i].reg;
buzbeefa57c472012-11-21 12:06:18 -0800264 FPRegs[i].in_use = true;
buzbee1fd33462013-03-25 13:40:45 -0700265 MarkPreservedSingle(v_reg, res);
buzbeefa57c472012-11-21 12:06:18 -0800266 FPRegs[i+1].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 DCHECK_EQ(res + 1, FPRegs[i+1].reg);
buzbee1fd33462013-03-25 13:40:45 -0700268 MarkPreservedSingle(v_reg+1, res+1);
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 break;
270 }
buzbee67bf8852011-08-17 17:51:35 -0700271 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700272 }
273 if (res != -1) {
buzbee1fd33462013-03-25 13:40:45 -0700274 promotion_map_[p_map_idx].fp_location = kLocPhysReg;
275 promotion_map_[p_map_idx].FpReg = res;
276 promotion_map_[p_map_idx+1].fp_location = kLocPhysReg;
277 promotion_map_[p_map_idx+1].FpReg = res + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 }
279 return res;
buzbee67bf8852011-08-17 17:51:35 -0700280}
281
282
283/*
284 * Reserve a callee-save fp register. If this register can be used
285 * as the first of a double, attempt to allocate an even pair of fp
286 * single regs (but if can't still attempt to allocate a single, preferring
287 * first to allocate an odd register.
288 */
buzbee1fd33462013-03-25 13:40:45 -0700289int Mir2Lir::AllocPreservedFPReg(int s_reg, bool double_start)
buzbee67bf8852011-08-17 17:51:35 -0700290{
Bill Buzbeea114add2012-05-03 15:00:40 -0700291 int res = -1;
buzbeefa57c472012-11-21 12:06:18 -0800292 if (double_start) {
buzbee1fd33462013-03-25 13:40:45 -0700293 res = AllocPreservedDouble(s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 }
295 if (res == -1) {
buzbee1fd33462013-03-25 13:40:45 -0700296 res = AllocPreservedSingle(s_reg, false /* try odd # */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 }
298 if (res == -1)
buzbee1fd33462013-03-25 13:40:45 -0700299 res = AllocPreservedSingle(s_reg, true /* try even # */);
Bill Buzbeea114add2012-05-03 15:00:40 -0700300 return res;
buzbee67bf8852011-08-17 17:51:35 -0700301}
302
buzbee1fd33462013-03-25 13:40:45 -0700303int Mir2Lir::AllocTempBody(RegisterInfo* p, int num_regs, int* next_temp,
304 bool required)
buzbee67bf8852011-08-17 17:51:35 -0700305{
Bill Buzbeea114add2012-05-03 15:00:40 -0700306 int i;
buzbeefa57c472012-11-21 12:06:18 -0800307 int next = *next_temp;
308 for (i=0; i< num_regs; i++) {
309 if (next >= num_regs)
Bill Buzbeea114add2012-05-03 15:00:40 -0700310 next = 0;
buzbeefa57c472012-11-21 12:06:18 -0800311 if (p[next].is_temp && !p[next].in_use && !p[next].live) {
buzbee1fd33462013-03-25 13:40:45 -0700312 Clobber(p[next].reg);
buzbeefa57c472012-11-21 12:06:18 -0800313 p[next].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 p[next].pair = false;
buzbeefa57c472012-11-21 12:06:18 -0800315 *next_temp = next + 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700316 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700317 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700318 next++;
319 }
buzbeefa57c472012-11-21 12:06:18 -0800320 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) {
buzbee1fd33462013-03-25 13:40:45 -0700325 Clobber(p[next].reg);
buzbeefa57c472012-11-21 12:06:18 -0800326 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 }
333 if (required) {
buzbee1fd33462013-03-25 13:40:45 -0700334 CodegenDump();
335 DumpRegPool(reg_pool_->core_regs,
336 reg_pool_->num_core_regs);
Bill Buzbeea114add2012-05-03 15:00:40 -0700337 LOG(FATAL) << "No free temp registers";
338 }
339 return -1; // No register available
buzbee67bf8852011-08-17 17:51:35 -0700340}
341
342//REDO: too many assumptions.
buzbee1fd33462013-03-25 13:40:45 -0700343int Mir2Lir::AllocTempDouble()
buzbee67bf8852011-08-17 17:51:35 -0700344{
buzbee1fd33462013-03-25 13:40:45 -0700345 RegisterInfo* p = reg_pool_->FPRegs;
346 int num_regs = reg_pool_->num_fp_regs;
Bill Buzbeea114add2012-05-03 15:00:40 -0700347 /* Start looking at an even reg */
buzbee1fd33462013-03-25 13:40:45 -0700348 int next = reg_pool_->next_fp_reg & ~0x1;
buzbee67bf8852011-08-17 17:51:35 -0700349
Bill Buzbeea114add2012-05-03 15:00:40 -0700350 // First try to avoid allocating live registers
buzbeefa57c472012-11-21 12:06:18 -0800351 for (int i=0; i < num_regs; i+=2) {
352 if (next >= num_regs)
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 next = 0;
buzbeefa57c472012-11-21 12:06:18 -0800354 if ((p[next].is_temp && !p[next].in_use && !p[next].live) &&
355 (p[next+1].is_temp && !p[next+1].in_use && !p[next+1].live)) {
buzbee1fd33462013-03-25 13:40:45 -0700356 Clobber(p[next].reg);
357 Clobber(p[next+1].reg);
buzbeefa57c472012-11-21 12:06:18 -0800358 p[next].in_use = true;
359 p[next+1].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700360 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
361 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee1fd33462013-03-25 13:40:45 -0700362 reg_pool_->next_fp_reg = next + 2;
363 if (reg_pool_->next_fp_reg >= num_regs) {
364 reg_pool_->next_fp_reg = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700365 }
366 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700367 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700368 next += 2;
369 }
buzbee1fd33462013-03-25 13:40:45 -0700370 next = reg_pool_->next_fp_reg & ~0x1;
buzbeea50638b2011-11-02 15:15:06 -0700371
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 // No choice - find a pair and kill it.
buzbeefa57c472012-11-21 12:06:18 -0800373 for (int i=0; i < num_regs; i+=2) {
374 if (next >= num_regs)
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 next = 0;
buzbeefa57c472012-11-21 12:06:18 -0800376 if (p[next].is_temp && !p[next].in_use && p[next+1].is_temp &&
377 !p[next+1].in_use) {
buzbee1fd33462013-03-25 13:40:45 -0700378 Clobber(p[next].reg);
379 Clobber(p[next+1].reg);
buzbeefa57c472012-11-21 12:06:18 -0800380 p[next].in_use = true;
381 p[next+1].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700382 DCHECK_EQ((p[next].reg+1), p[next+1].reg);
383 DCHECK_EQ((p[next].reg & 0x1), 0);
buzbee1fd33462013-03-25 13:40:45 -0700384 reg_pool_->next_fp_reg = next + 2;
385 if (reg_pool_->next_fp_reg >= num_regs) {
386 reg_pool_->next_fp_reg = 0;
Bill Buzbeea114add2012-05-03 15:00:40 -0700387 }
388 return p[next].reg;
buzbee67bf8852011-08-17 17:51:35 -0700389 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700390 next += 2;
391 }
392 LOG(FATAL) << "No free temp registers (pair)";
393 return -1;
buzbee67bf8852011-08-17 17:51:35 -0700394}
395
396/* Return a temp if one is available, -1 otherwise */
buzbee1fd33462013-03-25 13:40:45 -0700397int Mir2Lir::AllocFreeTemp()
buzbee67bf8852011-08-17 17:51:35 -0700398{
buzbee1fd33462013-03-25 13:40:45 -0700399 return AllocTempBody(reg_pool_->core_regs,
400 reg_pool_->num_core_regs,
401 &reg_pool_->next_core_reg, true);
buzbee67bf8852011-08-17 17:51:35 -0700402}
403
buzbee1fd33462013-03-25 13:40:45 -0700404int Mir2Lir::AllocTemp()
buzbee67bf8852011-08-17 17:51:35 -0700405{
buzbee1fd33462013-03-25 13:40:45 -0700406 return AllocTempBody(reg_pool_->core_regs,
407 reg_pool_->num_core_regs,
408 &reg_pool_->next_core_reg, true);
buzbee67bf8852011-08-17 17:51:35 -0700409}
410
buzbee1fd33462013-03-25 13:40:45 -0700411int Mir2Lir::AllocTempFloat()
buzbee67bf8852011-08-17 17:51:35 -0700412{
buzbee1fd33462013-03-25 13:40:45 -0700413 return AllocTempBody(reg_pool_->FPRegs,
414 reg_pool_->num_fp_regs,
415 &reg_pool_->next_fp_reg, true);
buzbee67bf8852011-08-17 17:51:35 -0700416}
417
buzbee1fd33462013-03-25 13:40:45 -0700418Mir2Lir::RegisterInfo* Mir2Lir::AllocLiveBody(RegisterInfo* p, int num_regs, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700419{
Bill Buzbeea114add2012-05-03 15:00:40 -0700420 int i;
buzbeefa57c472012-11-21 12:06:18 -0800421 if (s_reg == -1)
buzbee67bf8852011-08-17 17:51:35 -0700422 return NULL;
buzbeefa57c472012-11-21 12:06:18 -0800423 for (i=0; i < num_regs; i++) {
424 if (p[i].live && (p[i].s_reg == s_reg)) {
425 if (p[i].is_temp)
426 p[i].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 return &p[i];
428 }
429 }
430 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700431}
432
buzbee1fd33462013-03-25 13:40:45 -0700433Mir2Lir::RegisterInfo* Mir2Lir::AllocLive(int s_reg, int reg_class)
buzbee67bf8852011-08-17 17:51:35 -0700434{
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 RegisterInfo* res = NULL;
buzbeefa57c472012-11-21 12:06:18 -0800436 switch (reg_class) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700437 case kAnyReg:
buzbee1fd33462013-03-25 13:40:45 -0700438 res = AllocLiveBody(reg_pool_->FPRegs,
439 reg_pool_->num_fp_regs, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 if (res)
441 break;
442 /* Intentional fallthrough */
443 case kCoreReg:
buzbee1fd33462013-03-25 13:40:45 -0700444 res = AllocLiveBody(reg_pool_->core_regs,
445 reg_pool_->num_core_regs, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 break;
447 case kFPReg:
buzbee1fd33462013-03-25 13:40:45 -0700448 res = AllocLiveBody(reg_pool_->FPRegs,
449 reg_pool_->num_fp_regs, s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700450 break;
451 default:
452 LOG(FATAL) << "Invalid register type";
453 }
454 return res;
buzbee67bf8852011-08-17 17:51:35 -0700455}
456
buzbee1fd33462013-03-25 13:40:45 -0700457void Mir2Lir::FreeTemp(int reg)
buzbee67bf8852011-08-17 17:51:35 -0700458{
buzbee1fd33462013-03-25 13:40:45 -0700459 RegisterInfo* p = reg_pool_->core_regs;
460 int num_regs = reg_pool_->num_core_regs;
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 int i;
buzbeefa57c472012-11-21 12:06:18 -0800462 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700463 if (p[i].reg == reg) {
buzbeefa57c472012-11-21 12:06:18 -0800464 if (p[i].is_temp) {
465 p[i].in_use = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 }
467 p[i].pair = false;
468 return;
buzbee67bf8852011-08-17 17:51:35 -0700469 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 }
buzbee1fd33462013-03-25 13:40:45 -0700471 p = reg_pool_->FPRegs;
472 num_regs = reg_pool_->num_fp_regs;
buzbeefa57c472012-11-21 12:06:18 -0800473 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 if (p[i].reg == reg) {
buzbeefa57c472012-11-21 12:06:18 -0800475 if (p[i].is_temp) {
476 p[i].in_use = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700477 }
478 p[i].pair = false;
479 return;
buzbee67bf8852011-08-17 17:51:35 -0700480 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 }
482 LOG(FATAL) << "Tried to free a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700483}
484
buzbee1fd33462013-03-25 13:40:45 -0700485Mir2Lir::RegisterInfo* Mir2Lir::IsLive(int reg)
buzbee67bf8852011-08-17 17:51:35 -0700486{
buzbee1fd33462013-03-25 13:40:45 -0700487 RegisterInfo* p = reg_pool_->core_regs;
488 int num_regs = reg_pool_->num_core_regs;
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 int i;
buzbeefa57c472012-11-21 12:06:18 -0800490 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 if (p[i].reg == reg) {
492 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700493 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 }
buzbee1fd33462013-03-25 13:40:45 -0700495 p = reg_pool_->FPRegs;
496 num_regs = reg_pool_->num_fp_regs;
buzbeefa57c472012-11-21 12:06:18 -0800497 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 if (p[i].reg == reg) {
499 return p[i].live ? &p[i] : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700500 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 }
502 return NULL;
buzbee67bf8852011-08-17 17:51:35 -0700503}
504
buzbee1fd33462013-03-25 13:40:45 -0700505Mir2Lir::RegisterInfo* Mir2Lir::IsTemp(int reg)
buzbee67bf8852011-08-17 17:51:35 -0700506{
buzbee1fd33462013-03-25 13:40:45 -0700507 RegisterInfo* p = GetRegInfo(reg);
buzbeefa57c472012-11-21 12:06:18 -0800508 return (p->is_temp) ? p : NULL;
buzbee67bf8852011-08-17 17:51:35 -0700509}
510
buzbee1fd33462013-03-25 13:40:45 -0700511Mir2Lir::RegisterInfo* Mir2Lir::IsPromoted(int reg)
buzbeeb29e4d12011-09-26 15:05:48 -0700512{
buzbee1fd33462013-03-25 13:40:45 -0700513 RegisterInfo* p = GetRegInfo(reg);
buzbeefa57c472012-11-21 12:06:18 -0800514 return (p->is_temp) ? NULL : p;
buzbeeb29e4d12011-09-26 15:05:48 -0700515}
516
buzbee1fd33462013-03-25 13:40:45 -0700517bool Mir2Lir::IsDirty(int reg)
buzbee67bf8852011-08-17 17:51:35 -0700518{
buzbee1fd33462013-03-25 13:40:45 -0700519 RegisterInfo* p = GetRegInfo(reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700520 return p->dirty;
buzbee67bf8852011-08-17 17:51:35 -0700521}
522
523/*
buzbee52a77fc2012-11-20 19:50:46 -0800524 * Similar to AllocTemp(), but forces the allocation of a specific
buzbee67bf8852011-08-17 17:51:35 -0700525 * register. No check is made to see if the register was previously
526 * allocated. Use with caution.
527 */
buzbee1fd33462013-03-25 13:40:45 -0700528void Mir2Lir::LockTemp(int reg)
buzbee67bf8852011-08-17 17:51:35 -0700529{
buzbee1fd33462013-03-25 13:40:45 -0700530 RegisterInfo* p = reg_pool_->core_regs;
531 int num_regs = reg_pool_->num_core_regs;
Bill Buzbeea114add2012-05-03 15:00:40 -0700532 int i;
buzbeefa57c472012-11-21 12:06:18 -0800533 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 if (p[i].reg == reg) {
buzbeefa57c472012-11-21 12:06:18 -0800535 DCHECK(p[i].is_temp);
536 p[i].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700537 p[i].live = false;
538 return;
buzbee67bf8852011-08-17 17:51:35 -0700539 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 }
buzbee1fd33462013-03-25 13:40:45 -0700541 p = reg_pool_->FPRegs;
542 num_regs = reg_pool_->num_fp_regs;
buzbeefa57c472012-11-21 12:06:18 -0800543 for (i=0; i< num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 if (p[i].reg == reg) {
buzbeefa57c472012-11-21 12:06:18 -0800545 DCHECK(p[i].is_temp);
546 p[i].in_use = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700547 p[i].live = false;
548 return;
buzbee67bf8852011-08-17 17:51:35 -0700549 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 }
551 LOG(FATAL) << "Tried to lock a non-existant temp: r" << reg;
buzbee67bf8852011-08-17 17:51:35 -0700552}
553
buzbee1fd33462013-03-25 13:40:45 -0700554void Mir2Lir::ResetDefBody(RegisterInfo* p)
buzbee67bf8852011-08-17 17:51:35 -0700555{
buzbeefa57c472012-11-21 12:06:18 -0800556 p->def_start = NULL;
557 p->def_end = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700558}
559
buzbee1fd33462013-03-25 13:40:45 -0700560void Mir2Lir::ResetDef(int reg)
buzbee5abfa3e2012-01-31 17:01:43 -0800561{
buzbee1fd33462013-03-25 13:40:45 -0700562 ResetDefBody(GetRegInfo(reg));
buzbee5abfa3e2012-01-31 17:01:43 -0800563}
564
buzbee1fd33462013-03-25 13:40:45 -0700565void Mir2Lir::NullifyRange(LIR *start, LIR *finish, int s_reg1, int s_reg2)
buzbee67bf8852011-08-17 17:51:35 -0700566{
Bill Buzbeea114add2012-05-03 15:00:40 -0700567 if (start && finish) {
568 LIR *p;
buzbeefa57c472012-11-21 12:06:18 -0800569 DCHECK_EQ(s_reg1, s_reg2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 for (p = start; ;p = p->next) {
buzbee52a77fc2012-11-20 19:50:46 -0800571 NopLIR(p);
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 if (p == finish)
573 break;
buzbee67bf8852011-08-17 17:51:35 -0700574 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 }
buzbee67bf8852011-08-17 17:51:35 -0700576}
577
578/*
579 * Mark the beginning and end LIR of a def sequence. Note that
580 * on entry start points to the LIR prior to the beginning of the
581 * sequence.
582 */
buzbee1fd33462013-03-25 13:40:45 -0700583void Mir2Lir::MarkDef(RegLocation rl, LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700584{
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 DCHECK(!rl.wide);
586 DCHECK(start && start->next);
587 DCHECK(finish);
buzbee1fd33462013-03-25 13:40:45 -0700588 RegisterInfo* p = GetRegInfo(rl.low_reg);
buzbeefa57c472012-11-21 12:06:18 -0800589 p->def_start = start->next;
590 p->def_end = finish;
buzbee67bf8852011-08-17 17:51:35 -0700591}
592
593/*
594 * Mark the beginning and end LIR of a def sequence. Note that
595 * on entry start points to the LIR prior to the beginning of the
596 * sequence.
597 */
buzbee1fd33462013-03-25 13:40:45 -0700598void Mir2Lir::MarkDefWide(RegLocation rl, LIR *start, LIR *finish)
buzbee67bf8852011-08-17 17:51:35 -0700599{
Bill Buzbeea114add2012-05-03 15:00:40 -0700600 DCHECK(rl.wide);
601 DCHECK(start && start->next);
602 DCHECK(finish);
buzbee1fd33462013-03-25 13:40:45 -0700603 RegisterInfo* p = GetRegInfo(rl.low_reg);
604 ResetDef(rl.high_reg); // Only track low of pair
buzbeefa57c472012-11-21 12:06:18 -0800605 p->def_start = start->next;
606 p->def_end = finish;
buzbee67bf8852011-08-17 17:51:35 -0700607}
608
buzbee1fd33462013-03-25 13:40:45 -0700609RegLocation Mir2Lir::WideToNarrow(RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700610{
Bill Buzbeea114add2012-05-03 15:00:40 -0700611 DCHECK(rl.wide);
612 if (rl.location == kLocPhysReg) {
buzbee1fd33462013-03-25 13:40:45 -0700613 RegisterInfo* info_lo = GetRegInfo(rl.low_reg);
614 RegisterInfo* info_hi = GetRegInfo(rl.high_reg);
buzbeefa57c472012-11-21 12:06:18 -0800615 if (info_lo->is_temp) {
616 info_lo->pair = false;
617 info_lo->def_start = NULL;
618 info_lo->def_end = NULL;
buzbee67bf8852011-08-17 17:51:35 -0700619 }
buzbeefa57c472012-11-21 12:06:18 -0800620 if (info_hi->is_temp) {
621 info_hi->pair = false;
622 info_hi->def_start = NULL;
623 info_hi->def_end = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700624 }
625 }
626 rl.wide = false;
627 return rl;
buzbee67bf8852011-08-17 17:51:35 -0700628}
629
buzbee1fd33462013-03-25 13:40:45 -0700630void Mir2Lir::ResetDefLoc(RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700631{
Bill Buzbeea114add2012-05-03 15:00:40 -0700632 DCHECK(!rl.wide);
buzbee1fd33462013-03-25 13:40:45 -0700633 RegisterInfo* p = IsTemp(rl.low_reg);
634 if (p && !(cu_->disable_opt & (1 << kSuppressLoads))) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700635 DCHECK(!p->pair);
buzbee1fd33462013-03-25 13:40:45 -0700636 NullifyRange(p->def_start, p->def_end, p->s_reg, rl.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 }
buzbee1fd33462013-03-25 13:40:45 -0700638 ResetDef(rl.low_reg);
buzbee67bf8852011-08-17 17:51:35 -0700639}
640
buzbee1fd33462013-03-25 13:40:45 -0700641void Mir2Lir::ResetDefLocWide(RegLocation rl)
buzbee67bf8852011-08-17 17:51:35 -0700642{
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 DCHECK(rl.wide);
buzbee1fd33462013-03-25 13:40:45 -0700644 RegisterInfo* p_low = IsTemp(rl.low_reg);
645 RegisterInfo* p_high = IsTemp(rl.high_reg);
646 if (p_low && !(cu_->disable_opt & (1 << kSuppressLoads))) {
buzbeefa57c472012-11-21 12:06:18 -0800647 DCHECK(p_low->pair);
buzbee1fd33462013-03-25 13:40:45 -0700648 NullifyRange(p_low->def_start, p_low->def_end, p_low->s_reg, rl.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700649 }
buzbee1fd33462013-03-25 13:40:45 -0700650 if (p_high && !(cu_->disable_opt & (1 << kSuppressLoads))) {
buzbeefa57c472012-11-21 12:06:18 -0800651 DCHECK(p_high->pair);
Bill Buzbeea114add2012-05-03 15:00:40 -0700652 }
buzbee1fd33462013-03-25 13:40:45 -0700653 ResetDef(rl.low_reg);
654 ResetDef(rl.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700655}
656
buzbee1fd33462013-03-25 13:40:45 -0700657void Mir2Lir::ResetDefTracking()
buzbee67bf8852011-08-17 17:51:35 -0700658{
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 int i;
buzbee1fd33462013-03-25 13:40:45 -0700660 for (i=0; i< reg_pool_->num_core_regs; i++) {
661 ResetDefBody(&reg_pool_->core_regs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 }
buzbee1fd33462013-03-25 13:40:45 -0700663 for (i=0; i< reg_pool_->num_fp_regs; i++) {
664 ResetDefBody(&reg_pool_->FPRegs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700665 }
buzbee67bf8852011-08-17 17:51:35 -0700666}
667
buzbee1fd33462013-03-25 13:40:45 -0700668void Mir2Lir::ClobberAllRegs()
buzbee67bf8852011-08-17 17:51:35 -0700669{
Bill Buzbeea114add2012-05-03 15:00:40 -0700670 int i;
buzbee1fd33462013-03-25 13:40:45 -0700671 for (i=0; i< reg_pool_->num_core_regs; i++) {
672 ClobberBody(&reg_pool_->core_regs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700673 }
buzbee1fd33462013-03-25 13:40:45 -0700674 for (i=0; i< reg_pool_->num_fp_regs; i++) {
675 ClobberBody(&reg_pool_->FPRegs[i]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700676 }
buzbee67bf8852011-08-17 17:51:35 -0700677}
678
buzbee67bf8852011-08-17 17:51:35 -0700679// Make sure nothing is live and dirty
buzbee1fd33462013-03-25 13:40:45 -0700680void Mir2Lir::FlushAllRegsBody(RegisterInfo* info, int num_regs)
buzbee67bf8852011-08-17 17:51:35 -0700681{
Bill Buzbeea114add2012-05-03 15:00:40 -0700682 int i;
buzbeefa57c472012-11-21 12:06:18 -0800683 for (i=0; i < num_regs; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 if (info[i].live && info[i].dirty) {
685 if (info[i].pair) {
buzbee1fd33462013-03-25 13:40:45 -0700686 FlushRegWide(info[i].reg, info[i].partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700687 } else {
buzbee1fd33462013-03-25 13:40:45 -0700688 FlushReg(info[i].reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700689 }
buzbee67bf8852011-08-17 17:51:35 -0700690 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700691 }
buzbee67bf8852011-08-17 17:51:35 -0700692}
693
buzbee1fd33462013-03-25 13:40:45 -0700694void Mir2Lir::FlushAllRegs()
buzbee67bf8852011-08-17 17:51:35 -0700695{
buzbee1fd33462013-03-25 13:40:45 -0700696 FlushAllRegsBody(reg_pool_->core_regs,
697 reg_pool_->num_core_regs);
698 FlushAllRegsBody(reg_pool_->FPRegs,
699 reg_pool_->num_fp_regs);
700 ClobberAllRegs();
buzbee67bf8852011-08-17 17:51:35 -0700701}
702
703
704//TUNING: rewrite all of this reg stuff. Probably use an attribute table
buzbee1fd33462013-03-25 13:40:45 -0700705bool Mir2Lir::RegClassMatches(int reg_class, int reg)
buzbee67bf8852011-08-17 17:51:35 -0700706{
buzbeefa57c472012-11-21 12:06:18 -0800707 if (reg_class == kAnyReg) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700708 return true;
buzbeefa57c472012-11-21 12:06:18 -0800709 } else if (reg_class == kCoreReg) {
buzbee1fd33462013-03-25 13:40:45 -0700710 return !IsFpReg(reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700711 } else {
buzbee1fd33462013-03-25 13:40:45 -0700712 return IsFpReg(reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700713 }
buzbee67bf8852011-08-17 17:51:35 -0700714}
715
buzbee1fd33462013-03-25 13:40:45 -0700716void Mir2Lir::MarkLive(int reg, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700717{
buzbee1fd33462013-03-25 13:40:45 -0700718 RegisterInfo* info = GetRegInfo(reg);
buzbeefa57c472012-11-21 12:06:18 -0800719 if ((info->reg == reg) && (info->s_reg == s_reg) && info->live) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700720 return; /* already live */
buzbeefa57c472012-11-21 12:06:18 -0800721 } else if (s_reg != INVALID_SREG) {
buzbee1fd33462013-03-25 13:40:45 -0700722 ClobberSReg(s_reg);
buzbeefa57c472012-11-21 12:06:18 -0800723 if (info->is_temp) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700724 info->live = true;
buzbee67bf8852011-08-17 17:51:35 -0700725 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700726 } else {
buzbeefa57c472012-11-21 12:06:18 -0800727 /* Can't be live if no associated s_reg */
728 DCHECK(info->is_temp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700729 info->live = false;
730 }
buzbeefa57c472012-11-21 12:06:18 -0800731 info->s_reg = s_reg;
buzbee67bf8852011-08-17 17:51:35 -0700732}
733
buzbee1fd33462013-03-25 13:40:45 -0700734void Mir2Lir::MarkTemp(int reg)
buzbee67bf8852011-08-17 17:51:35 -0700735{
buzbee1fd33462013-03-25 13:40:45 -0700736 RegisterInfo* info = GetRegInfo(reg);
buzbeefa57c472012-11-21 12:06:18 -0800737 info->is_temp = true;
buzbee67bf8852011-08-17 17:51:35 -0700738}
739
buzbee1fd33462013-03-25 13:40:45 -0700740void Mir2Lir::UnmarkTemp(int reg)
buzbee9e0f9b02011-08-24 15:32:46 -0700741{
buzbee1fd33462013-03-25 13:40:45 -0700742 RegisterInfo* info = GetRegInfo(reg);
buzbeefa57c472012-11-21 12:06:18 -0800743 info->is_temp = false;
buzbee9e0f9b02011-08-24 15:32:46 -0700744}
745
buzbee1fd33462013-03-25 13:40:45 -0700746void Mir2Lir::MarkPair(int low_reg, int high_reg)
buzbee67bf8852011-08-17 17:51:35 -0700747{
buzbee1fd33462013-03-25 13:40:45 -0700748 RegisterInfo* info_lo = GetRegInfo(low_reg);
749 RegisterInfo* info_hi = GetRegInfo(high_reg);
buzbeefa57c472012-11-21 12:06:18 -0800750 info_lo->pair = info_hi->pair = true;
751 info_lo->partner = high_reg;
752 info_hi->partner = low_reg;
buzbee67bf8852011-08-17 17:51:35 -0700753}
754
buzbee1fd33462013-03-25 13:40:45 -0700755void Mir2Lir::MarkClean(RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700756{
buzbee1fd33462013-03-25 13:40:45 -0700757 RegisterInfo* info = GetRegInfo(loc.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700758 info->dirty = false;
759 if (loc.wide) {
buzbee1fd33462013-03-25 13:40:45 -0700760 info = GetRegInfo(loc.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700761 info->dirty = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700762 }
buzbee67bf8852011-08-17 17:51:35 -0700763}
764
buzbee1fd33462013-03-25 13:40:45 -0700765void Mir2Lir::MarkDirty(RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700766{
Bill Buzbeea114add2012-05-03 15:00:40 -0700767 if (loc.home) {
768 // If already home, can't be dirty
769 return;
770 }
buzbee1fd33462013-03-25 13:40:45 -0700771 RegisterInfo* info = GetRegInfo(loc.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700772 info->dirty = true;
773 if (loc.wide) {
buzbee1fd33462013-03-25 13:40:45 -0700774 info = GetRegInfo(loc.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700775 info->dirty = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700776 }
buzbee67bf8852011-08-17 17:51:35 -0700777}
778
buzbee1fd33462013-03-25 13:40:45 -0700779void Mir2Lir::MarkInUse(int reg)
buzbee67bf8852011-08-17 17:51:35 -0700780{
buzbee1fd33462013-03-25 13:40:45 -0700781 RegisterInfo* info = GetRegInfo(reg);
buzbeefa57c472012-11-21 12:06:18 -0800782 info->in_use = true;
buzbee67bf8852011-08-17 17:51:35 -0700783}
784
buzbee1fd33462013-03-25 13:40:45 -0700785void Mir2Lir::CopyRegInfo(int new_reg, int old_reg)
buzbee67bf8852011-08-17 17:51:35 -0700786{
buzbee1fd33462013-03-25 13:40:45 -0700787 RegisterInfo* new_info = GetRegInfo(new_reg);
788 RegisterInfo* old_info = GetRegInfo(old_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700789 // Target temp status must not change
buzbeefa57c472012-11-21 12:06:18 -0800790 bool is_temp = new_info->is_temp;
791 *new_info = *old_info;
Bill Buzbeea114add2012-05-03 15:00:40 -0700792 // Restore target's temp status
buzbeefa57c472012-11-21 12:06:18 -0800793 new_info->is_temp = is_temp;
794 new_info->reg = new_reg;
buzbee67bf8852011-08-17 17:51:35 -0700795}
796
buzbee1fd33462013-03-25 13:40:45 -0700797bool Mir2Lir::CheckCorePoolSanity()
buzbee6181f792011-09-29 11:14:04 -0700798{
buzbee1fd33462013-03-25 13:40:45 -0700799 for (static int i = 0; i < reg_pool_->num_core_regs; i++) {
800 if (reg_pool_->core_regs[i].pair) {
801 static int my_reg = reg_pool_->core_regs[i].reg;
802 static int my_sreg = reg_pool_->core_regs[i].s_reg;
803 static int partner_reg = reg_pool_->core_regs[i].partner;
804 static RegisterInfo* partner = GetRegInfo(partner_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700805 DCHECK(partner != NULL);
806 DCHECK(partner->pair);
buzbeefa57c472012-11-21 12:06:18 -0800807 DCHECK_EQ(my_reg, partner->partner);
808 static int partner_sreg = partner->s_reg;
809 if (my_sreg == INVALID_SREG) {
810 DCHECK_EQ(partner_sreg, INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -0700811 } else {
buzbeefa57c472012-11-21 12:06:18 -0800812 int diff = my_sreg - partner_sreg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 DCHECK((diff == -1) || (diff == 1));
buzbee6181f792011-09-29 11:14:04 -0700814 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700815 }
buzbee1fd33462013-03-25 13:40:45 -0700816 if (!reg_pool_->core_regs[i].live) {
817 DCHECK(reg_pool_->core_regs[i].def_start == NULL);
818 DCHECK(reg_pool_->core_regs[i].def_end == NULL);
Bill Buzbeea114add2012-05-03 15:00:40 -0700819 }
buzbee6181f792011-09-29 11:14:04 -0700820 }
821 return true;
822}
823
buzbeeaad94382012-11-21 07:40:50 -0800824/*
825 * Return an updated location record with current in-register status.
826 * If the value lives in live temps, reflect that fact. No code
827 * is generated. If the live value is part of an older pair,
828 * clobber both low and high.
829 * TUNING: clobbering both is a bit heavy-handed, but the alternative
830 * is a bit complex when dealing with FP regs. Examine code to see
831 * if it's worthwhile trying to be more clever here.
832 */
833
buzbee1fd33462013-03-25 13:40:45 -0700834RegLocation Mir2Lir::UpdateLoc(RegLocation loc)
buzbeeaad94382012-11-21 07:40:50 -0800835{
836 DCHECK(!loc.wide);
buzbee1fd33462013-03-25 13:40:45 -0700837 DCHECK(CheckCorePoolSanity());
buzbeeaad94382012-11-21 07:40:50 -0800838 if (loc.location != kLocPhysReg) {
839 DCHECK((loc.location == kLocDalvikFrame) ||
840 (loc.location == kLocCompilerTemp));
buzbee1fd33462013-03-25 13:40:45 -0700841 RegisterInfo* info_lo = AllocLive(loc.s_reg_low, kAnyReg);
buzbeefa57c472012-11-21 12:06:18 -0800842 if (info_lo) {
843 if (info_lo->pair) {
buzbee1fd33462013-03-25 13:40:45 -0700844 Clobber(info_lo->reg);
845 Clobber(info_lo->partner);
846 FreeTemp(info_lo->reg);
buzbeeaad94382012-11-21 07:40:50 -0800847 } else {
buzbeefa57c472012-11-21 12:06:18 -0800848 loc.low_reg = info_lo->reg;
buzbeeaad94382012-11-21 07:40:50 -0800849 loc.location = kLocPhysReg;
850 }
851 }
852 }
853
854 return loc;
855}
856
buzbeefa57c472012-11-21 12:06:18 -0800857/* see comments for update_loc */
buzbee1fd33462013-03-25 13:40:45 -0700858RegLocation Mir2Lir::UpdateLocWide(RegLocation loc)
buzbee67bf8852011-08-17 17:51:35 -0700859{
Bill Buzbeea114add2012-05-03 15:00:40 -0700860 DCHECK(loc.wide);
buzbee1fd33462013-03-25 13:40:45 -0700861 DCHECK(CheckCorePoolSanity());
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 if (loc.location != kLocPhysReg) {
863 DCHECK((loc.location == kLocDalvikFrame) ||
864 (loc.location == kLocCompilerTemp));
865 // Are the dalvik regs already live in physical registers?
buzbee1fd33462013-03-25 13:40:45 -0700866 RegisterInfo* info_lo = AllocLive(loc.s_reg_low, kAnyReg);
867 RegisterInfo* info_hi = AllocLive(GetSRegHi(loc.s_reg_low), kAnyReg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 bool match = true;
buzbeefa57c472012-11-21 12:06:18 -0800869 match = match && (info_lo != NULL);
870 match = match && (info_hi != NULL);
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 // Are they both core or both FP?
buzbee1fd33462013-03-25 13:40:45 -0700872 match = match && (IsFpReg(info_lo->reg) == IsFpReg(info_hi->reg));
Bill Buzbeea114add2012-05-03 15:00:40 -0700873 // If a pair of floating point singles, are they properly aligned?
buzbee1fd33462013-03-25 13:40:45 -0700874 if (match && IsFpReg(info_lo->reg)) {
buzbeefa57c472012-11-21 12:06:18 -0800875 match &= ((info_lo->reg & 0x1) == 0);
876 match &= ((info_hi->reg - info_lo->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?
buzbeefa57c472012-11-21 12:06:18 -0800879 if (match && (info_lo->pair || info_hi->pair)) {
880 match = (info_lo->pair == info_hi->pair);
881 match &= ((info_lo->reg == info_hi->partner) &&
882 (info_hi->reg == info_lo->partner));
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 }
884 if (match) {
885 // Can reuse - update the register usage info
buzbeefa57c472012-11-21 12:06:18 -0800886 loc.low_reg = info_lo->reg;
887 loc.high_reg = info_hi->reg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700888 loc.location = kLocPhysReg;
buzbee1fd33462013-03-25 13:40:45 -0700889 MarkPair(loc.low_reg, loc.high_reg);
890 DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700891 return loc;
892 }
893 // Can't easily reuse - clobber and free any overlaps
buzbeefa57c472012-11-21 12:06:18 -0800894 if (info_lo) {
buzbee1fd33462013-03-25 13:40:45 -0700895 Clobber(info_lo->reg);
896 FreeTemp(info_lo->reg);
buzbeefa57c472012-11-21 12:06:18 -0800897 if (info_lo->pair)
buzbee1fd33462013-03-25 13:40:45 -0700898 Clobber(info_lo->partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 }
buzbeefa57c472012-11-21 12:06:18 -0800900 if (info_hi) {
buzbee1fd33462013-03-25 13:40:45 -0700901 Clobber(info_hi->reg);
902 FreeTemp(info_hi->reg);
buzbeefa57c472012-11-21 12:06:18 -0800903 if (info_hi->pair)
buzbee1fd33462013-03-25 13:40:45 -0700904 Clobber(info_hi->partner);
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 }
906 }
907 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700908}
909
buzbeeed3e9302011-09-23 17:34:19 -0700910
911/* For use in cases we don't know (or care) width */
buzbee1fd33462013-03-25 13:40:45 -0700912RegLocation Mir2Lir::UpdateRawLoc(RegLocation loc)
buzbeeed3e9302011-09-23 17:34:19 -0700913{
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 if (loc.wide)
buzbee1fd33462013-03-25 13:40:45 -0700915 return UpdateLocWide(loc);
Bill Buzbeea114add2012-05-03 15:00:40 -0700916 else
buzbee1fd33462013-03-25 13:40:45 -0700917 return UpdateLoc(loc);
buzbeeed3e9302011-09-23 17:34:19 -0700918}
919
buzbee1fd33462013-03-25 13:40:45 -0700920RegLocation Mir2Lir::EvalLocWide(RegLocation loc, int reg_class, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700921{
Bill Buzbeea114add2012-05-03 15:00:40 -0700922 DCHECK(loc.wide);
buzbeefa57c472012-11-21 12:06:18 -0800923 int new_regs;
924 int low_reg;
925 int high_reg;
buzbee67bf8852011-08-17 17:51:35 -0700926
buzbee1fd33462013-03-25 13:40:45 -0700927 loc = UpdateLocWide(loc);
buzbee67bf8852011-08-17 17:51:35 -0700928
Bill Buzbeea114add2012-05-03 15:00:40 -0700929 /* If already in registers, we can assume proper form. Right reg class? */
930 if (loc.location == kLocPhysReg) {
buzbee1fd33462013-03-25 13:40:45 -0700931 DCHECK_EQ(IsFpReg(loc.low_reg), IsFpReg(loc.high_reg));
932 DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
933 if (!RegClassMatches(reg_class, loc.low_reg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700934 /* Wrong register class. Reallocate and copy */
buzbee1fd33462013-03-25 13:40:45 -0700935 new_regs = AllocTypedTempPair(loc.fp, reg_class);
buzbeefa57c472012-11-21 12:06:18 -0800936 low_reg = new_regs & 0xff;
937 high_reg = (new_regs >> 8) & 0xff;
buzbee1fd33462013-03-25 13:40:45 -0700938 OpRegCopyWide(low_reg, high_reg, loc.low_reg, loc.high_reg);
939 CopyRegInfo(low_reg, loc.low_reg);
940 CopyRegInfo(high_reg, loc.high_reg);
941 Clobber(loc.low_reg);
942 Clobber(loc.high_reg);
buzbeefa57c472012-11-21 12:06:18 -0800943 loc.low_reg = low_reg;
944 loc.high_reg = high_reg;
buzbee1fd33462013-03-25 13:40:45 -0700945 MarkPair(loc.low_reg, loc.high_reg);
946 DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700947 }
buzbee67bf8852011-08-17 17:51:35 -0700948 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700949 }
950
buzbeefa57c472012-11-21 12:06:18 -0800951 DCHECK_NE(loc.s_reg_low, INVALID_SREG);
952 DCHECK_NE(GetSRegHi(loc.s_reg_low), INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -0700953
buzbee1fd33462013-03-25 13:40:45 -0700954 new_regs = AllocTypedTempPair(loc.fp, reg_class);
buzbeefa57c472012-11-21 12:06:18 -0800955 loc.low_reg = new_regs & 0xff;
956 loc.high_reg = (new_regs >> 8) & 0xff;
Bill Buzbeea114add2012-05-03 15:00:40 -0700957
buzbee1fd33462013-03-25 13:40:45 -0700958 MarkPair(loc.low_reg, loc.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700959 if (update) {
960 loc.location = kLocPhysReg;
buzbee1fd33462013-03-25 13:40:45 -0700961 MarkLive(loc.low_reg, loc.s_reg_low);
962 MarkLive(loc.high_reg, GetSRegHi(loc.s_reg_low));
Bill Buzbeea114add2012-05-03 15:00:40 -0700963 }
buzbee1fd33462013-03-25 13:40:45 -0700964 DCHECK(!IsFpReg(loc.low_reg) || ((loc.low_reg & 0x1) == 0));
Bill Buzbeea114add2012-05-03 15:00:40 -0700965 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700966}
967
buzbee1fd33462013-03-25 13:40:45 -0700968RegLocation Mir2Lir::EvalLoc(RegLocation loc, int reg_class, bool update)
buzbee67bf8852011-08-17 17:51:35 -0700969{
buzbeefa57c472012-11-21 12:06:18 -0800970 int new_reg;
buzbee67bf8852011-08-17 17:51:35 -0700971
Bill Buzbeea114add2012-05-03 15:00:40 -0700972 if (loc.wide)
buzbee1fd33462013-03-25 13:40:45 -0700973 return EvalLocWide(loc, reg_class, update);
buzbee67bf8852011-08-17 17:51:35 -0700974
buzbee1fd33462013-03-25 13:40:45 -0700975 loc = UpdateLoc(loc);
buzbee67bf8852011-08-17 17:51:35 -0700976
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 if (loc.location == kLocPhysReg) {
buzbee1fd33462013-03-25 13:40:45 -0700978 if (!RegClassMatches(reg_class, loc.low_reg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700979 /* Wrong register class. Realloc, copy and transfer ownership */
buzbee1fd33462013-03-25 13:40:45 -0700980 new_reg = AllocTypedTemp(loc.fp, reg_class);
981 OpRegCopy(new_reg, loc.low_reg);
982 CopyRegInfo(new_reg, loc.low_reg);
983 Clobber(loc.low_reg);
buzbeefa57c472012-11-21 12:06:18 -0800984 loc.low_reg = new_reg;
buzbee67bf8852011-08-17 17:51:35 -0700985 }
986 return loc;
Bill Buzbeea114add2012-05-03 15:00:40 -0700987 }
988
buzbeefa57c472012-11-21 12:06:18 -0800989 DCHECK_NE(loc.s_reg_low, INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -0700990
buzbee1fd33462013-03-25 13:40:45 -0700991 new_reg = AllocTypedTemp(loc.fp, reg_class);
buzbeefa57c472012-11-21 12:06:18 -0800992 loc.low_reg = new_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700993
994 if (update) {
995 loc.location = kLocPhysReg;
buzbee1fd33462013-03-25 13:40:45 -0700996 MarkLive(loc.low_reg, loc.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700997 }
998 return loc;
buzbee67bf8852011-08-17 17:51:35 -0700999}
1000
buzbeefa57c472012-11-21 12:06:18 -08001001/* USE SSA names to count references of base Dalvik v_regs. */
buzbeeb0245ae2013-04-02 15:33:54 -07001002void Mir2Lir::CountRefs(RefCounts* core_counts, RefCounts* fp_counts) {
buzbee1fd33462013-03-25 13:40:45 -07001003 for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) {
1004 RegLocation loc = mir_graph_->reg_location_[i];
buzbeefa57c472012-11-21 12:06:18 -08001005 RefCounts* counts = loc.fp ? fp_counts : core_counts;
buzbee1fd33462013-03-25 13:40:45 -07001006 int p_map_idx = SRegToPMap(loc.s_reg_low);
buzbee4ef3e452012-12-14 13:35:28 -08001007 //Don't count easily regenerated immediates
buzbee1fd33462013-03-25 13:40:45 -07001008 if (loc.fp || !IsInexpensiveConstant(loc)) {
1009 counts[p_map_idx].count += mir_graph_->GetUseCount(i);
buzbee239c4e72012-03-16 08:42:29 -07001010 }
buzbeec7d1f912013-02-07 15:22:39 -08001011 if (loc.wide && loc.fp && !loc.high_word) {
1012 counts[p_map_idx].double_start = true;
buzbeee3acd072012-02-25 17:03:10 -08001013 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001014 }
buzbeee3acd072012-02-25 17:03:10 -08001015}
1016
1017/* qsort callback function, sort descending */
buzbeeaad94382012-11-21 07:40:50 -08001018static int SortCounts(const void *val1, const void *val2)
buzbeee3acd072012-02-25 17:03:10 -08001019{
buzbee1fd33462013-03-25 13:40:45 -07001020 const Mir2Lir::RefCounts* op1 = reinterpret_cast<const Mir2Lir::RefCounts*>(val1);
1021 const Mir2Lir::RefCounts* op2 = reinterpret_cast<const Mir2Lir::RefCounts*>(val2);
Bill Buzbeea114add2012-05-03 15:00:40 -07001022 return (op1->count == op2->count) ? 0 : (op1->count < op2->count ? 1 : -1);
buzbeee3acd072012-02-25 17:03:10 -08001023}
1024
buzbee1fd33462013-03-25 13:40:45 -07001025void Mir2Lir::DumpCounts(const RefCounts* arr, int size, const char* msg)
buzbeee3acd072012-02-25 17:03:10 -08001026{
Bill Buzbeea114add2012-05-03 15:00:40 -07001027 LOG(INFO) << msg;
1028 for (int i = 0; i < size; i++) {
buzbeefa57c472012-11-21 12:06:18 -08001029 LOG(INFO) << "s_reg[" << arr[i].s_reg << "]: " << arr[i].count;
Bill Buzbeea114add2012-05-03 15:00:40 -07001030 }
buzbeee3acd072012-02-25 17:03:10 -08001031}
1032
1033/*
1034 * Note: some portions of this code required even if the kPromoteRegs
1035 * optimization is disabled.
1036 */
buzbee1fd33462013-03-25 13:40:45 -07001037void Mir2Lir::DoPromotion()
buzbeee3acd072012-02-25 17:03:10 -08001038{
buzbee1fd33462013-03-25 13:40:45 -07001039 int reg_bias = cu_->num_compiler_temps + 1;
1040 int dalvik_regs = cu_->num_dalvik_registers;
buzbeefa57c472012-11-21 12:06:18 -08001041 int num_regs = dalvik_regs + reg_bias;
buzbeeb0245ae2013-04-02 15:33:54 -07001042 const int promotion_threshold = 1;
buzbeee3acd072012-02-25 17:03:10 -08001043
Bill Buzbeea114add2012-05-03 15:00:40 -07001044 // Allow target code to add any special registers
buzbee1fd33462013-03-25 13:40:45 -07001045 AdjustSpillMask();
buzbeee3acd072012-02-25 17:03:10 -08001046
Bill Buzbeea114add2012-05-03 15:00:40 -07001047 /*
1048 * Simple register promotion. Just do a static count of the uses
1049 * of Dalvik registers. Note that we examine the SSA names, but
1050 * count based on original Dalvik register name. Count refs
1051 * separately based on type in order to give allocation
1052 * preference to fp doubles - which must be allocated sequential
1053 * physical single fp registers started with an even-numbered
1054 * reg.
1055 * TUNING: replace with linear scan once we have the ability
1056 * to describe register live ranges for GC.
1057 */
buzbee862a7602013-04-05 10:58:54 -07001058 RefCounts *core_regs =
1059 static_cast<RefCounts*>(arena_->NewMem(sizeof(RefCounts) * num_regs, true,
1060 ArenaAllocator::kAllocRegAlloc));
1061 RefCounts *FpRegs =
1062 static_cast<RefCounts *>(arena_->NewMem(sizeof(RefCounts) * num_regs, true,
1063 ArenaAllocator::kAllocRegAlloc));
Bill Buzbeea114add2012-05-03 15:00:40 -07001064 // Set ssa names for original Dalvik registers
buzbeefa57c472012-11-21 12:06:18 -08001065 for (int i = 0; i < dalvik_regs; i++) {
1066 core_regs[i].s_reg = FpRegs[i].s_reg = i;
Bill Buzbeea114add2012-05-03 15:00:40 -07001067 }
1068 // Set ssa name for Method*
buzbee1fd33462013-03-25 13:40:45 -07001069 core_regs[dalvik_regs].s_reg = mir_graph_->GetMethodSReg();
1070 FpRegs[dalvik_regs].s_reg = mir_graph_->GetMethodSReg(); // For consistecy
buzbeefa57c472012-11-21 12:06:18 -08001071 // Set ssa names for compiler_temps
buzbee1fd33462013-03-25 13:40:45 -07001072 for (int i = 1; i <= cu_->num_compiler_temps; i++) {
buzbee862a7602013-04-05 10:58:54 -07001073 CompilerTemp* ct = mir_graph_->compiler_temps_.Get(i);
buzbeefa57c472012-11-21 12:06:18 -08001074 core_regs[dalvik_regs + i].s_reg = ct->s_reg;
1075 FpRegs[dalvik_regs + i].s_reg = ct->s_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001076 }
1077
buzbeeb0245ae2013-04-02 15:33:54 -07001078 // Sum use counts of SSA regs by original Dalvik vreg.
1079 CountRefs(core_regs, FpRegs);
Bill Buzbeea114add2012-05-03 15:00:40 -07001080
1081 /*
1082 * Ideally, we'd allocate doubles starting with an even-numbered
1083 * register. Bias the counts to try to allocate any vreg that's
1084 * used as the start of a pair first.
1085 */
buzbeefa57c472012-11-21 12:06:18 -08001086 for (int i = 0; i < num_regs; i++) {
1087 if (FpRegs[i].double_start) {
buzbee52a77fc2012-11-20 19:50:46 -08001088 FpRegs[i].count *= 2;
buzbeee3acd072012-02-25 17:03:10 -08001089 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001090 }
1091
1092 // Sort the count arrays
buzbeefa57c472012-11-21 12:06:18 -08001093 qsort(core_regs, num_regs, sizeof(RefCounts), SortCounts);
1094 qsort(FpRegs, num_regs, sizeof(RefCounts), SortCounts);
Bill Buzbeea114add2012-05-03 15:00:40 -07001095
buzbee1fd33462013-03-25 13:40:45 -07001096 if (cu_->verbose) {
buzbeefa57c472012-11-21 12:06:18 -08001097 DumpCounts(core_regs, num_regs, "Core regs after sort");
1098 DumpCounts(FpRegs, num_regs, "Fp regs after sort");
Bill Buzbeea114add2012-05-03 15:00:40 -07001099 }
1100
buzbee1fd33462013-03-25 13:40:45 -07001101 if (!(cu_->disable_opt & (1 << kPromoteRegs))) {
buzbee52a77fc2012-11-20 19:50:46 -08001102 // Promote FpRegs
buzbeefa57c472012-11-21 12:06:18 -08001103 for (int i = 0; (i < num_regs) &&
1104 (FpRegs[i].count >= promotion_threshold ); i++) {
buzbee1fd33462013-03-25 13:40:45 -07001105 int p_map_idx = SRegToPMap(FpRegs[i].s_reg);
1106 if (promotion_map_[p_map_idx].fp_location != kLocPhysReg) {
1107 int reg = AllocPreservedFPReg(FpRegs[i].s_reg,
buzbeefa57c472012-11-21 12:06:18 -08001108 FpRegs[i].double_start);
Bill Buzbeea114add2012-05-03 15:00:40 -07001109 if (reg < 0) {
1110 break; // No more left
1111 }
1112 }
buzbee239c4e72012-03-16 08:42:29 -07001113 }
buzbee9c044ce2012-03-18 13:24:07 -07001114
Bill Buzbeea114add2012-05-03 15:00:40 -07001115 // Promote core regs
buzbeefa57c472012-11-21 12:06:18 -08001116 for (int i = 0; (i < num_regs) &&
buzbeeb0245ae2013-04-02 15:33:54 -07001117 (core_regs[i].count >= promotion_threshold); i++) {
buzbee1fd33462013-03-25 13:40:45 -07001118 int p_map_idx = SRegToPMap(core_regs[i].s_reg);
1119 if (promotion_map_[p_map_idx].core_location !=
Bill Buzbeea114add2012-05-03 15:00:40 -07001120 kLocPhysReg) {
buzbee1fd33462013-03-25 13:40:45 -07001121 int reg = AllocPreservedCoreReg(core_regs[i].s_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -07001122 if (reg < 0) {
1123 break; // No more left
1124 }
1125 }
buzbeee3acd072012-02-25 17:03:10 -08001126 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001127 }
buzbeee3acd072012-02-25 17:03:10 -08001128
Bill Buzbeea114add2012-05-03 15:00:40 -07001129 // Now, update SSA names to new home locations
buzbee1fd33462013-03-25 13:40:45 -07001130 for (int i = 0; i < mir_graph_->GetNumSSARegs(); i++) {
1131 RegLocation *curr = &mir_graph_->reg_location_[i];
1132 int p_map_idx = SRegToPMap(curr->s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -07001133 if (!curr->wide) {
1134 if (curr->fp) {
buzbee1fd33462013-03-25 13:40:45 -07001135 if (promotion_map_[p_map_idx].fp_location == kLocPhysReg) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001136 curr->location = kLocPhysReg;
buzbee1fd33462013-03-25 13:40:45 -07001137 curr->low_reg = promotion_map_[p_map_idx].FpReg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001138 curr->home = true;
1139 }
1140 } else {
buzbee1fd33462013-03-25 13:40:45 -07001141 if (promotion_map_[p_map_idx].core_location == kLocPhysReg) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001142 curr->location = kLocPhysReg;
buzbee1fd33462013-03-25 13:40:45 -07001143 curr->low_reg = promotion_map_[p_map_idx].core_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001144 curr->home = true;
1145 }
1146 }
buzbeefa57c472012-11-21 12:06:18 -08001147 curr->high_reg = INVALID_REG;
Bill Buzbeea114add2012-05-03 15:00:40 -07001148 } else {
buzbeefa57c472012-11-21 12:06:18 -08001149 if (curr->high_word) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001150 continue;
1151 }
1152 if (curr->fp) {
buzbee1fd33462013-03-25 13:40:45 -07001153 if ((promotion_map_[p_map_idx].fp_location == kLocPhysReg) &&
1154 (promotion_map_[p_map_idx+1].fp_location ==
Bill Buzbeea114add2012-05-03 15:00:40 -07001155 kLocPhysReg)) {
buzbee1fd33462013-03-25 13:40:45 -07001156 int low_reg = promotion_map_[p_map_idx].FpReg;
1157 int high_reg = promotion_map_[p_map_idx+1].FpReg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001158 // Doubles require pair of singles starting at even reg
buzbeefa57c472012-11-21 12:06:18 -08001159 if (((low_reg & 0x1) == 0) && ((low_reg + 1) == high_reg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001160 curr->location = kLocPhysReg;
buzbeefa57c472012-11-21 12:06:18 -08001161 curr->low_reg = low_reg;
1162 curr->high_reg = high_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001163 curr->home = true;
1164 }
1165 }
1166 } else {
buzbee1fd33462013-03-25 13:40:45 -07001167 if ((promotion_map_[p_map_idx].core_location == kLocPhysReg)
1168 && (promotion_map_[p_map_idx+1].core_location ==
Bill Buzbeea114add2012-05-03 15:00:40 -07001169 kLocPhysReg)) {
1170 curr->location = kLocPhysReg;
buzbee1fd33462013-03-25 13:40:45 -07001171 curr->low_reg = promotion_map_[p_map_idx].core_reg;
1172 curr->high_reg = promotion_map_[p_map_idx+1].core_reg;
Bill Buzbeea114add2012-05-03 15:00:40 -07001173 curr->home = true;
1174 }
1175 }
buzbeee3acd072012-02-25 17:03:10 -08001176 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001177 }
buzbee1fd33462013-03-25 13:40:45 -07001178 if (cu_->verbose) {
1179 DumpPromotionMap();
buzbeeca7a5e42012-08-20 11:12:18 -07001180 }
buzbeee3acd072012-02-25 17:03:10 -08001181}
1182
1183/* Returns sp-relative offset in bytes for a VReg */
buzbee1fd33462013-03-25 13:40:45 -07001184int Mir2Lir::VRegOffset(int v_reg)
buzbeee3acd072012-02-25 17:03:10 -08001185{
buzbee1fd33462013-03-25 13:40:45 -07001186 return StackVisitor::GetVRegOffset(cu_->code_item, core_spill_mask_,
1187 fp_spill_mask_, frame_size_, v_reg);
buzbeee3acd072012-02-25 17:03:10 -08001188}
1189
1190/* Returns sp-relative offset in bytes for a SReg */
buzbee1fd33462013-03-25 13:40:45 -07001191int Mir2Lir::SRegOffset(int s_reg)
buzbeee3acd072012-02-25 17:03:10 -08001192{
buzbee1fd33462013-03-25 13:40:45 -07001193 return VRegOffset(mir_graph_->SRegToVReg(s_reg));
buzbee02031b12012-11-23 09:41:35 -08001194}
1195
1196/* Mark register usage state and return long retloc */
buzbee1fd33462013-03-25 13:40:45 -07001197RegLocation Mir2Lir::GetReturnWide(bool is_double)
buzbee02031b12012-11-23 09:41:35 -08001198{
buzbee1fd33462013-03-25 13:40:45 -07001199 RegLocation gpr_res = LocCReturnWide();
1200 RegLocation fpr_res = LocCReturnDouble();
buzbee02031b12012-11-23 09:41:35 -08001201 RegLocation res = is_double ? fpr_res : gpr_res;
buzbee1fd33462013-03-25 13:40:45 -07001202 Clobber(res.low_reg);
1203 Clobber(res.high_reg);
1204 LockTemp(res.low_reg);
1205 LockTemp(res.high_reg);
1206 MarkPair(res.low_reg, res.high_reg);
buzbee02031b12012-11-23 09:41:35 -08001207 return res;
1208}
1209
buzbee1fd33462013-03-25 13:40:45 -07001210RegLocation Mir2Lir::GetReturn(bool is_float)
buzbee02031b12012-11-23 09:41:35 -08001211{
buzbee1fd33462013-03-25 13:40:45 -07001212 RegLocation gpr_res = LocCReturn();
1213 RegLocation fpr_res = LocCReturnFloat();
buzbee02031b12012-11-23 09:41:35 -08001214 RegLocation res = is_float ? fpr_res : gpr_res;
buzbee1fd33462013-03-25 13:40:45 -07001215 Clobber(res.low_reg);
1216 if (cu_->instruction_set == kMips) {
1217 MarkInUse(res.low_reg);
buzbee02031b12012-11-23 09:41:35 -08001218 } else {
buzbee1fd33462013-03-25 13:40:45 -07001219 LockTemp(res.low_reg);
buzbee02031b12012-11-23 09:41:35 -08001220 }
1221 return res;
1222}
1223
buzbee1fd33462013-03-25 13:40:45 -07001224void Mir2Lir::SimpleRegAlloc()
buzbee311ca162013-02-28 15:56:43 -08001225{
buzbee1fd33462013-03-25 13:40:45 -07001226 DoPromotion();
buzbee311ca162013-02-28 15:56:43 -08001227
buzbee1fd33462013-03-25 13:40:45 -07001228 if (cu_->verbose && !(cu_->disable_opt & (1 << kPromoteRegs))) {
buzbee311ca162013-02-28 15:56:43 -08001229 LOG(INFO) << "After Promotion";
buzbee1fd33462013-03-25 13:40:45 -07001230 mir_graph_->DumpRegLocTable(mir_graph_->reg_location_, mir_graph_->GetNumSSARegs());
buzbee311ca162013-02-28 15:56:43 -08001231 }
1232
1233 /* Set the frame size */
buzbee1fd33462013-03-25 13:40:45 -07001234 frame_size_ = ComputeFrameSize();
1235}
1236
1237/*
1238 * Get the "real" sreg number associated with an s_reg slot. In general,
1239 * s_reg values passed through codegen are the SSA names created by
1240 * dataflow analysis and refer to slot numbers in the mir_graph_->reg_location
1241 * array. However, renaming is accomplished by simply replacing RegLocation
1242 * entries in the reglocation[] array. Therefore, when location
1243 * records for operands are first created, we need to ask the locRecord
1244 * identified by the dataflow pass what it's new name is.
1245 */
1246int Mir2Lir::GetSRegHi(int lowSreg) {
1247 return (lowSreg == INVALID_SREG) ? INVALID_SREG : lowSreg + 1;
1248}
1249
1250bool Mir2Lir::oat_live_out(int s_reg) {
1251 //For now.
1252 return true;
1253}
1254
1255int Mir2Lir::oatSSASrc(MIR* mir, int num) {
1256 DCHECK_GT(mir->ssa_rep->num_uses, num);
1257 return mir->ssa_rep->uses[num];
buzbee311ca162013-02-28 15:56:43 -08001258}
1259
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001260} // namespace art