blob: 11e18a7e98b2f1910615e762c6ee0a89a2e24837 [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Dalvik.h"
18#include "CompilerInternals.h"
19#include "Dataflow.h"
20#include "codegen/Ralloc.h"
21
buzbee03fa2632011-09-20 17:10:57 -070022static bool setFp(CompilationUnit* cUnit, int index, bool isFP) {
23 bool change = false;
24 if (isFP && !cUnit->regLocation[index].fp) {
25 cUnit->regLocation[index].fp = true;
26 change = true;
27 }
28 return change;
29}
30
buzbee67bf8852011-08-17 17:51:35 -070031/*
buzbee03fa2632011-09-20 17:10:57 -070032 * Infer types and sizes. We don't need to track change on sizes,
33 * as it doesn't propagate. We're guaranteed at least one pass through
34 * the cfg.
buzbee67bf8852011-08-17 17:51:35 -070035 */
buzbee03fa2632011-09-20 17:10:57 -070036static bool inferTypeAndSize(CompilationUnit* cUnit, BasicBlock* bb)
buzbee67bf8852011-08-17 17:51:35 -070037{
38 MIR *mir;
buzbee03fa2632011-09-20 17:10:57 -070039 bool changed = false; // Did anything change?
40
41 if (bb->dataFlowInfo == NULL) return false;
buzbee67bf8852011-08-17 17:51:35 -070042 if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock)
buzbee03fa2632011-09-20 17:10:57 -070043 return false;
buzbee67bf8852011-08-17 17:51:35 -070044
45 for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
46 SSARepresentation *ssaRep = mir->ssaRep;
47 if (ssaRep) {
buzbee03fa2632011-09-20 17:10:57 -070048 int attrs = oatDataFlowAttributes[mir->dalvikInsn.opcode];
49 int next = 0;
50 if (attrs & DF_DA_WIDE) {
51 cUnit->regLocation[ssaRep->defs[0]].wide = true;
buzbee67bf8852011-08-17 17:51:35 -070052 }
buzbee03fa2632011-09-20 17:10:57 -070053 if (attrs & DF_UA_WIDE) {
54 cUnit->regLocation[ssaRep->uses[next]].wide = true;
55 next += 2;
56 }
57 if (attrs & DF_UB_WIDE) {
58 cUnit->regLocation[ssaRep->uses[next]].wide = true;
59 next += 2;
60 }
61 if (attrs & DF_UC_WIDE) {
62 cUnit->regLocation[ssaRep->uses[next]].wide = true;
63 }
64 for (int i=0; ssaRep->fpUse && i< ssaRep->numUses; i++) {
65 if (ssaRep->fpUse[i])
66 changed |= setFp(cUnit, ssaRep->uses[i], true);
67 }
68 for (int i=0; ssaRep->fpDef && i< ssaRep->numDefs; i++) {
buzbee67bf8852011-08-17 17:51:35 -070069 if (ssaRep->fpDef[i])
buzbee03fa2632011-09-20 17:10:57 -070070 changed |= setFp(cUnit, ssaRep->defs[i], true);
71 }
72 // Special-case handling for moves & Phi
73 if (attrs & (DF_IS_MOVE | DF_NULL_TRANSFER_N)) {
74 bool isFP = cUnit->regLocation[ssaRep->defs[0]].fp;
75 for (int i = 0; i < ssaRep->numUses; i++) {
76 isFP |= cUnit->regLocation[ssaRep->uses[i]].fp;
77 }
78 changed |= setFp(cUnit, ssaRep->defs[0], isFP);
79 for (int i = 0; i < ssaRep->numUses; i++) {
80 changed |= setFp(cUnit, ssaRep->uses[i], isFP);
81 }
buzbee67bf8852011-08-17 17:51:35 -070082 }
83 }
84 }
buzbee03fa2632011-09-20 17:10:57 -070085 return changed;
buzbee67bf8852011-08-17 17:51:35 -070086}
87
88static const char* storageName[] = {" Frame ", "PhysReg", " Spill "};
89
buzbeedfd3d702011-08-28 12:56:51 -070090void oatDumpRegLocTable(RegLocation* table, int count)
buzbee67bf8852011-08-17 17:51:35 -070091{
92 for (int i = 0; i < count; i++) {
93 char buf[100];
94 snprintf(buf, 100, "Loc[%02d] : %s, %c %c r%d r%d S%d : %s s%d s%d",
95 i, storageName[table[i].location], table[i].wide ? 'W' : 'N',
96 table[i].fp ? 'F' : 'C', table[i].lowReg, table[i].highReg,
97 table[i].sRegLow, storageName[table[i].fpLocation],
98 table[i].fpLowReg & FP_REG_MASK, table[i].fpHighReg &
99 FP_REG_MASK);
100 LOG(INFO) << buf;
101 }
102}
103
104static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, INVALID_REG,
105 INVALID_REG, INVALID_SREG, 0,
106 kLocDalvikFrame, INVALID_REG, INVALID_REG,
107 INVALID_OFFSET};
108
109/*
110 * Simple register allocation. Some Dalvik virtual registers may
111 * be promoted to physical registers. Most of the work for temp
112 * allocation is done on the fly. We also do some initilization and
113 * type inference here.
114 */
115void oatSimpleRegAlloc(CompilationUnit* cUnit)
116{
117 int i;
118 RegLocation* loc;
119
120 /* Allocate the location map */
121 loc = (RegLocation*)oatNew(cUnit->numSSARegs * sizeof(*loc), true);
122 for (i=0; i< cUnit->numSSARegs; i++) {
123 loc[i] = freshLoc;
124 loc[i].sRegLow = i;
125 }
126 cUnit->regLocation = loc;
127
buzbeee9a72f62011-09-04 17:59:07 -0700128 /* Add types of incoming arguments based on signature */
129 int numRegs = cUnit->method->NumRegisters();
130 int numIns = cUnit->method->NumIns();
131 if (numIns > 0) {
132 int sReg = numRegs - numIns;
133 if (!cUnit->method->IsStatic()) {
134 // Skip past "this"
135 sReg++;
136 }
Brian Carlstromc74255f2011-09-11 22:47:39 -0700137 const String* shorty = cUnit->method->GetShorty();
Brian Carlstrom2ed67392011-09-09 14:53:28 -0700138 for (int i = 1; i < shorty->GetLength(); i++) {
139 char arg = shorty->CharAt(i);
buzbeee9a72f62011-09-04 17:59:07 -0700140 // Is it wide?
141 if ((arg == 'D') || (arg == 'J')) {
142 cUnit->regLocation[sReg].wide = true;
143 cUnit->regLocation[sReg+1].fp = cUnit->regLocation[sReg].fp;
144 sReg++; // Skip to next
145 }
146 sReg++;
147 }
148 }
149
buzbee03fa2632011-09-20 17:10:57 -0700150 /* Do type & size inference pass */
151 oatDataFlowAnalysisDispatcher(cUnit, inferTypeAndSize,
152 kPreOrderDFSTraversal,
153 true /* isIterative */);
buzbee67bf8852011-08-17 17:51:35 -0700154
155 /*
156 * Set the sRegLow field to refer to the pre-SSA name of the
157 * base Dalvik virtual register. Once we add a better register
158 * allocator, remove this remapping.
159 */
160 for (i=0; i < cUnit->numSSARegs; i++) {
161 cUnit->regLocation[i].sRegLow =
162 DECODE_REG(oatConvertSSARegToDalvik(cUnit, loc[i].sRegLow));
163 }
164
165 cUnit->coreSpillMask = 0;
166 cUnit->fpSpillMask = 0;
167 cUnit->numSpills = 0;
168
169 oatDoPromotion(cUnit);
170
171 if (cUnit->printMe && !(cUnit->disableOpt & (1 << kPromoteRegs))) {
172 LOG(INFO) << "After Promotion";
buzbeedfd3d702011-08-28 12:56:51 -0700173 oatDumpRegLocTable(cUnit->regLocation, cUnit->numSSARegs);
buzbee67bf8852011-08-17 17:51:35 -0700174 }
175
176 /* Figure out the frame size */
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700177 cUnit->numIns = cUnit->method->NumIns();
178 cUnit->numRegs = cUnit->method->NumRegisters() - cUnit->numIns;
179 cUnit->numOuts = cUnit->method->NumOuts();
buzbee67bf8852011-08-17 17:51:35 -0700180 cUnit->numPadding = (STACK_ALIGN_WORDS -
181 (cUnit->numSpills + cUnit->numRegs +
182 cUnit->numOuts + 2)) & (STACK_ALIGN_WORDS-1);
183 cUnit->frameSize = (cUnit->numSpills + cUnit->numRegs + cUnit->numOuts +
184 cUnit->numPadding + 2) * 4;
185 cUnit->insOffset = cUnit->frameSize + 4;
186 cUnit->regsOffset = (cUnit->numOuts + cUnit->numPadding + 1) * 4;
187
188 /* Compute sp-relative home location offsets */
189 for (i = 0; i < cUnit->numSSARegs; i++) {
190 int vReg = oatS2VReg(cUnit, cUnit->regLocation[i].sRegLow);
191 cUnit->regLocation[i].spOffset = oatVRegOffset(cUnit, vReg);
192 }
193}