blob: c8f9c51ffd75ff1705dd3cffd3695b832384d6b8 [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
buzbee1bc37c62012-11-20 13:35:41 -080017#include "codegen_util.h"
Brian Carlstrom641ce032013-01-31 15:21:37 -080018#include "compiler/compiler_ir.h"
19#include "ralloc_util.h"
buzbee1bc37c62012-11-20 13:35:41 -080020
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080021namespace art {
22
buzbeeb046e162012-10-30 15:48:42 -070023/* This file contains target-independent codegen and support. */
buzbee67bf8852011-08-17 17:51:35 -070024
buzbee31a4a6f2012-02-28 15:36:15 -080025/*
26 * Load an immediate value into a fixed or temp register. Target
buzbeefa57c472012-11-21 12:06:18 -080027 * register is clobbered, and marked in_use.
buzbee31a4a6f2012-02-28 15:36:15 -080028 */
buzbee02031b12012-11-23 09:41:35 -080029LIR* Codegen::LoadConstant(CompilationUnit* cu, int r_dest, int value)
buzbee31a4a6f2012-02-28 15:36:15 -080030{
buzbeefa57c472012-11-21 12:06:18 -080031 if (IsTemp(cu, r_dest)) {
32 Clobber(cu, r_dest);
33 MarkInUse(cu, r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -070034 }
buzbeefa57c472012-11-21 12:06:18 -080035 return LoadConstantNoClobber(cu, r_dest, value);
buzbee31a4a6f2012-02-28 15:36:15 -080036}
buzbee67bf8852011-08-17 17:51:35 -070037
buzbee5f61f672012-11-28 17:22:17 -080038/*
39 * Temporary workaround for Issue 7250540. If we're loading a constant zero into a
40 * promoted floating point register, also copy a zero into the int/ref identity of
41 * that sreg.
42 */
buzbee7da142f2012-11-29 16:33:42 -080043void Codegen::Workaround7250540(CompilationUnit* cu, RegLocation rl_dest, int zero_reg)
buzbee5f61f672012-11-28 17:22:17 -080044{
buzbee7da142f2012-11-29 16:33:42 -080045 if (rl_dest.fp) {
buzbee5f61f672012-11-28 17:22:17 -080046 int pmap_index = SRegToPMap(cu, rl_dest.s_reg_low);
47 if (cu->promotion_map[pmap_index].fp_location == kLocPhysReg) {
buzbee7da142f2012-11-29 16:33:42 -080048 // Now, determine if this vreg is ever used as a reference. If not, we're done.
buzbeed8506212012-12-20 14:15:05 -080049 if (!cu->gen_bitcode) {
50 // TUNING: We no longer have this info for QuickGBC - assume the worst
51 bool used_as_reference = false;
52 int base_vreg = SRegToVReg(cu, rl_dest.s_reg_low);
53 for (int i = 0; !used_as_reference && (i < cu->num_ssa_regs); i++) {
54 if (SRegToVReg(cu, cu->reg_location[i].s_reg_low) == base_vreg) {
55 used_as_reference |= cu->reg_location[i].ref;
56 }
buzbee7da142f2012-11-29 16:33:42 -080057 }
buzbeed8506212012-12-20 14:15:05 -080058 if (!used_as_reference) {
59 return;
60 }
buzbee7da142f2012-11-29 16:33:42 -080061 }
buzbee4ef3e452012-12-14 13:35:28 -080062 int temp_reg = zero_reg;
63 if (temp_reg == INVALID_REG) {
64 temp_reg = AllocTemp(cu);
65 cu->cg->LoadConstant(cu, temp_reg, 0);
66 }
buzbee5f61f672012-11-28 17:22:17 -080067 if (cu->promotion_map[pmap_index].core_location == kLocPhysReg) {
68 // Promoted - just copy in a zero
buzbee4ef3e452012-12-14 13:35:28 -080069 OpRegCopy(cu, cu->promotion_map[pmap_index].core_reg, temp_reg);
buzbee5f61f672012-11-28 17:22:17 -080070 } else {
71 // Lives in the frame, need to store.
buzbee4ef3e452012-12-14 13:35:28 -080072 StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low), temp_reg, kWord);
73 }
74 if (zero_reg == INVALID_REG) {
75 FreeTemp(cu, temp_reg);
buzbee5f61f672012-11-28 17:22:17 -080076 }
77 }
78 }
79}
80
buzbee67bf8852011-08-17 17:51:35 -070081/* Load a word at base + displacement. Displacement must be word multiple */
buzbee02031b12012-11-23 09:41:35 -080082LIR* Codegen::LoadWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest)
buzbee67bf8852011-08-17 17:51:35 -070083{
buzbeefa57c472012-11-21 12:06:18 -080084 return LoadBaseDisp(cu, rBase, displacement, r_dest, kWord,
Bill Buzbeea114add2012-05-03 15:00:40 -070085 INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -070086}
87
buzbee02031b12012-11-23 09:41:35 -080088LIR* Codegen::StoreWordDisp(CompilationUnit* cu, int rBase, int displacement, int r_src)
buzbee67bf8852011-08-17 17:51:35 -070089{
buzbeefa57c472012-11-21 12:06:18 -080090 return StoreBaseDisp(cu, rBase, displacement, r_src, kWord);
buzbee67bf8852011-08-17 17:51:35 -070091}
92
93/*
94 * Load a Dalvik register into a physical register. Take care when
95 * using this routine, as it doesn't perform any bookkeeping regarding
96 * register liveness. That is the responsibility of the caller.
97 */
buzbee02031b12012-11-23 09:41:35 -080098void Codegen::LoadValueDirect(CompilationUnit* cu, RegLocation rl_src, int r_dest)
buzbee67bf8852011-08-17 17:51:35 -070099{
buzbeefa57c472012-11-21 12:06:18 -0800100 rl_src = UpdateLoc(cu, rl_src);
101 if (rl_src.location == kLocPhysReg) {
102 OpRegCopy(cu, r_dest, rl_src.low_reg);
buzbee4ef3e452012-12-14 13:35:28 -0800103 } else if (IsInexpensiveConstant(cu, rl_src)) {
104 LoadConstantNoClobber(cu, r_dest, ConstantValue(cu, rl_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 } else {
buzbeefa57c472012-11-21 12:06:18 -0800106 DCHECK((rl_src.location == kLocDalvikFrame) ||
107 (rl_src.location == kLocCompilerTemp));
buzbee4ef3e452012-12-14 13:35:28 -0800108 LoadWordDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low), r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700109 }
buzbee67bf8852011-08-17 17:51:35 -0700110}
111
112/*
buzbee52a77fc2012-11-20 19:50:46 -0800113 * Similar to LoadValueDirect, but clobbers and allocates the target
buzbee67bf8852011-08-17 17:51:35 -0700114 * register. Should be used when loading to a fixed register (for example,
115 * loading arguments to an out of line call.
116 */
buzbee02031b12012-11-23 09:41:35 -0800117void Codegen::LoadValueDirectFixed(CompilationUnit* cu, RegLocation rl_src, int r_dest)
buzbee67bf8852011-08-17 17:51:35 -0700118{
buzbeefa57c472012-11-21 12:06:18 -0800119 Clobber(cu, r_dest);
120 MarkInUse(cu, r_dest);
121 LoadValueDirect(cu, rl_src, r_dest);
buzbee67bf8852011-08-17 17:51:35 -0700122}
123
124/*
125 * Load a Dalvik register pair into a physical register[s]. Take care when
126 * using this routine, as it doesn't perform any bookkeeping regarding
127 * register liveness. That is the responsibility of the caller.
128 */
buzbee02031b12012-11-23 09:41:35 -0800129void Codegen::LoadValueDirectWide(CompilationUnit* cu, RegLocation rl_src, int reg_lo,
buzbeefa57c472012-11-21 12:06:18 -0800130 int reg_hi)
buzbee67bf8852011-08-17 17:51:35 -0700131{
buzbeefa57c472012-11-21 12:06:18 -0800132 rl_src = UpdateLocWide(cu, rl_src);
133 if (rl_src.location == kLocPhysReg) {
134 OpRegCopyWide(cu, reg_lo, reg_hi, rl_src.low_reg, rl_src.high_reg);
buzbee4ef3e452012-12-14 13:35:28 -0800135 } else if (IsInexpensiveConstant(cu, rl_src)) {
136 LoadConstantWide(cu, reg_lo, reg_hi, ConstantValueWide(cu, rl_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 } else {
buzbeefa57c472012-11-21 12:06:18 -0800138 DCHECK((rl_src.location == kLocDalvikFrame) ||
139 (rl_src.location == kLocCompilerTemp));
140 LoadBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_src.s_reg_low),
141 reg_lo, reg_hi, INVALID_SREG);
Bill Buzbeea114add2012-05-03 15:00:40 -0700142 }
buzbee67bf8852011-08-17 17:51:35 -0700143}
144
145/*
buzbee52a77fc2012-11-20 19:50:46 -0800146 * Similar to LoadValueDirect, but clobbers and allocates the target
buzbee67bf8852011-08-17 17:51:35 -0700147 * registers. Should be used when loading to a fixed registers (for example,
148 * loading arguments to an out of line call.
149 */
buzbee02031b12012-11-23 09:41:35 -0800150void Codegen::LoadValueDirectWideFixed(CompilationUnit* cu, RegLocation rl_src, int reg_lo,
151 int reg_hi)
buzbee67bf8852011-08-17 17:51:35 -0700152{
buzbeefa57c472012-11-21 12:06:18 -0800153 Clobber(cu, reg_lo);
154 Clobber(cu, reg_hi);
155 MarkInUse(cu, reg_lo);
156 MarkInUse(cu, reg_hi);
157 LoadValueDirectWide(cu, rl_src, reg_lo, reg_hi);
buzbee67bf8852011-08-17 17:51:35 -0700158}
159
buzbee02031b12012-11-23 09:41:35 -0800160RegLocation Codegen::LoadValue(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind)
buzbee67bf8852011-08-17 17:51:35 -0700161{
buzbeefa57c472012-11-21 12:06:18 -0800162 rl_src = EvalLoc(cu, rl_src, op_kind, false);
buzbee4ef3e452012-12-14 13:35:28 -0800163 if (IsInexpensiveConstant(cu, rl_src) || rl_src.location != kLocPhysReg) {
buzbeefa57c472012-11-21 12:06:18 -0800164 LoadValueDirect(cu, rl_src, rl_src.low_reg);
165 rl_src.location = kLocPhysReg;
166 MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
Bill Buzbeea114add2012-05-03 15:00:40 -0700167 }
buzbeefa57c472012-11-21 12:06:18 -0800168 return rl_src;
buzbee67bf8852011-08-17 17:51:35 -0700169}
170
buzbee02031b12012-11-23 09:41:35 -0800171void Codegen::StoreValue(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
buzbee67bf8852011-08-17 17:51:35 -0700172{
buzbee3d661942012-03-14 17:37:27 -0700173#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700174 /*
175 * Sanity checking - should never try to store to the same
176 * ssa name during the compilation of a single instruction
buzbee52a77fc2012-11-20 19:50:46 -0800177 * without an intervening ClobberSReg().
Bill Buzbeea114add2012-05-03 15:00:40 -0700178 */
buzbeefa57c472012-11-21 12:06:18 -0800179 DCHECK((cu->live_sreg == INVALID_SREG) ||
180 (rl_dest.s_reg_low != cu->live_sreg));
181 cu->live_sreg = rl_dest.s_reg_low;
buzbee3d661942012-03-14 17:37:27 -0700182#endif
buzbeefa57c472012-11-21 12:06:18 -0800183 LIR* def_start;
184 LIR* def_end;
185 DCHECK(!rl_dest.wide);
186 DCHECK(!rl_src.wide);
187 rl_src = UpdateLoc(cu, rl_src);
188 rl_dest = UpdateLoc(cu, rl_dest);
189 if (rl_src.location == kLocPhysReg) {
190 if (IsLive(cu, rl_src.low_reg) ||
191 IsPromoted(cu, rl_src.low_reg) ||
192 (rl_dest.location == kLocPhysReg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700193 // Src is live/promoted or Dest has assigned reg.
buzbeefa57c472012-11-21 12:06:18 -0800194 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
195 OpRegCopy(cu, rl_dest.low_reg, rl_src.low_reg);
buzbee67bf8852011-08-17 17:51:35 -0700196 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700197 // Just re-assign the registers. Dest gets Src's regs
buzbeefa57c472012-11-21 12:06:18 -0800198 rl_dest.low_reg = rl_src.low_reg;
199 Clobber(cu, rl_src.low_reg);
buzbee67bf8852011-08-17 17:51:35 -0700200 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 } else {
202 // Load Src either into promoted Dest or temps allocated for Dest
buzbeefa57c472012-11-21 12:06:18 -0800203 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
204 LoadValueDirect(cu, rl_src, rl_dest.low_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 }
buzbee67bf8852011-08-17 17:51:35 -0700206
Bill Buzbeea114add2012-05-03 15:00:40 -0700207 // Dest is now live and dirty (until/if we flush it to home location)
buzbeefa57c472012-11-21 12:06:18 -0800208 MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low);
209 MarkDirty(cu, rl_dest);
buzbee67bf8852011-08-17 17:51:35 -0700210
211
buzbeefa57c472012-11-21 12:06:18 -0800212 ResetDefLoc(cu, rl_dest);
213 if (IsDirty(cu, rl_dest.low_reg) &&
214 oat_live_out(cu, rl_dest.s_reg_low)) {
215 def_start = cu->last_lir_insn;
216 StoreBaseDisp(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low),
217 rl_dest.low_reg, kWord);
218 MarkClean(cu, rl_dest);
219 def_end = cu->last_lir_insn;
buzbee5f61f672012-11-28 17:22:17 -0800220 if (!rl_dest.ref) {
221 // Exclude references from store elimination
222 MarkDef(cu, rl_dest, def_start, def_end);
223 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 }
buzbee67bf8852011-08-17 17:51:35 -0700225}
226
buzbee02031b12012-11-23 09:41:35 -0800227RegLocation Codegen::LoadValueWide(CompilationUnit* cu, RegLocation rl_src, RegisterClass op_kind)
buzbee67bf8852011-08-17 17:51:35 -0700228{
buzbeefa57c472012-11-21 12:06:18 -0800229 DCHECK(rl_src.wide);
230 rl_src = EvalLoc(cu, rl_src, op_kind, false);
buzbee4ef3e452012-12-14 13:35:28 -0800231 if (IsInexpensiveConstant(cu, rl_src) || rl_src.location != kLocPhysReg) {
buzbeefa57c472012-11-21 12:06:18 -0800232 LoadValueDirectWide(cu, rl_src, rl_src.low_reg, rl_src.high_reg);
233 rl_src.location = kLocPhysReg;
234 MarkLive(cu, rl_src.low_reg, rl_src.s_reg_low);
buzbee4ef3e452012-12-14 13:35:28 -0800235 MarkLive(cu, rl_src.high_reg, GetSRegHi(rl_src.s_reg_low));
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 }
buzbeefa57c472012-11-21 12:06:18 -0800237 return rl_src;
buzbee67bf8852011-08-17 17:51:35 -0700238}
239
buzbee02031b12012-11-23 09:41:35 -0800240void Codegen::StoreValueWide(CompilationUnit* cu, RegLocation rl_dest, RegLocation rl_src)
buzbee67bf8852011-08-17 17:51:35 -0700241{
buzbee3d661942012-03-14 17:37:27 -0700242#ifndef NDEBUG
Bill Buzbeea114add2012-05-03 15:00:40 -0700243 /*
244 * Sanity checking - should never try to store to the same
245 * ssa name during the compilation of a single instruction
buzbee52a77fc2012-11-20 19:50:46 -0800246 * without an intervening ClobberSReg().
Bill Buzbeea114add2012-05-03 15:00:40 -0700247 */
buzbeefa57c472012-11-21 12:06:18 -0800248 DCHECK((cu->live_sreg == INVALID_SREG) ||
249 (rl_dest.s_reg_low != cu->live_sreg));
250 cu->live_sreg = rl_dest.s_reg_low;
buzbee3d661942012-03-14 17:37:27 -0700251#endif
buzbeefa57c472012-11-21 12:06:18 -0800252 LIR* def_start;
253 LIR* def_end;
buzbee02031b12012-11-23 09:41:35 -0800254 DCHECK_EQ(IsFpReg(rl_src.low_reg), IsFpReg(rl_src.high_reg));
buzbeefa57c472012-11-21 12:06:18 -0800255 DCHECK(rl_dest.wide);
256 DCHECK(rl_src.wide);
257 if (rl_src.location == kLocPhysReg) {
258 if (IsLive(cu, rl_src.low_reg) ||
259 IsLive(cu, rl_src.high_reg) ||
260 IsPromoted(cu, rl_src.low_reg) ||
261 IsPromoted(cu, rl_src.high_reg) ||
262 (rl_dest.location == kLocPhysReg)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 // Src is live or promoted or Dest has assigned reg.
buzbeefa57c472012-11-21 12:06:18 -0800264 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
265 OpRegCopyWide(cu, rl_dest.low_reg, rl_dest.high_reg,
266 rl_src.low_reg, rl_src.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700267 } else {
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 // Just re-assign the registers. Dest gets Src's regs
buzbeefa57c472012-11-21 12:06:18 -0800269 rl_dest.low_reg = rl_src.low_reg;
270 rl_dest.high_reg = rl_src.high_reg;
271 Clobber(cu, rl_src.low_reg);
272 Clobber(cu, rl_src.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700273 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700274 } else {
275 // Load Src either into promoted Dest or temps allocated for Dest
buzbeefa57c472012-11-21 12:06:18 -0800276 rl_dest = EvalLoc(cu, rl_dest, kAnyReg, false);
277 LoadValueDirectWide(cu, rl_src, rl_dest.low_reg, rl_dest.high_reg);
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 }
buzbee67bf8852011-08-17 17:51:35 -0700279
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 // Dest is now live and dirty (until/if we flush it to home location)
buzbeefa57c472012-11-21 12:06:18 -0800281 MarkLive(cu, rl_dest.low_reg, rl_dest.s_reg_low);
282 MarkLive(cu, rl_dest.high_reg, GetSRegHi(rl_dest.s_reg_low));
283 MarkDirty(cu, rl_dest);
284 MarkPair(cu, rl_dest.low_reg, rl_dest.high_reg);
buzbee67bf8852011-08-17 17:51:35 -0700285
286
buzbeefa57c472012-11-21 12:06:18 -0800287 ResetDefLocWide(cu, rl_dest);
288 if ((IsDirty(cu, rl_dest.low_reg) ||
289 IsDirty(cu, rl_dest.high_reg)) &&
290 (oat_live_out(cu, rl_dest.s_reg_low) ||
291 oat_live_out(cu, GetSRegHi(rl_dest.s_reg_low)))) {
292 def_start = cu->last_lir_insn;
293 DCHECK_EQ((SRegToVReg(cu, rl_dest.s_reg_low)+1),
294 SRegToVReg(cu, GetSRegHi(rl_dest.s_reg_low)));
295 StoreBaseDispWide(cu, TargetReg(kSp), SRegOffset(cu, rl_dest.s_reg_low),
296 rl_dest.low_reg, rl_dest.high_reg);
297 MarkClean(cu, rl_dest);
298 def_end = cu->last_lir_insn;
299 MarkDefWide(cu, rl_dest, def_start, def_end);
Bill Buzbeea114add2012-05-03 15:00:40 -0700300 }
buzbee67bf8852011-08-17 17:51:35 -0700301}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800302
buzbeee1965672012-03-11 18:39:19 -0700303/* Utilities to load the current Method* */
buzbee02031b12012-11-23 09:41:35 -0800304void Codegen::LoadCurrMethodDirect(CompilationUnit *cu, int r_tgt)
buzbee31a4a6f2012-02-28 15:36:15 -0800305{
buzbeefa57c472012-11-21 12:06:18 -0800306 LoadValueDirectFixed(cu, cu->method_loc, r_tgt);
buzbee31a4a6f2012-02-28 15:36:15 -0800307}
308
buzbee02031b12012-11-23 09:41:35 -0800309RegLocation Codegen::LoadCurrMethod(CompilationUnit *cu)
buzbee31a4a6f2012-02-28 15:36:15 -0800310{
buzbeefa57c472012-11-21 12:06:18 -0800311 return LoadValue(cu, cu->method_loc, kCoreReg);
buzbee31a4a6f2012-02-28 15:36:15 -0800312}
313
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800314} // namespace art