blob: b17855bb3f1195b2cfcda83528b77ef52094555d [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"
buzbeec143c552011-08-20 17:38:58 -070021#include <vector>
buzbee67bf8852011-08-17 17:51:35 -070022
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080023namespace art {
24
buzbee67bf8852011-08-17 17:51:35 -070025typedef enum RegisterClass {
26 kCoreReg,
27 kFPReg,
28 kAnyReg,
29} RegisterClass;
30
31typedef enum RegLocationType {
32 kLocDalvikFrame = 0, // Normal Dalvik register
33 kLocPhysReg,
34 kLocSpill,
35} RegLocationType;
36
buzbee67bc2362011-10-11 18:08:40 -070037typedef struct PromotionMap {
38 RegLocationType coreLocation:3;
39 u1 coreReg;
40 RegLocationType fpLocation:3;
41 u1 fpReg;
42 bool firstInPair;
43} PromotionMap;
44
buzbee67bf8852011-08-17 17:51:35 -070045typedef struct RegLocation {
buzbee67bc2362011-10-11 18:08:40 -070046 RegLocationType location:3;
buzbee67bf8852011-08-17 17:51:35 -070047 unsigned wide:1;
buzbee67bc2362011-10-11 18:08:40 -070048 unsigned defined:1; // Do we know the type?
49 unsigned fp:1; // Floating point?
50 unsigned core:1; // Non-floating point?
51 unsigned highWord:1; // High word of pair?
52 unsigned home:1; // Does this represent the home location?
53 u1 lowReg; // First physical register
54 u1 highReg; // 2nd physical register (if wide)
55 s2 sRegLow; // SSA name for low Dalvik word
buzbee67bf8852011-08-17 17:51:35 -070056} RegLocation;
57
58#define INVALID_SREG (-1)
buzbee3ddc0d12011-10-05 10:36:21 -070059#define INVALID_VREG (0xFFFFU)
buzbee67bc2362011-10-11 18:08:40 -070060#define INVALID_REG (0xFF)
buzbee67bf8852011-08-17 17:51:35 -070061#define INVALID_OFFSET (-1)
62
buzbee99ba9642012-01-25 14:23:14 -080063/*
64 * Some code patterns cause the generation of excessively large
65 * methods - in particular initialization sequences. There isn't much
66 * benefit in optimizing these methods, and the cost can be very high.
67 * We attempt to identify these cases, and avoid performing most dataflow
68 * analysis. Two thresholds are used - one for known initializers and one
buzbee5abfa3e2012-01-31 17:01:43 -080069 * for everything else.
buzbee99ba9642012-01-25 14:23:14 -080070 */
buzbee5abfa3e2012-01-31 17:01:43 -080071#define MANY_BLOCKS_INITIALIZER 1000 /* Threshold for switching dataflow off */
72#define MANY_BLOCKS 4000 /* Non-initializer threshold */
buzbee99ba9642012-01-25 14:23:14 -080073
buzbee67bf8852011-08-17 17:51:35 -070074typedef enum BBType {
75 kEntryBlock,
76 kDalvikByteCode,
77 kExitBlock,
78 kExceptionHandling,
79 kCatchEntry,
80} BBType;
81
82typedef struct LIR {
83 int offset; // Offset of this instruction
84 int dalvikOffset; // Offset of Dalvik opcode
85 struct LIR* next;
86 struct LIR* prev;
87 struct LIR* target;
88} LIR;
89
90enum ExtendedMIROpcode {
91 kMirOpFirst = kNumPackedOpcodes,
92 kMirOpPhi = kMirOpFirst,
93 kMirOpNullNRangeUpCheck,
94 kMirOpNullNRangeDownCheck,
95 kMirOpLowerBound,
96 kMirOpPunt,
97 kMirOpCheckInlinePrediction, // Gen checks for predicted inlining
98 kMirOpLast,
99};
100
101struct SSARepresentation;
102
103typedef enum {
104 kMIRIgnoreNullCheck = 0,
105 kMIRNullCheckOnly,
106 kMIRIgnoreRangeCheck,
107 kMIRRangeCheckOnly,
108 kMIRInlined, // Invoke is inlined (ie dead)
109 kMIRInlinedPred, // Invoke is inlined via prediction
110 kMIRCallee, // Instruction is inlined from callee
buzbeec1f45042011-09-21 16:03:19 -0700111 kMIRIgnoreSuspendCheck,
buzbee67bf8852011-08-17 17:51:35 -0700112} MIROptimizationFlagPositons;
113
114#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
115#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
116#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
117#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
118#define MIR_INLINED (1 << kMIRInlined)
119#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
120#define MIR_CALLEE (1 << kMIRCallee)
buzbeec1f45042011-09-21 16:03:19 -0700121#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck)
buzbee67bf8852011-08-17 17:51:35 -0700122
123typedef struct CallsiteInfo {
124 const char* classDescriptor;
125 Object* classLoader;
126 const Method* method;
127 LIR* misPredBranchOver;
128} CallsiteInfo;
129
130typedef struct MIR {
131 DecodedInstruction dalvikInsn;
132 unsigned int width;
133 unsigned int offset;
134 struct MIR* prev;
135 struct MIR* next;
136 struct SSARepresentation* ssaRep;
buzbee43a36422011-09-14 14:00:13 -0700137 int optimizationFlags;
buzbee67bf8852011-08-17 17:51:35 -0700138 int seqNum;
139 union {
140 // Used by the inlined insn from the callee to find the mother method
141 const Method* calleeMethod;
142 // Used by the inlined invoke to find the class and method pointers
143 CallsiteInfo* callsiteInfo;
buzbeec0ecd652011-09-25 18:11:54 -0700144 // Used to quickly locate all Phi opcodes
145 struct MIR* phiNext;
buzbee67bf8852011-08-17 17:51:35 -0700146 } meta;
147} MIR;
148
149struct BasicBlockDataFlow;
150
151/* For successorBlockList */
152typedef enum BlockListType {
153 kNotUsed = 0,
154 kCatch,
155 kPackedSwitch,
156 kSparseSwitch,
157} BlockListType;
158
159typedef struct BasicBlock {
160 int id;
buzbee5b537102012-01-17 17:33:47 -0800161 int dfsId;
buzbee67bf8852011-08-17 17:51:35 -0700162 bool visited;
163 bool hidden;
buzbee43a36422011-09-14 14:00:13 -0700164 bool catchEntry;
buzbee67bf8852011-08-17 17:51:35 -0700165 unsigned int startOffset;
166 const Method* containingMethod; // For blocks from the callee
167 BBType blockType;
168 bool needFallThroughBranch; // For blocks ended due to length limit
169 bool isFallThroughFromInvoke; // True means the block needs alignment
170 MIR* firstMIRInsn;
171 MIR* lastMIRInsn;
172 struct BasicBlock* fallThrough;
173 struct BasicBlock* taken;
174 struct BasicBlock* iDom; // Immediate dominator
175 struct BasicBlockDataFlow* dataFlowInfo;
buzbee5abfa3e2012-01-31 17:01:43 -0800176 GrowableList* predecessors;
buzbee67bf8852011-08-17 17:51:35 -0700177 ArenaBitVector* dominators;
178 ArenaBitVector* iDominated; // Set nodes being immediately dominated
179 ArenaBitVector* domFrontier; // Dominance frontier
180 struct { // For one-to-many successors like
181 BlockListType blockListType; // switch and exception handling
182 GrowableList blocks;
183 } successorBlockList;
184} BasicBlock;
185
186/*
187 * The "blocks" field in "successorBlockList" points to an array of
188 * elements with the type "SuccessorBlockInfo".
189 * For catch blocks, key is type index for the exception.
190 * For swtich blocks, key is the case value.
191 */
192typedef struct SuccessorBlockInfo {
193 BasicBlock* block;
194 int key;
195} SuccessorBlockInfo;
196
197struct LoopAnalysis;
198struct RegisterPool;
199
200typedef enum AssemblerStatus {
201 kSuccess,
202 kRetryAll,
203 kRetryHalve
204} AssemblerStatus;
205
buzbee5b537102012-01-17 17:33:47 -0800206#define NOTVISITED (-1)
207
buzbee67bf8852011-08-17 17:51:35 -0700208typedef struct CompilationUnit {
209 int numInsts;
210 int numBlocks;
211 GrowableList blockList;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800212 const Compiler* compiler; // Compiler driving this compiler
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800213 ClassLinker* class_linker; // Linker to resolve fields and methods
214 const DexFile* dex_file; // DexFile containing the method being compiled
215 DexCache* dex_cache; // DexFile's corresponding cache
216 const ClassLoader* class_loader; // compiling method's class loader
Ian Rogersa3760aa2011-11-14 14:32:37 -0800217 uint32_t method_idx; // compiling method's index into method_ids of DexFile
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800218 const DexFile::CodeItem* code_item; // compiling method's DexFile code_item
Ian Rogersa3760aa2011-11-14 14:32:37 -0800219 uint32_t access_flags; // compiling method's access flags
220 const char* shorty; // compiling method's shorty
buzbee67bf8852011-08-17 17:51:35 -0700221 LIR* firstLIRInsn;
222 LIR* lastLIRInsn;
223 LIR* literalList; // Constants
224 LIR* classPointerList; // Relocatable
225 int numClassPointers;
226 LIR* chainCellOffsetLIR;
buzbeece302932011-10-04 14:32:18 -0700227 uint32_t disableOpt; // optControlVector flags
228 uint32_t enableDebug; // debugControlVector flags
buzbee67bf8852011-08-17 17:51:35 -0700229 int headerSize; // bytes before the first code ptr
230 int dataOffset; // starting offset of literal pool
231 int totalSize; // header + code size
232 AssemblerStatus assemblerStatus; // Success or fix and retry
233 int assemblerRetries;
Brian Carlstrome7d856b2012-01-11 18:10:55 -0800234 std::vector<uint16_t> codeBuffer;
buzbee4ef76522011-09-08 10:00:32 -0700235 std::vector<uint32_t> mappingTable;
buzbee3ddc0d12011-10-05 10:36:21 -0700236 std::vector<uint16_t> coreVmapTable;
237 std::vector<uint16_t> fpVmapTable;
buzbee67bf8852011-08-17 17:51:35 -0700238 bool printMe;
buzbee67bf8852011-08-17 17:51:35 -0700239 bool hasClassLiterals; // Contains class ptrs used as literals
240 bool hasLoop; // Contains a loop
241 bool hasInvoke; // Contains an invoke instruction
242 bool heapMemOp; // Mark mem ops for self verification
243 bool usesLinkRegister; // For self-verification only
244 bool methodTraceSupport; // For TraceView profiling
245 struct RegisterPool* regPool;
246 int optRound; // round number to tell an LIR's age
247 OatInstructionSetType instructionSet;
248 /* Number of total regs used in the whole cUnit after SSA transformation */
249 int numSSARegs;
250 /* Map SSA reg i to the Dalvik[15..0]/Sub[31..16] pair. */
251 GrowableList* ssaToDalvikMap;
252
253 /* The following are new data structures to support SSA representations */
254 /* Map original Dalvik reg i to the SSA[15..0]/Sub[31..16] pair */
255 int* dalvikToSSAMap; // length == method->registersSize
buzbeef0cde542011-09-13 14:55:02 -0700256 int* SSALastDefs; // length == method->registersSize
buzbee67bf8852011-08-17 17:51:35 -0700257 ArenaBitVector* isConstantV; // length == numSSAReg
258 int* constantValues; // length == numSSAReg
buzbeec0ecd652011-09-25 18:11:54 -0700259 int* phiAliasMap; // length == numSSAReg
260 MIR* phiList;
buzbee67bf8852011-08-17 17:51:35 -0700261
262 /* Map SSA names to location */
263 RegLocation* regLocation;
264 int sequenceNumber;
265
buzbee67bc2362011-10-11 18:08:40 -0700266 /* Keep track of Dalvik vReg to physical register mappings */
267 PromotionMap* promotionMap;
268
buzbee67bf8852011-08-17 17:51:35 -0700269 /*
270 * Set to the Dalvik PC of the switch instruction if it has more than
271 * MAX_CHAINED_SWITCH_CASES cases.
272 */
273 const u2* switchOverflowPad;
274
275 int numReachableBlocks;
276 int numDalvikRegisters; // method->registersSize + inlined
277 BasicBlock* entryBlock;
278 BasicBlock* exitBlock;
279 BasicBlock* curBlock;
280 BasicBlock* nextCodegenBlock; // for extended trace codegen
281 GrowableList dfsOrder;
buzbee5b537102012-01-17 17:33:47 -0800282 GrowableList dfsPostOrder;
buzbee67bf8852011-08-17 17:51:35 -0700283 GrowableList domPostOrderTraversal;
buzbee5ade1d22011-09-09 14:44:52 -0700284 GrowableList throwLaunchpads;
buzbeec1f45042011-09-21 16:03:19 -0700285 GrowableList suspendLaunchpads;
buzbee5b537102012-01-17 17:33:47 -0800286 int* iDomList;
buzbee67bf8852011-08-17 17:51:35 -0700287 ArenaBitVector* tryBlockAddr;
288 ArenaBitVector** defBlockMatrix; // numDalvikRegister x numBlocks
289 ArenaBitVector* tempBlockV;
290 ArenaBitVector* tempDalvikRegisterV;
291 ArenaBitVector* tempSSARegisterV; // numSSARegs
292 bool printSSANames;
293 void* blockLabelList;
294 bool quitLoopMode; // cold path/complex bytecode
295 int preservedRegsUsed; // How many callee save regs used
296 /*
buzbee5ade1d22011-09-09 14:44:52 -0700297 * Frame layout details.
298 * NOTE: for debug support it will be necessary to add a structure
299 * to map the Dalvik virtual registers to the promoted registers.
300 * NOTE: "num" fields are in 4-byte words, "Size" and "Offset" in bytes.
buzbee67bf8852011-08-17 17:51:35 -0700301 */
302 int numIns;
303 int numOuts;
Ian Rogersa3760aa2011-11-14 14:32:37 -0800304 int numRegs; // Unlike numDalvikRegisters, does not include ins
buzbeebbaf8942011-10-02 13:08:29 -0700305 int numCoreSpills;
buzbee67bf8852011-08-17 17:51:35 -0700306 int numFPSpills;
307 int numPadding; // # of 4-byte padding cells
308 int regsOffset; // sp-relative offset to beginning of Dalvik regs
309 int insOffset; // sp-relative offset to beginning of Dalvik ins
310 int frameSize;
311 unsigned int coreSpillMask;
312 unsigned int fpSpillMask;
buzbeecefd1872011-09-09 09:59:52 -0700313 unsigned int attrs;
buzbee67bf8852011-08-17 17:51:35 -0700314 /*
315 * CLEANUP/RESTRUCTURE: The code generation utilities don't have a built-in
buzbee03fa2632011-09-20 17:10:57 -0700316 * mechanism to propagate the original Dalvik opcode address to the
buzbee67bf8852011-08-17 17:51:35 -0700317 * associated generated instructions. For the trace compiler, this wasn't
318 * necessary because the interpreter handled all throws and debugging
319 * requests. For now we'll handle this by placing the Dalvik offset
320 * in the CompilationUnit struct before codegen for each instruction.
321 * The low-level LIR creation utilites will pull it from here. Should
322 * be rewritten.
323 */
324 int currentDalvikOffset;
325 GrowableList switchTables;
buzbee67bf8852011-08-17 17:51:35 -0700326 GrowableList fillArrayData;
327 const u2* insns;
328 u4 insnsSize;
buzbee99ba9642012-01-25 14:23:14 -0800329 bool disableDataflow; // Skip dataflow analysis if possible
buzbee5b537102012-01-17 17:33:47 -0800330 std::map<unsigned int, BasicBlock*> blockMap; // findBlock lookup cache
buzbee85d8c1e2012-01-27 15:52:35 -0800331 std::map<unsigned int, LIR*> boundaryMap; // boundary lookup cache
buzbee5abfa3e2012-01-31 17:01:43 -0800332 int defCount; // Used to estimate number of SSA names
buzbee67bf8852011-08-17 17:51:35 -0700333} CompilationUnit;
334
buzbee5abfa3e2012-01-31 17:01:43 -0800335BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId);
buzbee67bf8852011-08-17 17:51:35 -0700336
337void oatAppendMIR(BasicBlock* bb, MIR* mir);
338
339void oatPrependMIR(BasicBlock* bb, MIR* mir);
340
341void oatInsertMIRAfter(BasicBlock* bb, MIR* currentMIR, MIR* newMIR);
342
343void oatAppendLIR(CompilationUnit* cUnit, LIR* lir);
344
345void oatInsertLIRBefore(LIR* currentLIR, LIR* newLIR);
346
347void oatInsertLIRAfter(LIR* currentLIR, LIR* newLIR);
348
349/* Debug Utilities */
350void oatDumpCompilationUnit(CompilationUnit* cUnit);
351
Elliott Hughes11d1b0c2012-01-23 16:57:47 -0800352} // namespace art
353
buzbee67bf8852011-08-17 17:51:35 -0700354#endif // ART_SRC_COMPILER_COMPILER_IR_H_