blob: 66cc3225c98fbffe3aa393ef283ec8e4b018cfc8 [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#ifndef ART_SRC_COMPILER_COMPILER_IR_H_
18#define ART_SRC_COMPILER_COMPILER_IR_H_
19
20#include "codegen/Optimizer.h"
Ian Rogers1bddec32012-02-04 12:27:34 -080021#include "CompilerUtility.h"
buzbeec143c552011-08-20 17:38:58 -070022#include <vector>
buzbee67bf8852011-08-17 17:51:35 -070023
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080024namespace art {
25
buzbee67bf8852011-08-17 17:51:35 -070026typedef enum RegisterClass {
27 kCoreReg,
28 kFPReg,
29 kAnyReg,
30} RegisterClass;
31
32typedef enum RegLocationType {
33 kLocDalvikFrame = 0, // Normal Dalvik register
34 kLocPhysReg,
35 kLocSpill,
36} RegLocationType;
37
buzbee67bc2362011-10-11 18:08:40 -070038typedef struct PromotionMap {
39 RegLocationType coreLocation:3;
40 u1 coreReg;
41 RegLocationType fpLocation:3;
42 u1 fpReg;
43 bool firstInPair;
44} PromotionMap;
45
buzbee67bf8852011-08-17 17:51:35 -070046typedef struct RegLocation {
buzbee67bc2362011-10-11 18:08:40 -070047 RegLocationType location:3;
buzbee67bf8852011-08-17 17:51:35 -070048 unsigned wide:1;
buzbee67bc2362011-10-11 18:08:40 -070049 unsigned defined:1; // Do we know the type?
50 unsigned fp:1; // Floating point?
51 unsigned core:1; // Non-floating point?
52 unsigned highWord:1; // High word of pair?
53 unsigned home:1; // Does this represent the home location?
54 u1 lowReg; // First physical register
55 u1 highReg; // 2nd physical register (if wide)
56 s2 sRegLow; // SSA name for low Dalvik word
buzbee67bf8852011-08-17 17:51:35 -070057} RegLocation;
58
buzbeee3acd072012-02-25 17:03:10 -080059 /*
60 * Data structure tracking the mapping between a Dalvik register (pair) and a
61 * native register (pair). The idea is to reuse the previously loaded value
62 * if possible, otherwise to keep the value in a native register as long as
63 * possible.
64 */
65typedef struct RegisterInfo {
66 int reg; // Reg number
67 bool inUse; // Has it been allocated?
68 bool isTemp; // Can allocate as temp?
69 bool pair; // Part of a register pair?
70 int partner; // If pair, other reg of pair
71 bool live; // Is there an associated SSA name?
72 bool dirty; // If live, is it dirty?
73 int sReg; // Name of live value
74 struct LIR *defStart; // Starting inst in last def sequence
75 struct LIR *defEnd; // Ending inst in last def sequence
76} RegisterInfo;
77
78typedef struct RegisterPool {
79 int numCoreRegs;
80 RegisterInfo *coreRegs;
81 int nextCoreReg;
82 int numFPRegs;
83 RegisterInfo *FPRegs;
84 int nextFPReg;
85} RegisterPool;
86
buzbee67bf8852011-08-17 17:51:35 -070087#define INVALID_SREG (-1)
buzbee3ddc0d12011-10-05 10:36:21 -070088#define INVALID_VREG (0xFFFFU)
buzbee67bc2362011-10-11 18:08:40 -070089#define INVALID_REG (0xFF)
buzbee67bf8852011-08-17 17:51:35 -070090#define INVALID_OFFSET (-1)
91
buzbee99ba9642012-01-25 14:23:14 -080092/*
93 * Some code patterns cause the generation of excessively large
94 * methods - in particular initialization sequences. There isn't much
95 * benefit in optimizing these methods, and the cost can be very high.
96 * We attempt to identify these cases, and avoid performing most dataflow
97 * analysis. Two thresholds are used - one for known initializers and one
buzbee5abfa3e2012-01-31 17:01:43 -080098 * for everything else.
buzbee99ba9642012-01-25 14:23:14 -080099 */
buzbee5abfa3e2012-01-31 17:01:43 -0800100#define MANY_BLOCKS_INITIALIZER 1000 /* Threshold for switching dataflow off */
101#define MANY_BLOCKS 4000 /* Non-initializer threshold */
buzbee99ba9642012-01-25 14:23:14 -0800102
buzbee67bf8852011-08-17 17:51:35 -0700103typedef enum BBType {
104 kEntryBlock,
105 kDalvikByteCode,
106 kExitBlock,
107 kExceptionHandling,
108 kCatchEntry,
109} BBType;
110
111typedef struct LIR {
112 int offset; // Offset of this instruction
113 int dalvikOffset; // Offset of Dalvik opcode
114 struct LIR* next;
115 struct LIR* prev;
116 struct LIR* target;
117} LIR;
118
119enum ExtendedMIROpcode {
120 kMirOpFirst = kNumPackedOpcodes,
121 kMirOpPhi = kMirOpFirst,
122 kMirOpNullNRangeUpCheck,
123 kMirOpNullNRangeDownCheck,
124 kMirOpLowerBound,
125 kMirOpPunt,
126 kMirOpCheckInlinePrediction, // Gen checks for predicted inlining
127 kMirOpLast,
128};
129
130struct SSARepresentation;
131
132typedef enum {
133 kMIRIgnoreNullCheck = 0,
134 kMIRNullCheckOnly,
135 kMIRIgnoreRangeCheck,
136 kMIRRangeCheckOnly,
137 kMIRInlined, // Invoke is inlined (ie dead)
138 kMIRInlinedPred, // Invoke is inlined via prediction
139 kMIRCallee, // Instruction is inlined from callee
buzbeec1f45042011-09-21 16:03:19 -0700140 kMIRIgnoreSuspendCheck,
buzbee67bf8852011-08-17 17:51:35 -0700141} MIROptimizationFlagPositons;
142
143#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
144#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
145#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
146#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
147#define MIR_INLINED (1 << kMIRInlined)
148#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
149#define MIR_CALLEE (1 << kMIRCallee)
buzbeec1f45042011-09-21 16:03:19 -0700150#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck)
buzbee67bf8852011-08-17 17:51:35 -0700151
152typedef struct CallsiteInfo {
153 const char* classDescriptor;
154 Object* classLoader;
155 const Method* method;
156 LIR* misPredBranchOver;
157} CallsiteInfo;
158
159typedef struct MIR {
160 DecodedInstruction dalvikInsn;
161 unsigned int width;
162 unsigned int offset;
163 struct MIR* prev;
164 struct MIR* next;
165 struct SSARepresentation* ssaRep;
buzbee43a36422011-09-14 14:00:13 -0700166 int optimizationFlags;
buzbee67bf8852011-08-17 17:51:35 -0700167 int seqNum;
168 union {
169 // Used by the inlined insn from the callee to find the mother method
170 const Method* calleeMethod;
171 // Used by the inlined invoke to find the class and method pointers
172 CallsiteInfo* callsiteInfo;
buzbeec0ecd652011-09-25 18:11:54 -0700173 // Used to quickly locate all Phi opcodes
174 struct MIR* phiNext;
buzbee67bf8852011-08-17 17:51:35 -0700175 } meta;
176} MIR;
177
178struct BasicBlockDataFlow;
179
180/* For successorBlockList */
181typedef enum BlockListType {
182 kNotUsed = 0,
183 kCatch,
184 kPackedSwitch,
185 kSparseSwitch,
186} BlockListType;
187
188typedef struct BasicBlock {
189 int id;
buzbee5b537102012-01-17 17:33:47 -0800190 int dfsId;
buzbee67bf8852011-08-17 17:51:35 -0700191 bool visited;
192 bool hidden;
buzbee43a36422011-09-14 14:00:13 -0700193 bool catchEntry;
buzbee67bf8852011-08-17 17:51:35 -0700194 unsigned int startOffset;
195 const Method* containingMethod; // For blocks from the callee
196 BBType blockType;
197 bool needFallThroughBranch; // For blocks ended due to length limit
198 bool isFallThroughFromInvoke; // True means the block needs alignment
199 MIR* firstMIRInsn;
200 MIR* lastMIRInsn;
201 struct BasicBlock* fallThrough;
202 struct BasicBlock* taken;
203 struct BasicBlock* iDom; // Immediate dominator
204 struct BasicBlockDataFlow* dataFlowInfo;
buzbee5abfa3e2012-01-31 17:01:43 -0800205 GrowableList* predecessors;
buzbee67bf8852011-08-17 17:51:35 -0700206 ArenaBitVector* dominators;
207 ArenaBitVector* iDominated; // Set nodes being immediately dominated
208 ArenaBitVector* domFrontier; // Dominance frontier
209 struct { // For one-to-many successors like
210 BlockListType blockListType; // switch and exception handling
211 GrowableList blocks;
212 } successorBlockList;
213} BasicBlock;
214
215/*
216 * The "blocks" field in "successorBlockList" points to an array of
217 * elements with the type "SuccessorBlockInfo".
218 * For catch blocks, key is type index for the exception.
219 * For swtich blocks, key is the case value.
220 */
221typedef struct SuccessorBlockInfo {
222 BasicBlock* block;
223 int key;
224} SuccessorBlockInfo;
225
226struct LoopAnalysis;
227struct RegisterPool;
buzbeeba938cb2012-02-03 14:47:55 -0800228struct ArenaMemBlock;
229struct Memstats;
buzbee67bf8852011-08-17 17:51:35 -0700230
231typedef enum AssemblerStatus {
232 kSuccess,
233 kRetryAll,
234 kRetryHalve
235} AssemblerStatus;
236
buzbee5b537102012-01-17 17:33:47 -0800237#define NOTVISITED (-1)
238
buzbee67bf8852011-08-17 17:51:35 -0700239typedef struct CompilationUnit {
240 int numInsts;
241 int numBlocks;
242 GrowableList blockList;
Ian Rogers996cc582012-02-14 22:23:29 -0800243 Compiler* compiler; // Compiler driving this compiler
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800244 ClassLinker* class_linker; // Linker to resolve fields and methods
245 const DexFile* dex_file; // DexFile containing the method being compiled
246 DexCache* dex_cache; // DexFile's corresponding cache
247 const ClassLoader* class_loader; // compiling method's class loader
Ian Rogersa3760aa2011-11-14 14:32:37 -0800248 uint32_t method_idx; // compiling method's index into method_ids of DexFile
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800249 const DexFile::CodeItem* code_item; // compiling method's DexFile code_item
Ian Rogersa3760aa2011-11-14 14:32:37 -0800250 uint32_t access_flags; // compiling method's access flags
251 const char* shorty; // compiling method's shorty
buzbee67bf8852011-08-17 17:51:35 -0700252 LIR* firstLIRInsn;
253 LIR* lastLIRInsn;
254 LIR* literalList; // Constants
255 LIR* classPointerList; // Relocatable
256 int numClassPointers;
257 LIR* chainCellOffsetLIR;
buzbeece302932011-10-04 14:32:18 -0700258 uint32_t disableOpt; // optControlVector flags
259 uint32_t enableDebug; // debugControlVector flags
buzbee67bf8852011-08-17 17:51:35 -0700260 int headerSize; // bytes before the first code ptr
261 int dataOffset; // starting offset of literal pool
262 int totalSize; // header + code size
263 AssemblerStatus assemblerStatus; // Success or fix and retry
264 int assemblerRetries;
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800265 std::vector<uint16_t> codeBuffer;
buzbee4ef76522011-09-08 10:00:32 -0700266 std::vector<uint32_t> mappingTable;
buzbee3ddc0d12011-10-05 10:36:21 -0700267 std::vector<uint16_t> coreVmapTable;
268 std::vector<uint16_t> fpVmapTable;
buzbee44b412b2012-02-04 08:50:53 -0800269 bool genDebugger; // Generate code for debugger
buzbee67bf8852011-08-17 17:51:35 -0700270 bool printMe;
buzbee67bf8852011-08-17 17:51:35 -0700271 bool hasClassLiterals; // Contains class ptrs used as literals
272 bool hasLoop; // Contains a loop
273 bool hasInvoke; // Contains an invoke instruction
274 bool heapMemOp; // Mark mem ops for self verification
275 bool usesLinkRegister; // For self-verification only
276 bool methodTraceSupport; // For TraceView profiling
277 struct RegisterPool* regPool;
278 int optRound; // round number to tell an LIR's age
279 OatInstructionSetType instructionSet;
280 /* Number of total regs used in the whole cUnit after SSA transformation */
281 int numSSARegs;
282 /* Map SSA reg i to the Dalvik[15..0]/Sub[31..16] pair. */
283 GrowableList* ssaToDalvikMap;
284
285 /* The following are new data structures to support SSA representations */
286 /* Map original Dalvik reg i to the SSA[15..0]/Sub[31..16] pair */
287 int* dalvikToSSAMap; // length == method->registersSize
buzbeef0cde542011-09-13 14:55:02 -0700288 int* SSALastDefs; // length == method->registersSize
buzbee67bf8852011-08-17 17:51:35 -0700289 ArenaBitVector* isConstantV; // length == numSSAReg
290 int* constantValues; // length == numSSAReg
buzbeec0ecd652011-09-25 18:11:54 -0700291 int* phiAliasMap; // length == numSSAReg
292 MIR* phiList;
buzbee67bf8852011-08-17 17:51:35 -0700293
294 /* Map SSA names to location */
295 RegLocation* regLocation;
296 int sequenceNumber;
297
buzbee67bc2362011-10-11 18:08:40 -0700298 /* Keep track of Dalvik vReg to physical register mappings */
299 PromotionMap* promotionMap;
300
buzbee67bf8852011-08-17 17:51:35 -0700301 /*
302 * Set to the Dalvik PC of the switch instruction if it has more than
303 * MAX_CHAINED_SWITCH_CASES cases.
304 */
305 const u2* switchOverflowPad;
306
307 int numReachableBlocks;
308 int numDalvikRegisters; // method->registersSize + inlined
309 BasicBlock* entryBlock;
310 BasicBlock* exitBlock;
311 BasicBlock* curBlock;
312 BasicBlock* nextCodegenBlock; // for extended trace codegen
313 GrowableList dfsOrder;
buzbee5b537102012-01-17 17:33:47 -0800314 GrowableList dfsPostOrder;
buzbee67bf8852011-08-17 17:51:35 -0700315 GrowableList domPostOrderTraversal;
buzbee5ade1d22011-09-09 14:44:52 -0700316 GrowableList throwLaunchpads;
buzbeec1f45042011-09-21 16:03:19 -0700317 GrowableList suspendLaunchpads;
buzbee5b537102012-01-17 17:33:47 -0800318 int* iDomList;
buzbee67bf8852011-08-17 17:51:35 -0700319 ArenaBitVector* tryBlockAddr;
320 ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks
321 ArenaBitVector* tempBlockV;
322 ArenaBitVector* tempDalvikRegisterV;
323 ArenaBitVector* tempSSARegisterV; // numSSARegs
324 bool printSSANames;
325 void* blockLabelList;
326 bool quitLoopMode; // cold path/complex bytecode
327 int preservedRegsUsed; // How many callee save regs used
328 /*
buzbee5ade1d22011-09-09 14:44:52 -0700329 * Frame layout details.
330 * NOTE: for debug support it will be necessary to add a structure
331 * to map the Dalvik virtual registers to the promoted registers.
332 * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes.
buzbee67bf8852011-08-17 17:51:35 -0700333 */
334 int numIns;
335 int numOuts;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800336 int numRegs; // Unlike numDalvikRegisters, does not include ins
buzbeebbaf8942011-10-02 13:08:29 -0700337 int numCoreSpills;
buzbee67bf8852011-08-17 17:51:35 -0700338 int numFPSpills;
339 int numPadding; // # of 4-byte padding cells
340 int regsOffset; // sp-relative offset to beginning of Dalvik regs
341 int insOffset; // sp-relative offset to beginning of Dalvik ins
342 int frameSize;
343 unsigned int coreSpillMask;
344 unsigned int fpSpillMask;
buzbeecefd1872011-09-09 09:59:52 -0700345 unsigned int attrs;
buzbee67bf8852011-08-17 17:51:35 -0700346 /*
347 * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
buzbee03fa2632011-09-20 17:10:57 -0700348 * mechanism to propagate the original Dalvik opcode address to the
buzbee67bf8852011-08-17 17:51:35 -0700349 * associated generated instructions. For the trace compiler, this wasn't
350 * necessary because the interpreter handled all throws and debugging
351 * requests. For now we'll handle this by placing the Dalvik offset
352 * in the CompilationUnit struct before codegen for each instruction.
353 * The low-level LIR creation utilites will pull it from here. Should
354 * be rewritten.
355 */
356 int currentDalvikOffset;
357 GrowableList switchTables;
buzbee67bf8852011-08-17 17:51:35 -0700358 GrowableList fillArrayData;
359 const u2* insns;
360 u4 insnsSize;
buzbee99ba9642012-01-25 14:23:14 -0800361 bool disableDataflow; // Skip dataflow analysis if possible
buzbee5b537102012-01-17 17:33:47 -0800362 std::map<unsigned int, BasicBlock*> blockMap; // findBlock lookup cache
buzbee85d8c1e2012-01-27 15:52:35 -0800363 std::map<unsigned int, LIR*> boundaryMap; // boundary lookup cache
buzbee5abfa3e2012-01-31 17:01:43 -0800364 int defCount; // Used to estimate number of SSA names
buzbeeba938cb2012-02-03 14:47:55 -0800365 std::string* compilerMethodMatch;
366 bool compilerFlipMatch;
367 struct ArenaMemBlock* arenaHead;
368 struct ArenaMemBlock* currentArena;
369 int numArenaBlocks;
370 struct Memstats* mstats;
buzbee67bf8852011-08-17 17:51:35 -0700371} CompilationUnit;
372
buzbeee3acd072012-02-25 17:03:10 -0800373typedef enum OpSize {
374 kWord,
375 kLong,
376 kSingle,
377 kDouble,
378 kUnsignedHalf,
379 kSignedHalf,
380 kUnsignedByte,
381 kSignedByte,
382} OpSize;
383
buzbee5abfa3e2012-01-31 17:01:43 -0800384BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId);
buzbee67bf8852011-08-17 17:51:35 -0700385
386void oatAppendMIR(BasicBlock* bb, MIR* mir);
387
388void oatPrependMIR(BasicBlock* bb, MIR* mir);
389
390void oatInsertMIRAfter(BasicBlock* bb, MIR* currentMIR, MIR* newMIR);
391
392void oatAppendLIR(CompilationUnit* cUnit, LIR* lir);
393
394void oatInsertLIRBefore(LIR* currentLIR, LIR* newLIR);
395
396void oatInsertLIRAfter(LIR* currentLIR, LIR* newLIR);
397
398/* Debug Utilities */
399void oatDumpCompilationUnit(CompilationUnit* cUnit);
400
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800401} // namespace art
402
buzbee67bf8852011-08-17 17:51:35 -0700403#endif // ART_SRC_COMPILER_COMPILER_IR_H_