blob: 514205d07c9f0ddfde93aefcb9010ceb569de222 [file] [log] [blame]
buzbee311ca162013-02-28 15:56:43 -08001/*
2 * Copyright (C) 2013 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_DEX_MIRGRAPH_H_
18#define ART_SRC_COMPILER_DEX_MIRGRAPH_H_
19
20#include "dex_file.h"
21#include "dex_instruction.h"
22#include "compiler_ir.h"
23
24namespace art {
25
26enum DataFlowAttributePos {
27 kUA = 0,
28 kUB,
29 kUC,
30 kAWide,
31 kBWide,
32 kCWide,
33 kDA,
34 kIsMove,
35 kSetsConst,
36 kFormat35c,
37 kFormat3rc,
38 kNullCheckSrc0, // Null check of uses[0].
39 kNullCheckSrc1, // Null check of uses[1].
40 kNullCheckSrc2, // Null check of uses[2].
41 kNullCheckOut0, // Null check out outgoing arg0.
42 kDstNonNull, // May assume dst is non-null.
43 kRetNonNull, // May assume retval is non-null.
44 kNullTransferSrc0, // Object copy src[0] -> dst.
45 kNullTransferSrcN, // Phi null check state transfer.
46 kRangeCheckSrc1, // Range check of uses[1].
47 kRangeCheckSrc2, // Range check of uses[2].
48 kRangeCheckSrc3, // Range check of uses[3].
49 kFPA,
50 kFPB,
51 kFPC,
52 kCoreA,
53 kCoreB,
54 kCoreC,
55 kRefA,
56 kRefB,
57 kRefC,
58 kUsesMethodStar, // Implicit use of Method*.
59};
60
61#define DF_NOP 0
62#define DF_UA (1 << kUA)
63#define DF_UB (1 << kUB)
64#define DF_UC (1 << kUC)
65#define DF_A_WIDE (1 << kAWide)
66#define DF_B_WIDE (1 << kBWide)
67#define DF_C_WIDE (1 << kCWide)
68#define DF_DA (1 << kDA)
69#define DF_IS_MOVE (1 << kIsMove)
70#define DF_SETS_CONST (1 << kSetsConst)
71#define DF_FORMAT_35C (1 << kFormat35c)
72#define DF_FORMAT_3RC (1 << kFormat3rc)
73#define DF_NULL_CHK_0 (1 << kNullCheckSrc0)
74#define DF_NULL_CHK_1 (1 << kNullCheckSrc1)
75#define DF_NULL_CHK_2 (1 << kNullCheckSrc2)
76#define DF_NULL_CHK_OUT0 (1 << kNullCheckOut0)
77#define DF_NON_NULL_DST (1 << kDstNonNull)
78#define DF_NON_NULL_RET (1 << kRetNonNull)
79#define DF_NULL_TRANSFER_0 (1 << kNullTransferSrc0)
80#define DF_NULL_TRANSFER_N (1 << kNullTransferSrcN)
81#define DF_RANGE_CHK_1 (1 << kRangeCheckSrc1)
82#define DF_RANGE_CHK_2 (1 << kRangeCheckSrc2)
83#define DF_RANGE_CHK_3 (1 << kRangeCheckSrc3)
84#define DF_FP_A (1 << kFPA)
85#define DF_FP_B (1 << kFPB)
86#define DF_FP_C (1 << kFPC)
87#define DF_CORE_A (1 << kCoreA)
88#define DF_CORE_B (1 << kCoreB)
89#define DF_CORE_C (1 << kCoreC)
90#define DF_REF_A (1 << kRefA)
91#define DF_REF_B (1 << kRefB)
92#define DF_REF_C (1 << kRefC)
93#define DF_UMS (1 << kUsesMethodStar)
94
95#define DF_HAS_USES (DF_UA | DF_UB | DF_UC)
96
97#define DF_HAS_DEFS (DF_DA)
98
99#define DF_HAS_NULL_CHKS (DF_NULL_CHK_0 | \
100 DF_NULL_CHK_1 | \
101 DF_NULL_CHK_2 | \
102 DF_NULL_CHK_OUT0)
103
104#define DF_HAS_RANGE_CHKS (DF_RANGE_CHK_1 | \
105 DF_RANGE_CHK_2 | \
106 DF_RANGE_CHK_3)
107
108#define DF_HAS_NR_CHKS (DF_HAS_NULL_CHKS | \
109 DF_HAS_RANGE_CHKS)
110
111#define DF_A_IS_REG (DF_UA | DF_DA)
112#define DF_B_IS_REG (DF_UB)
113#define DF_C_IS_REG (DF_UC)
114#define DF_IS_GETTER_OR_SETTER (DF_IS_GETTER | DF_IS_SETTER)
115#define DF_USES_FP (DF_FP_A | DF_FP_B | DF_FP_C)
116
buzbee1fd33462013-03-25 13:40:45 -0700117enum OatMethodAttributes {
118 kIsLeaf, // Method is leaf.
119 kHasLoop, // Method contains simple loop.
120};
121
122#define METHOD_IS_LEAF (1 << kIsLeaf)
123#define METHOD_HAS_LOOP (1 << kHasLoop)
124
125// Minimum field size to contain Dalvik v_reg number.
126#define VREG_NUM_WIDTH 16
127
128#define INVALID_SREG (-1)
129#define INVALID_VREG (0xFFFFU)
130#define INVALID_REG (0xFF)
131#define INVALID_OFFSET (0xDEADF00FU)
132
133/* SSA encodings for special registers */
134#define SSA_METHOD_BASEREG (-2)
135/* First compiler temp basereg, grows smaller */
136#define SSA_CTEMP_BASEREG (SSA_METHOD_BASEREG - 1)
137
138#define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck)
139#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly)
140#define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck)
141#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly)
142#define MIR_INLINED (1 << kMIRInlined)
143#define MIR_INLINED_PRED (1 << kMIRInlinedPred)
144#define MIR_CALLEE (1 << kMIRCallee)
145#define MIR_IGNORE_SUSPEND_CHECK (1 << kMIRIgnoreSuspendCheck)
146#define MIR_DUP (1 << kMIRDup)
147
148/*
149 * In general, vreg/sreg describe Dalvik registers that originated with dx. However,
150 * it is useful to have compiler-generated temporary registers and have them treated
151 * in the same manner as dx-generated virtual registers. This struct records the SSA
152 * name of compiler-introduced temporaries.
153 */
154struct CompilerTemp {
155 int s_reg;
156};
157
158// When debug option enabled, records effectiveness of null and range check elimination.
159struct Checkstats {
160 int null_checks;
161 int null_checks_eliminated;
162 int range_checks;
163 int range_checks_eliminated;
164};
165
166// Dataflow attributes of a basic block.
167struct BasicBlockDataFlow {
168 ArenaBitVector* use_v;
169 ArenaBitVector* def_v;
170 ArenaBitVector* live_in_v;
171 ArenaBitVector* phi_v;
172 int* vreg_to_ssa_map;
173 ArenaBitVector* ending_null_check_v;
174};
175
176/*
177 * Normalized use/def for a MIR operation using SSA names rather than vregs. Note that
178 * uses/defs retain the Dalvik convention that long operations operate on a pair of 32-bit
179 * vregs. For example, "ADD_LONG v0, v2, v3" would have 2 defs (v0/v1) and 4 uses (v2/v3, v4/v5).
180 * Following SSA renaming, this is the primary struct used by code generators to locate
181 * operand and result registers. This is a somewhat confusing and unhelpful convention that
182 * we may want to revisit in the future.
183 */
184struct SSARepresentation {
185 int num_uses;
186 int* uses;
187 bool* fp_use;
188 int num_defs;
189 int* defs;
190 bool* fp_def;
191};
192
193/*
194 * The Midlevel Intermediate Representation node, which may be largely considered a
195 * wrapper around a Dalvik byte code.
196 */
197struct MIR {
198 DecodedInstruction dalvikInsn;
199 unsigned int width;
200 unsigned int offset;
201 int m_unit_index; // From which method was this MIR included
202 MIR* prev;
203 MIR* next;
204 SSARepresentation* ssa_rep;
205 int optimization_flags;
206 union {
207 // Establish link between two halves of throwing instructions.
208 MIR* throw_insn;
209 // Saved opcode for NOP'd MIRs
210 Instruction::Code original_opcode;
211 } meta;
212};
213
214struct BasicBlock {
215 int id;
216 int dfs_id;
217 bool visited;
218 bool hidden;
219 bool catch_entry;
220 bool explicit_throw;
221 bool conditional_branch;
222 bool terminated_by_return; // Block ends with a Dalvik return opcode.
223 bool dominates_return; // Is a member of return extended basic block.
224 uint16_t start_offset;
225 uint16_t nesting_depth;
226 BBType block_type;
227 MIR* first_mir_insn;
228 MIR* last_mir_insn;
229 BasicBlock* fall_through;
230 BasicBlock* taken;
231 BasicBlock* i_dom; // Immediate dominator.
232 BasicBlockDataFlow* data_flow_info;
233 GrowableList* predecessors;
234 ArenaBitVector* dominators;
235 ArenaBitVector* i_dominated; // Set nodes being immediately dominated.
236 ArenaBitVector* dom_frontier; // Dominance frontier.
237 struct { // For one-to-many successors like.
238 BlockListType block_list_type; // switch and exception handling.
239 GrowableList blocks;
240 } successor_block_list;
241};
242
243/*
244 * The "blocks" field in "successor_block_list" points to an array of elements with the type
245 * "SuccessorBlockInfo". For catch blocks, key is type index for the exception. For swtich
246 * blocks, key is the case value.
247 */
248struct SuccessorBlockInfo {
249 BasicBlock* block;
250 int key;
251};
252
253/*
254 * Whereas a SSA name describes a definition of a Dalvik vreg, the RegLocation describes
255 * the type of an SSA name (and, can also be used by code generators to record where the
256 * value is located (i.e. - physical register, frame, spill, etc.). For each SSA name (SReg)
257 * there is a RegLocation.
258 * FIXME: The orig_sreg field was added as a workaround for llvm bitcode generation. With
259 * the latest restructuring, we should be able to remove it and rely on s_reg_low throughout.
260 */
261struct RegLocation {
262 RegLocationType location:3;
263 unsigned wide:1;
264 unsigned defined:1; // Do we know the type?
265 unsigned is_const:1; // Constant, value in mir_graph->constant_values[].
266 unsigned fp:1; // Floating point?
267 unsigned core:1; // Non-floating point?
268 unsigned ref:1; // Something GC cares about.
269 unsigned high_word:1; // High word of pair?
270 unsigned home:1; // Does this represent the home location?
271 uint8_t low_reg; // First physical register.
272 uint8_t high_reg; // 2nd physical register (if wide).
273 int32_t s_reg_low; // SSA name for low Dalvik word.
274 int32_t orig_sreg; // TODO: remove after Bitcode gen complete
275 // and consolodate usage w/ s_reg_low.
276};
277
278/*
279 * Collection of information describing an invoke, and the destination of
280 * the subsequent MOVE_RESULT (if applicable). Collected as a unit to enable
281 * more efficient invoke code generation.
282 */
283struct CallInfo {
284 int num_arg_words; // Note: word count, not arg count.
285 RegLocation* args; // One for each word of arguments.
286 RegLocation result; // Eventual target of MOVE_RESULT.
287 int opt_flags;
288 InvokeType type;
289 uint32_t dex_idx;
290 uint32_t index; // Method idx for invokes, type idx for FilledNewArray.
291 uintptr_t direct_code;
292 uintptr_t direct_method;
293 RegLocation target; // Target of following move_result.
294 bool skip_this;
295 bool is_range;
296 int offset; // Dalvik offset.
297};
298
299
300const RegLocation bad_loc = {kLocDalvikFrame, 0, 0, 0, 0, 0, 0, 0, 0,
301 INVALID_REG, INVALID_REG, INVALID_SREG, INVALID_SREG};
buzbee311ca162013-02-28 15:56:43 -0800302
303class MIRGraph {
Ian Rogers71fe2672013-03-19 20:45:02 -0700304 public:
305 MIRGraph(CompilationUnit* cu);
306 ~MIRGraph() {}
buzbee311ca162013-02-28 15:56:43 -0800307
Ian Rogers71fe2672013-03-19 20:45:02 -0700308 /*
309 * Parse dex method and add MIR at current insert point. Returns id (which is
310 * actually the index of the method in the m_units_ array).
311 */
312 void InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags,
313 InvokeType invoke_type, uint32_t class_def_idx,
314 uint32_t method_idx, jobject class_loader, const DexFile& dex_file);
buzbee311ca162013-02-28 15:56:43 -0800315
Ian Rogers71fe2672013-03-19 20:45:02 -0700316 /* Find existing block */
317 BasicBlock* FindBlock(unsigned int code_offset) {
318 return FindBlock(code_offset, false, false, NULL);
319 }
buzbee311ca162013-02-28 15:56:43 -0800320
Ian Rogers71fe2672013-03-19 20:45:02 -0700321 const uint16_t* GetCurrentInsns() const {
322 return current_code_item_->insns_;
323 }
buzbee311ca162013-02-28 15:56:43 -0800324
Ian Rogers71fe2672013-03-19 20:45:02 -0700325 const uint16_t* GetInsns(int m_unit_index) const {
326 return m_units_[m_unit_index]->GetCodeItem()->insns_;
327 }
buzbee311ca162013-02-28 15:56:43 -0800328
Ian Rogers71fe2672013-03-19 20:45:02 -0700329 int GetNumBlocks() const {
330 return num_blocks_;
331 }
buzbee311ca162013-02-28 15:56:43 -0800332
Ian Rogers71fe2672013-03-19 20:45:02 -0700333 ArenaBitVector* GetTryBlockAddr() const {
334 return try_block_addr_;
335 }
buzbee311ca162013-02-28 15:56:43 -0800336
Ian Rogers71fe2672013-03-19 20:45:02 -0700337 BasicBlock* GetEntryBlock() const {
338 return entry_block_;
339 }
buzbee311ca162013-02-28 15:56:43 -0800340
Ian Rogers71fe2672013-03-19 20:45:02 -0700341 BasicBlock* GetExitBlock() const {
342 return exit_block_;
343 }
buzbee311ca162013-02-28 15:56:43 -0800344
Ian Rogers71fe2672013-03-19 20:45:02 -0700345 GrowableListIterator GetBasicBlockIterator() {
346 GrowableListIterator iterator;
347 GrowableListIteratorInit(&block_list_, &iterator);
348 return iterator;
349 }
buzbee311ca162013-02-28 15:56:43 -0800350
Ian Rogers71fe2672013-03-19 20:45:02 -0700351 BasicBlock* GetBasicBlock(int block_id) const {
352 return reinterpret_cast<BasicBlock*>(GrowableListGetElement(&block_list_, block_id));
353 }
buzbee311ca162013-02-28 15:56:43 -0800354
Ian Rogers71fe2672013-03-19 20:45:02 -0700355 size_t GetBasicBlockListCount() const {
356 return block_list_.num_used;
357 }
buzbee311ca162013-02-28 15:56:43 -0800358
Ian Rogers71fe2672013-03-19 20:45:02 -0700359 GrowableList* GetBlockList() {
360 return &block_list_;
361 }
buzbee311ca162013-02-28 15:56:43 -0800362
Ian Rogers71fe2672013-03-19 20:45:02 -0700363 GrowableList* GetDfsOrder() {
364 return &dfs_order_;
365 }
buzbee311ca162013-02-28 15:56:43 -0800366
Ian Rogers71fe2672013-03-19 20:45:02 -0700367 GrowableList* GetDfsPostOrder() {
368 return &dfs_post_order_;
369 }
buzbee311ca162013-02-28 15:56:43 -0800370
Ian Rogers71fe2672013-03-19 20:45:02 -0700371 GrowableList* GetDomPostOrder() {
372 return &dom_post_order_traversal_;
373 }
buzbee311ca162013-02-28 15:56:43 -0800374
Ian Rogers71fe2672013-03-19 20:45:02 -0700375 GrowableList* GetSSASubscripts() {
376 return ssa_subscripts_;
377 }
buzbee311ca162013-02-28 15:56:43 -0800378
Ian Rogers71fe2672013-03-19 20:45:02 -0700379 int GetDefCount() const {
380 return def_count_;
381 }
buzbee311ca162013-02-28 15:56:43 -0800382
Ian Rogers71fe2672013-03-19 20:45:02 -0700383 void EnableOpcodeCounting() {
384 opcode_count_ = static_cast<int*>(NewMem(cu_, kNumPackedOpcodes * sizeof(int), true,
385 kAllocMisc));
386 }
buzbee311ca162013-02-28 15:56:43 -0800387
Ian Rogers71fe2672013-03-19 20:45:02 -0700388 void ShowOpcodeStats();
buzbee311ca162013-02-28 15:56:43 -0800389
Ian Rogers71fe2672013-03-19 20:45:02 -0700390 DexCompilationUnit* GetCurrentDexCompilationUnit() const {
391 return m_units_[current_method_];
392 }
buzbee311ca162013-02-28 15:56:43 -0800393
Ian Rogers71fe2672013-03-19 20:45:02 -0700394 void DumpCFG(const char* dir_prefix, bool all_blocks);
buzbee311ca162013-02-28 15:56:43 -0800395
Ian Rogers71fe2672013-03-19 20:45:02 -0700396 void BuildRegLocations();
buzbee311ca162013-02-28 15:56:43 -0800397
Ian Rogers71fe2672013-03-19 20:45:02 -0700398 void DumpRegLocTable(RegLocation* table, int count);
buzbee311ca162013-02-28 15:56:43 -0800399
Ian Rogers71fe2672013-03-19 20:45:02 -0700400 void BasicBlockOptimization();
buzbee311ca162013-02-28 15:56:43 -0800401
Ian Rogers71fe2672013-03-19 20:45:02 -0700402 bool IsConst(int32_t s_reg) const {
403 return (IsBitSet(is_constant_v_, s_reg));
404 }
buzbee311ca162013-02-28 15:56:43 -0800405
Ian Rogers71fe2672013-03-19 20:45:02 -0700406 bool IsConst(RegLocation loc) const {
407 return (IsConst(loc.orig_sreg));
408 }
buzbee311ca162013-02-28 15:56:43 -0800409
Ian Rogers71fe2672013-03-19 20:45:02 -0700410 int32_t ConstantValue(RegLocation loc) const {
411 DCHECK(IsConst(loc));
412 return constant_values_[loc.orig_sreg];
413 }
buzbee311ca162013-02-28 15:56:43 -0800414
Ian Rogers71fe2672013-03-19 20:45:02 -0700415 int32_t ConstantValue(int32_t s_reg) const {
416 DCHECK(IsConst(s_reg));
417 return constant_values_[s_reg];
418 }
buzbee311ca162013-02-28 15:56:43 -0800419
Ian Rogers71fe2672013-03-19 20:45:02 -0700420 int64_t ConstantValueWide(RegLocation loc) const {
421 DCHECK(IsConst(loc));
422 return (static_cast<int64_t>(constant_values_[loc.orig_sreg + 1]) << 32) |
423 Low32Bits(static_cast<int64_t>(constant_values_[loc.orig_sreg]));
424 }
buzbee311ca162013-02-28 15:56:43 -0800425
Ian Rogers71fe2672013-03-19 20:45:02 -0700426 bool IsConstantNullRef(RegLocation loc) const {
427 return loc.ref && loc.is_const && (ConstantValue(loc) == 0);
428 }
buzbee311ca162013-02-28 15:56:43 -0800429
Ian Rogers71fe2672013-03-19 20:45:02 -0700430 int GetNumSSARegs() const {
431 return num_ssa_regs_;
432 }
buzbee311ca162013-02-28 15:56:43 -0800433
Ian Rogers71fe2672013-03-19 20:45:02 -0700434 void SetNumSSARegs(int new_num) {
435 num_ssa_regs_ = new_num;
436 }
buzbee311ca162013-02-28 15:56:43 -0800437
Ian Rogers71fe2672013-03-19 20:45:02 -0700438 int GetNumReachableBlocks() const {
439 return num_reachable_blocks_;
440 }
buzbee311ca162013-02-28 15:56:43 -0800441
Ian Rogers71fe2672013-03-19 20:45:02 -0700442 int GetUseCount(int vreg) const {
443 return GrowableListGetElement(&use_counts_, vreg);
444 }
buzbee311ca162013-02-28 15:56:43 -0800445
Ian Rogers71fe2672013-03-19 20:45:02 -0700446 int GetRawUseCount(int vreg) const {
447 return GrowableListGetElement(&raw_use_counts_, vreg);
448 }
buzbee311ca162013-02-28 15:56:43 -0800449
Ian Rogers71fe2672013-03-19 20:45:02 -0700450 int GetSSASubscript(int ssa_reg) const {
451 return GrowableListGetElement(ssa_subscripts_, ssa_reg);
452 }
buzbee311ca162013-02-28 15:56:43 -0800453
Ian Rogers71fe2672013-03-19 20:45:02 -0700454 const char* GetSSAString(int ssa_reg) const {
455 return GET_ELEM_N(ssa_strings_, char*, ssa_reg);
456 }
buzbee311ca162013-02-28 15:56:43 -0800457
buzbee1fd33462013-03-25 13:40:45 -0700458 RegLocation GetRawSrc(MIR* mir, int num)
459 {
460 DCHECK(num < mir->ssa_rep->num_uses);
461 RegLocation res = reg_location_[mir->ssa_rep->uses[num]];
462 return res;
463 }
464
465 RegLocation GetRawDest(MIR* mir)
466 {
467 DCHECK_GT(mir->ssa_rep->num_defs, 0);
468 RegLocation res = reg_location_[mir->ssa_rep->defs[0]];
469 return res;
470 }
471
472 RegLocation GetDest(MIR* mir)
473 {
474 RegLocation res = GetRawDest(mir);
475 DCHECK(!res.wide);
476 return res;
477 }
478
479 RegLocation GetSrc(MIR* mir, int num)
480 {
481 RegLocation res = GetRawSrc(mir, num);
482 DCHECK(!res.wide);
483 return res;
484 }
485
486 RegLocation GetDestWide(MIR* mir)
487 {
488 RegLocation res = GetRawDest(mir);
489 DCHECK(res.wide);
490 return res;
491 }
492
493 RegLocation GetSrcWide(MIR* mir, int low)
494 {
495 RegLocation res = GetRawSrc(mir, low);
496 DCHECK(res.wide);
497 return res;
498 }
499
500 RegLocation GetBadLoc() {
501 return bad_loc;
502 }
503
504 int GetMethodSReg() {
505 return method_sreg_;
506 }
507
508 bool MethodIsLeaf() {
509 return attributes_ & METHOD_IS_LEAF;
510 }
511
512 RegLocation GetRegLocation(int index) {
513 DCHECK((index >= 0) && (index > num_ssa_regs_));
514 return reg_location_[index];
515 }
516
517 RegLocation GetMethodLoc() {
518 return reg_location_[method_sreg_];
519 }
520
Ian Rogers71fe2672013-03-19 20:45:02 -0700521 void BasicBlockCombine();
522 void CodeLayout();
523 void DumpCheckStats();
524 void PropagateConstants();
525 MIR* FindMoveResult(BasicBlock* bb, MIR* mir);
526 int SRegToVReg(int ssa_reg) const;
527 void VerifyDataflow();
528 void MethodUseCount();
529 void SSATransformation();
530 void CheckForDominanceFrontier(BasicBlock* dom_bb, const BasicBlock* succ_bb);
531 void NullCheckElimination();
buzbee1fd33462013-03-25 13:40:45 -0700532 bool SetFp(int index, bool is_fp);
533 bool SetCore(int index, bool is_core);
534 bool SetRef(int index, bool is_ref);
535 bool SetWide(int index, bool is_wide);
536 bool SetHigh(int index, bool is_high);
537 void AppendMIR(BasicBlock* bb, MIR* mir);
538 void PrependMIR(BasicBlock* bb, MIR* mir);
539 void InsertMIRAfter(BasicBlock* bb, MIR* current_mir, MIR* new_mir);
540 char* GetDalvikDisassembly(const MIR* mir);
541
542 void ReplaceSpecialChars(std::string& str);
543 std::string GetSSAName(int ssa_reg);
544 std::string GetSSANameWithConst(int ssa_reg, bool singles_only);
545 void GetBlockName(BasicBlock* bb, char* name);
546 const char* GetShortyFromTargetIdx(int);
547 void DumpMIRGraph();
548 CallInfo* NewMemCallInfo(BasicBlock* bb, MIR* mir, InvokeType type, bool is_range);
buzbee311ca162013-02-28 15:56:43 -0800549
Ian Rogers71fe2672013-03-19 20:45:02 -0700550 /*
551 * IsDebugBuild sanity check: keep track of the Dex PCs for catch entries so that later on
552 * we can verify that all catch entries have native PC entries.
553 */
554 std::set<uint32_t> catches_;
buzbee311ca162013-02-28 15:56:43 -0800555
buzbee1fd33462013-03-25 13:40:45 -0700556 // TODO: make these private.
557 RegLocation* reg_location_; // Map SSA names to location.
558 GrowableList compiler_temps_;
559 SafeMap<unsigned int, unsigned int> block_id_map_; // Block collapse lookup cache.
560
561 static const int oat_data_flow_attributes_[kMirOpLast];
562 static const char* extended_mir_op_names_[kMirOpLast - kMirOpFirst];
563
Ian Rogers71fe2672013-03-19 20:45:02 -0700564 private:
buzbee311ca162013-02-28 15:56:43 -0800565
Ian Rogers71fe2672013-03-19 20:45:02 -0700566 int FindCommonParent(int block1, int block2);
567 void ComputeSuccLineIn(ArenaBitVector* dest, const ArenaBitVector* src1,
568 const ArenaBitVector* src2);
569 void HandleLiveInUse(ArenaBitVector* use_v, ArenaBitVector* def_v,
570 ArenaBitVector* live_in_v, int dalvik_reg_id);
571 void HandleDef(ArenaBitVector* def_v, int dalvik_reg_id);
572 void CompilerInitializeSSAConversion();
573 bool DoSSAConversion(BasicBlock* bb);
574 bool InvokeUsesMethodStar(MIR* mir);
575 int ParseInsn(const uint16_t* code_ptr, DecodedInstruction* decoded_instruction);
576 bool ContentIsInsn(const uint16_t* code_ptr);
577 BasicBlock* SplitBlock(unsigned int code_offset, BasicBlock* orig_block,
buzbee311ca162013-02-28 15:56:43 -0800578 BasicBlock** immed_pred_block_p);
Ian Rogers71fe2672013-03-19 20:45:02 -0700579 BasicBlock* FindBlock(unsigned int code_offset, bool split, bool create,
580 BasicBlock** immed_pred_block_p);
581 void ProcessTryCatchBlocks();
582 BasicBlock* ProcessCanBranch(BasicBlock* cur_block, MIR* insn, int cur_offset, int width,
583 int flags, const uint16_t* code_ptr, const uint16_t* code_end);
584 void ProcessCanSwitch(BasicBlock* cur_block, MIR* insn, int cur_offset, int width, int flags);
585 BasicBlock* ProcessCanThrow(BasicBlock* cur_block, MIR* insn, int cur_offset, int width,
586 int flags, ArenaBitVector* try_block_addr, const uint16_t* code_ptr,
587 const uint16_t* code_end);
588 int AddNewSReg(int v_reg);
589 void HandleSSAUse(int* uses, int dalvik_reg, int reg_index);
590 void HandleSSADef(int* defs, int dalvik_reg, int reg_index);
591 void DataFlowSSAFormat35C(MIR* mir);
592 void DataFlowSSAFormat3RC(MIR* mir);
593 bool FindLocalLiveIn(BasicBlock* bb);
594 bool ClearVisitedFlag(struct BasicBlock* bb);
595 bool CountUses(struct BasicBlock* bb);
596 bool InferTypeAndSize(BasicBlock* bb);
597 bool VerifyPredInfo(BasicBlock* bb);
598 BasicBlock* NeedsVisit(BasicBlock* bb);
599 BasicBlock* NextUnvisitedSuccessor(BasicBlock* bb);
600 void MarkPreOrder(BasicBlock* bb);
601 void RecordDFSOrders(BasicBlock* bb);
602 void ComputeDFSOrders();
603 void ComputeDefBlockMatrix();
604 void ComputeDomPostOrderTraversal(BasicBlock* bb);
605 void ComputeDominators();
606 void InsertPhiNodes();
607 void DoDFSPreOrderSSARename(BasicBlock* block);
608 void SetConstant(int32_t ssa_reg, int value);
609 void SetConstantWide(int ssa_reg, int64_t value);
610 int GetSSAUseCount(int s_reg);
611 bool BasicBlockOpt(BasicBlock* bb);
612 bool EliminateNullChecks(BasicBlock* bb);
613 bool NullCheckEliminationInit(BasicBlock* bb);
614 bool BuildExtendedBBList(struct BasicBlock* bb);
615 bool FillDefBlockMatrix(BasicBlock* bb);
616 bool InitializeDominationInfo(BasicBlock* bb);
617 bool ComputeblockIDom(BasicBlock* bb);
618 bool ComputeBlockDominators(BasicBlock* bb);
619 bool SetDominators(BasicBlock* bb);
620 bool ComputeBlockLiveIns(BasicBlock* bb);
621 bool InsertPhiNodeOperands(BasicBlock* bb);
622 bool ComputeDominanceFrontier(BasicBlock* bb);
623 bool DoConstantPropogation(BasicBlock* bb);
624 bool CountChecks(BasicBlock* bb);
625 bool CombineBlocks(BasicBlock* bb);
buzbee311ca162013-02-28 15:56:43 -0800626
Ian Rogers71fe2672013-03-19 20:45:02 -0700627 CompilationUnit* const cu_;
628 GrowableList* ssa_base_vregs_;
629 GrowableList* ssa_subscripts_;
630 GrowableList* ssa_strings_;
631 // Map original Dalvik virtual reg i to the current SSA name.
632 int* vreg_to_ssa_map_; // length == method->registers_size
633 int* ssa_last_defs_; // length == method->registers_size
634 ArenaBitVector* is_constant_v_; // length == num_ssa_reg
635 int* constant_values_; // length == num_ssa_reg
636 // Use counts of ssa names.
637 GrowableList use_counts_; // Weighted by nesting depth
638 GrowableList raw_use_counts_; // Not weighted
639 int num_reachable_blocks_;
640 GrowableList dfs_order_;
641 GrowableList dfs_post_order_;
642 GrowableList dom_post_order_traversal_;
643 int* i_dom_list_;
644 ArenaBitVector** def_block_matrix_; // num_dalvik_register x num_blocks.
645 ArenaBitVector* temp_block_v_;
646 ArenaBitVector* temp_dalvik_register_v_;
647 ArenaBitVector* temp_ssa_register_v_; // num_ssa_regs.
648 static const int kInvalidEntry = -1;
649 GrowableList block_list_;
650 ArenaBitVector* try_block_addr_;
651 BasicBlock* entry_block_;
652 BasicBlock* exit_block_;
653 BasicBlock* cur_block_;
654 int num_blocks_;
655 const DexFile::CodeItem* current_code_item_;
656 SafeMap<unsigned int, BasicBlock*> block_map_; // FindBlock lookup cache.
657 std::vector<DexCompilationUnit*> m_units_; // List of methods included in this graph
658 typedef std::pair<int, int> MIRLocation; // Insert point, (m_unit_ index, offset)
659 std::vector<MIRLocation> method_stack_; // Include stack
660 int current_method_;
661 int current_offset_;
662 int def_count_; // Used to estimate size of ssa name storage.
663 int* opcode_count_; // Dex opcode coverage stats.
664 int num_ssa_regs_; // Number of names following SSA transformation.
665 std::vector<BasicBlock*> extended_basic_blocks_; // Heads of block "traces".
buzbee1fd33462013-03-25 13:40:45 -0700666 int method_sreg_;
667 unsigned int attributes_;
668 Checkstats* checkstats_;
buzbee311ca162013-02-28 15:56:43 -0800669};
670
671} // namespace art
672
673#endif // ART_SRC_COMPILER_DEX_MIRGRAPH_H_