Dataflow.cpp revision ab35b50311951feea3782151dd5422ee944685c2
1/*
2 * Copyright (C) 2009 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 "Dataflow.h"
19#include "Loop.h"
20#include "libdex/DexOpcodes.h"
21
22/*
23 * Main table containing data flow attributes for each bytecode. The
24 * first kNumPackedOpcodes entries are for Dalvik bytecode
25 * instructions, where extended opcode at the MIR level are appended
26 * afterwards.
27 *
28 * TODO - many optimization flags are incomplete - they will only limit the
29 * scope of optimizations but will not cause mis-optimizations.
30 */
31int dvmCompilerDataFlowAttributes[kMirOpLast] = {
32    // 00 OP_NOP
33    DF_NOP,
34
35    // 01 OP_MOVE vA, vB
36    DF_DA | DF_UB | DF_IS_MOVE,
37
38    // 02 OP_MOVE_FROM16 vAA, vBBBB
39    DF_DA | DF_UB | DF_IS_MOVE,
40
41    // 03 OP_MOVE_16 vAAAA, vBBBB
42    DF_DA | DF_UB | DF_IS_MOVE,
43
44    // 04 OP_MOVE_WIDE vA, vB
45    DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
46
47    // 05 OP_MOVE_WIDE_FROM16 vAA, vBBBB
48    DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
49
50    // 06 OP_MOVE_WIDE_16 vAAAA, vBBBB
51    DF_DA_WIDE | DF_UB_WIDE | DF_IS_MOVE,
52
53    // 07 OP_MOVE_OBJECT vA, vB
54    DF_DA | DF_UB | DF_IS_MOVE,
55
56    // 08 OP_MOVE_OBJECT_FROM16 vAA, vBBBB
57    DF_DA | DF_UB | DF_IS_MOVE,
58
59    // 09 OP_MOVE_OBJECT_16 vAAAA, vBBBB
60    DF_DA | DF_UB | DF_IS_MOVE,
61
62    // 0A OP_MOVE_RESULT vAA
63    DF_DA,
64
65    // 0B OP_MOVE_RESULT_WIDE vAA
66    DF_DA_WIDE,
67
68    // 0C OP_MOVE_RESULT_OBJECT vAA
69    DF_DA,
70
71    // 0D OP_MOVE_EXCEPTION vAA
72    DF_DA,
73
74    // 0E OP_RETURN_VOID
75    DF_NOP,
76
77    // 0F OP_RETURN vAA
78    DF_UA,
79
80    // 10 OP_RETURN_WIDE vAA
81    DF_UA_WIDE,
82
83    // 11 OP_RETURN_OBJECT vAA
84    DF_UA,
85
86    // 12 OP_CONST_4 vA, #+B
87    DF_DA | DF_SETS_CONST,
88
89    // 13 OP_CONST_16 vAA, #+BBBB
90    DF_DA | DF_SETS_CONST,
91
92    // 14 OP_CONST vAA, #+BBBBBBBB
93    DF_DA | DF_SETS_CONST,
94
95    // 15 OP_CONST_HIGH16 VAA, #+BBBB0000
96    DF_DA | DF_SETS_CONST,
97
98    // 16 OP_CONST_WIDE_16 vAA, #+BBBB
99    DF_DA_WIDE | DF_SETS_CONST,
100
101    // 17 OP_CONST_WIDE_32 vAA, #+BBBBBBBB
102    DF_DA_WIDE | DF_SETS_CONST,
103
104    // 18 OP_CONST_WIDE vAA, #+BBBBBBBBBBBBBBBB
105    DF_DA_WIDE | DF_SETS_CONST,
106
107    // 19 OP_CONST_WIDE_HIGH16 vAA, #+BBBB000000000000
108    DF_DA_WIDE | DF_SETS_CONST,
109
110    // 1A OP_CONST_STRING vAA, string@BBBB
111    DF_DA,
112
113    // 1B OP_CONST_STRING_JUMBO vAA, string@BBBBBBBB
114    DF_DA,
115
116    // 1C OP_CONST_CLASS vAA, type@BBBB
117    DF_DA,
118
119    // 1D OP_MONITOR_ENTER vAA
120    DF_UA,
121
122    // 1E OP_MONITOR_EXIT vAA
123    DF_UA,
124
125    // 1F OP_CHECK_CAST vAA, type@BBBB
126    DF_UA,
127
128    // 20 OP_INSTANCE_OF vA, vB, type@CCCC
129    DF_DA | DF_UB,
130
131    // 21 OP_ARRAY_LENGTH vA, vB
132    DF_DA | DF_UB,
133
134    // 22 OP_NEW_INSTANCE vAA, type@BBBB
135    DF_DA,
136
137    // 23 OP_NEW_ARRAY vA, vB, type@CCCC
138    DF_DA | DF_UB,
139
140    // 24 OP_FILLED_NEW_ARRAY {vD, vE, vF, vG, vA}
141    DF_FORMAT_35C,
142
143    // 25 OP_FILLED_NEW_ARRAY_RANGE {vCCCC .. vNNNN}, type@BBBB
144    DF_FORMAT_3RC,
145
146    // 26 OP_FILL_ARRAY_DATA vAA, +BBBBBBBB
147    DF_UA,
148
149    // 27 OP_THROW vAA
150    DF_UA,
151
152    // 28 OP_GOTO
153    DF_NOP,
154
155    // 29 OP_GOTO_16
156    DF_NOP,
157
158    // 2A OP_GOTO_32
159    DF_NOP,
160
161    // 2B OP_PACKED_SWITCH vAA, +BBBBBBBB
162    DF_UA,
163
164    // 2C OP_SPARSE_SWITCH vAA, +BBBBBBBB
165    DF_UA,
166
167    // 2D OP_CMPL_FLOAT vAA, vBB, vCC
168    DF_DA | DF_UB | DF_UC | DF_FP_B | DF_FP_C,
169
170    // 2E OP_CMPG_FLOAT vAA, vBB, vCC
171    DF_DA | DF_UB | DF_UC | DF_FP_B | DF_FP_C,
172
173    // 2F OP_CMPL_DOUBLE vAA, vBB, vCC
174    DF_DA | DF_UB_WIDE | DF_UC_WIDE | DF_FP_B | DF_FP_C,
175
176    // 30 OP_CMPG_DOUBLE vAA, vBB, vCC
177    DF_DA | DF_UB_WIDE | DF_UC_WIDE | DF_FP_B | DF_FP_C,
178
179    // 31 OP_CMP_LONG vAA, vBB, vCC
180    DF_DA | DF_UB_WIDE | DF_UC_WIDE,
181
182    // 32 OP_IF_EQ vA, vB, +CCCC
183    DF_UA | DF_UB,
184
185    // 33 OP_IF_NE vA, vB, +CCCC
186    DF_UA | DF_UB,
187
188    // 34 OP_IF_LT vA, vB, +CCCC
189    DF_UA | DF_UB,
190
191    // 35 OP_IF_GE vA, vB, +CCCC
192    DF_UA | DF_UB,
193
194    // 36 OP_IF_GT vA, vB, +CCCC
195    DF_UA | DF_UB,
196
197    // 37 OP_IF_LE vA, vB, +CCCC
198    DF_UA | DF_UB,
199
200
201    // 38 OP_IF_EQZ vAA, +BBBB
202    DF_UA,
203
204    // 39 OP_IF_NEZ vAA, +BBBB
205    DF_UA,
206
207    // 3A OP_IF_LTZ vAA, +BBBB
208    DF_UA,
209
210    // 3B OP_IF_GEZ vAA, +BBBB
211    DF_UA,
212
213    // 3C OP_IF_GTZ vAA, +BBBB
214    DF_UA,
215
216    // 3D OP_IF_LEZ vAA, +BBBB
217    DF_UA,
218
219    // 3E OP_UNUSED_3E
220    DF_NOP,
221
222    // 3F OP_UNUSED_3F
223    DF_NOP,
224
225    // 40 OP_UNUSED_40
226    DF_NOP,
227
228    // 41 OP_UNUSED_41
229    DF_NOP,
230
231    // 42 OP_UNUSED_42
232    DF_NOP,
233
234    // 43 OP_UNUSED_43
235    DF_NOP,
236
237    // 44 OP_AGET vAA, vBB, vCC
238    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0 | DF_IS_GETTER,
239
240    // 45 OP_AGET_WIDE vAA, vBB, vCC
241    DF_DA_WIDE | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0 | DF_IS_GETTER,
242
243    // 46 OP_AGET_OBJECT vAA, vBB, vCC
244    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0 | DF_IS_GETTER,
245
246    // 47 OP_AGET_BOOLEAN vAA, vBB, vCC
247    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0 | DF_IS_GETTER,
248
249    // 48 OP_AGET_BYTE vAA, vBB, vCC
250    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0 | DF_IS_GETTER,
251
252    // 49 OP_AGET_CHAR vAA, vBB, vCC
253    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0 | DF_IS_GETTER,
254
255    // 4A OP_AGET_SHORT vAA, vBB, vCC
256    DF_DA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_0 | DF_IS_GETTER,
257
258    // 4B OP_APUT vAA, vBB, vCC
259    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1 | DF_IS_SETTER,
260
261    // 4C OP_APUT_WIDE vAA, vBB, vCC
262    DF_UA_WIDE | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_2 | DF_IS_SETTER,
263
264    // 4D OP_APUT_OBJECT vAA, vBB, vCC
265    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1 | DF_IS_SETTER,
266
267    // 4E OP_APUT_BOOLEAN vAA, vBB, vCC
268    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1 | DF_IS_SETTER,
269
270    // 4F OP_APUT_BYTE vAA, vBB, vCC
271    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1 | DF_IS_SETTER,
272
273    // 50 OP_APUT_CHAR vAA, vBB, vCC
274    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1 | DF_IS_SETTER,
275
276    // 51 OP_APUT_SHORT vAA, vBB, vCC
277    DF_UA | DF_UB | DF_UC | DF_NULL_N_RANGE_CHECK_1 | DF_IS_SETTER,
278
279    // 52 OP_IGET vA, vB, field@CCCC
280    DF_DA | DF_UB | DF_IS_GETTER,
281
282    // 53 OP_IGET_WIDE vA, vB, field@CCCC
283    DF_DA_WIDE | DF_UB | DF_IS_GETTER,
284
285    // 54 OP_IGET_OBJECT vA, vB, field@CCCC
286    DF_DA | DF_UB | DF_IS_GETTER,
287
288    // 55 OP_IGET_BOOLEAN vA, vB, field@CCCC
289    DF_DA | DF_UB | DF_IS_GETTER,
290
291    // 56 OP_IGET_BYTE vA, vB, field@CCCC
292    DF_DA | DF_UB | DF_IS_GETTER,
293
294    // 57 OP_IGET_CHAR vA, vB, field@CCCC
295    DF_DA | DF_UB | DF_IS_GETTER,
296
297    // 58 OP_IGET_SHORT vA, vB, field@CCCC
298    DF_DA | DF_UB | DF_IS_GETTER,
299
300    // 59 OP_IPUT vA, vB, field@CCCC
301    DF_UA | DF_UB | DF_IS_SETTER,
302
303    // 5A OP_IPUT_WIDE vA, vB, field@CCCC
304    DF_UA_WIDE | DF_UB | DF_IS_SETTER,
305
306    // 5B OP_IPUT_OBJECT vA, vB, field@CCCC
307    DF_UA | DF_UB | DF_IS_SETTER,
308
309    // 5C OP_IPUT_BOOLEAN vA, vB, field@CCCC
310    DF_UA | DF_UB | DF_IS_SETTER,
311
312    // 5D OP_IPUT_BYTE vA, vB, field@CCCC
313    DF_UA | DF_UB | DF_IS_SETTER,
314
315    // 5E OP_IPUT_CHAR vA, vB, field@CCCC
316    DF_UA | DF_UB | DF_IS_SETTER,
317
318    // 5F OP_IPUT_SHORT vA, vB, field@CCCC
319    DF_UA | DF_UB | DF_IS_SETTER,
320
321    // 60 OP_SGET vAA, field@BBBB
322    DF_DA | DF_IS_GETTER,
323
324    // 61 OP_SGET_WIDE vAA, field@BBBB
325    DF_DA_WIDE | DF_IS_GETTER,
326
327    // 62 OP_SGET_OBJECT vAA, field@BBBB
328    DF_DA | DF_IS_GETTER,
329
330    // 63 OP_SGET_BOOLEAN vAA, field@BBBB
331    DF_DA | DF_IS_GETTER,
332
333    // 64 OP_SGET_BYTE vAA, field@BBBB
334    DF_DA | DF_IS_GETTER,
335
336    // 65 OP_SGET_CHAR vAA, field@BBBB
337    DF_DA | DF_IS_GETTER,
338
339    // 66 OP_SGET_SHORT vAA, field@BBBB
340    DF_DA | DF_IS_GETTER,
341
342    // 67 OP_SPUT vAA, field@BBBB
343    DF_UA | DF_IS_SETTER,
344
345    // 68 OP_SPUT_WIDE vAA, field@BBBB
346    DF_UA_WIDE | DF_IS_SETTER,
347
348    // 69 OP_SPUT_OBJECT vAA, field@BBBB
349    DF_UA | DF_IS_SETTER,
350
351    // 6A OP_SPUT_BOOLEAN vAA, field@BBBB
352    DF_UA | DF_IS_SETTER,
353
354    // 6B OP_SPUT_BYTE vAA, field@BBBB
355    DF_UA | DF_IS_SETTER,
356
357    // 6C OP_SPUT_CHAR vAA, field@BBBB
358    DF_UA | DF_IS_SETTER,
359
360    // 6D OP_SPUT_SHORT vAA, field@BBBB
361    DF_UA | DF_IS_SETTER,
362
363    // 6E OP_INVOKE_VIRTUAL {vD, vE, vF, vG, vA}
364    DF_FORMAT_35C,
365
366    // 6F OP_INVOKE_SUPER {vD, vE, vF, vG, vA}
367    DF_FORMAT_35C,
368
369    // 70 OP_INVOKE_DIRECT {vD, vE, vF, vG, vA}
370    DF_FORMAT_35C,
371
372    // 71 OP_INVOKE_STATIC {vD, vE, vF, vG, vA}
373    DF_FORMAT_35C,
374
375    // 72 OP_INVOKE_INTERFACE {vD, vE, vF, vG, vA}
376    DF_FORMAT_35C,
377
378    // 73 OP_UNUSED_73
379    DF_NOP,
380
381    // 74 OP_INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN}
382    DF_FORMAT_3RC,
383
384    // 75 OP_INVOKE_SUPER_RANGE {vCCCC .. vNNNN}
385    DF_FORMAT_3RC,
386
387    // 76 OP_INVOKE_DIRECT_RANGE {vCCCC .. vNNNN}
388    DF_FORMAT_3RC,
389
390    // 77 OP_INVOKE_STATIC_RANGE {vCCCC .. vNNNN}
391    DF_FORMAT_3RC,
392
393    // 78 OP_INVOKE_INTERFACE_RANGE {vCCCC .. vNNNN}
394    DF_FORMAT_3RC,
395
396    // 79 OP_UNUSED_79
397    DF_NOP,
398
399    // 7A OP_UNUSED_7A
400    DF_NOP,
401
402    // 7B OP_NEG_INT vA, vB
403    DF_DA | DF_UB,
404
405    // 7C OP_NOT_INT vA, vB
406    DF_DA | DF_UB,
407
408    // 7D OP_NEG_LONG vA, vB
409    DF_DA_WIDE | DF_UB_WIDE,
410
411    // 7E OP_NOT_LONG vA, vB
412    DF_DA_WIDE | DF_UB_WIDE,
413
414    // 7F OP_NEG_FLOAT vA, vB
415    DF_DA | DF_UB | DF_FP_A | DF_FP_B,
416
417    // 80 OP_NEG_DOUBLE vA, vB
418    DF_DA_WIDE | DF_UB_WIDE | DF_FP_A | DF_FP_B,
419
420    // 81 OP_INT_TO_LONG vA, vB
421    DF_DA_WIDE | DF_UB,
422
423    // 82 OP_INT_TO_FLOAT vA, vB
424    DF_DA | DF_UB | DF_FP_A,
425
426    // 83 OP_INT_TO_DOUBLE vA, vB
427    DF_DA_WIDE | DF_UB | DF_FP_A,
428
429    // 84 OP_LONG_TO_INT vA, vB
430    DF_DA | DF_UB_WIDE,
431
432    // 85 OP_LONG_TO_FLOAT vA, vB
433    DF_DA | DF_UB_WIDE | DF_FP_A,
434
435    // 86 OP_LONG_TO_DOUBLE vA, vB
436    DF_DA_WIDE | DF_UB_WIDE | DF_FP_A,
437
438    // 87 OP_FLOAT_TO_INT vA, vB
439    DF_DA | DF_UB | DF_FP_B,
440
441    // 88 OP_FLOAT_TO_LONG vA, vB
442    DF_DA_WIDE | DF_UB | DF_FP_B,
443
444    // 89 OP_FLOAT_TO_DOUBLE vA, vB
445    DF_DA_WIDE | DF_UB | DF_FP_A | DF_FP_B,
446
447    // 8A OP_DOUBLE_TO_INT vA, vB
448    DF_DA | DF_UB_WIDE | DF_FP_B,
449
450    // 8B OP_DOUBLE_TO_LONG vA, vB
451    DF_DA_WIDE | DF_UB_WIDE | DF_FP_B,
452
453    // 8C OP_DOUBLE_TO_FLOAT vA, vB
454    DF_DA | DF_UB_WIDE | DF_FP_A | DF_FP_B,
455
456    // 8D OP_INT_TO_BYTE vA, vB
457    DF_DA | DF_UB,
458
459    // 8E OP_INT_TO_CHAR vA, vB
460    DF_DA | DF_UB,
461
462    // 8F OP_INT_TO_SHORT vA, vB
463    DF_DA | DF_UB,
464
465    // 90 OP_ADD_INT vAA, vBB, vCC
466    DF_DA | DF_UB | DF_UC | DF_IS_LINEAR,
467
468    // 91 OP_SUB_INT vAA, vBB, vCC
469    DF_DA | DF_UB | DF_UC | DF_IS_LINEAR,
470
471    // 92 OP_MUL_INT vAA, vBB, vCC
472    DF_DA | DF_UB | DF_UC,
473
474    // 93 OP_DIV_INT vAA, vBB, vCC
475    DF_DA | DF_UB | DF_UC,
476
477    // 94 OP_REM_INT vAA, vBB, vCC
478    DF_DA | DF_UB | DF_UC,
479
480    // 95 OP_AND_INT vAA, vBB, vCC
481    DF_DA | DF_UB | DF_UC,
482
483    // 96 OP_OR_INT vAA, vBB, vCC
484    DF_DA | DF_UB | DF_UC,
485
486    // 97 OP_XOR_INT vAA, vBB, vCC
487    DF_DA | DF_UB | DF_UC,
488
489    // 98 OP_SHL_INT vAA, vBB, vCC
490    DF_DA | DF_UB | DF_UC,
491
492    // 99 OP_SHR_INT vAA, vBB, vCC
493    DF_DA | DF_UB | DF_UC,
494
495    // 9A OP_USHR_INT vAA, vBB, vCC
496    DF_DA | DF_UB | DF_UC,
497
498    // 9B OP_ADD_LONG vAA, vBB, vCC
499    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
500
501    // 9C OP_SUB_LONG vAA, vBB, vCC
502    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
503
504    // 9D OP_MUL_LONG vAA, vBB, vCC
505    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
506
507    // 9E OP_DIV_LONG vAA, vBB, vCC
508    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
509
510    // 9F OP_REM_LONG vAA, vBB, vCC
511    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
512
513    // A0 OP_AND_LONG vAA, vBB, vCC
514    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
515
516    // A1 OP_OR_LONG vAA, vBB, vCC
517    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
518
519    // A2 OP_XOR_LONG vAA, vBB, vCC
520    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE,
521
522    // A3 OP_SHL_LONG vAA, vBB, vCC
523    DF_DA_WIDE | DF_UB_WIDE | DF_UC,
524
525    // A4 OP_SHR_LONG vAA, vBB, vCC
526    DF_DA_WIDE | DF_UB_WIDE | DF_UC,
527
528    // A5 OP_USHR_LONG vAA, vBB, vCC
529    DF_DA_WIDE | DF_UB_WIDE | DF_UC,
530
531    // A6 OP_ADD_FLOAT vAA, vBB, vCC
532    DF_DA | DF_UB | DF_UC | DF_FP_A | DF_FP_B | DF_FP_C,
533
534    // A7 OP_SUB_FLOAT vAA, vBB, vCC
535    DF_DA | DF_UB | DF_UC | DF_FP_A | DF_FP_B | DF_FP_C,
536
537    // A8 OP_MUL_FLOAT vAA, vBB, vCC
538    DF_DA | DF_UB | DF_UC | DF_FP_A | DF_FP_B | DF_FP_C,
539
540    // A9 OP_DIV_FLOAT vAA, vBB, vCC
541    DF_DA | DF_UB | DF_UC | DF_FP_A | DF_FP_B | DF_FP_C,
542
543    // AA OP_REM_FLOAT vAA, vBB, vCC
544    DF_DA | DF_UB | DF_UC | DF_FP_A | DF_FP_B | DF_FP_C,
545
546    // AB OP_ADD_DOUBLE vAA, vBB, vCC
547    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE | DF_FP_A | DF_FP_B | DF_FP_C,
548
549    // AC OP_SUB_DOUBLE vAA, vBB, vCC
550    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE | DF_FP_A | DF_FP_B | DF_FP_C,
551
552    // AD OP_MUL_DOUBLE vAA, vBB, vCC
553    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE | DF_FP_A | DF_FP_B | DF_FP_C,
554
555    // AE OP_DIV_DOUBLE vAA, vBB, vCC
556    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE | DF_FP_A | DF_FP_B | DF_FP_C,
557
558    // AF OP_REM_DOUBLE vAA, vBB, vCC
559    DF_DA_WIDE | DF_UB_WIDE | DF_UC_WIDE | DF_FP_A | DF_FP_B | DF_FP_C,
560
561    // B0 OP_ADD_INT_2ADDR vA, vB
562    DF_DA | DF_UA | DF_UB,
563
564    // B1 OP_SUB_INT_2ADDR vA, vB
565    DF_DA | DF_UA | DF_UB,
566
567    // B2 OP_MUL_INT_2ADDR vA, vB
568    DF_DA | DF_UA | DF_UB,
569
570    // B3 OP_DIV_INT_2ADDR vA, vB
571    DF_DA | DF_UA | DF_UB,
572
573    // B4 OP_REM_INT_2ADDR vA, vB
574    DF_DA | DF_UA | DF_UB,
575
576    // B5 OP_AND_INT_2ADDR vA, vB
577    DF_DA | DF_UA | DF_UB,
578
579    // B6 OP_OR_INT_2ADDR vA, vB
580    DF_DA | DF_UA | DF_UB,
581
582    // B7 OP_XOR_INT_2ADDR vA, vB
583    DF_DA | DF_UA | DF_UB,
584
585    // B8 OP_SHL_INT_2ADDR vA, vB
586    DF_DA | DF_UA | DF_UB,
587
588    // B9 OP_SHR_INT_2ADDR vA, vB
589    DF_DA | DF_UA | DF_UB,
590
591    // BA OP_USHR_INT_2ADDR vA, vB
592    DF_DA | DF_UA | DF_UB,
593
594    // BB OP_ADD_LONG_2ADDR vA, vB
595    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
596
597    // BC OP_SUB_LONG_2ADDR vA, vB
598    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
599
600    // BD OP_MUL_LONG_2ADDR vA, vB
601    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
602
603    // BE OP_DIV_LONG_2ADDR vA, vB
604    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
605
606    // BF OP_REM_LONG_2ADDR vA, vB
607    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
608
609    // C0 OP_AND_LONG_2ADDR vA, vB
610    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
611
612    // C1 OP_OR_LONG_2ADDR vA, vB
613    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
614
615    // C2 OP_XOR_LONG_2ADDR vA, vB
616    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE,
617
618    // C3 OP_SHL_LONG_2ADDR vA, vB
619    DF_DA_WIDE | DF_UA_WIDE | DF_UB,
620
621    // C4 OP_SHR_LONG_2ADDR vA, vB
622    DF_DA_WIDE | DF_UA_WIDE | DF_UB,
623
624    // C5 OP_USHR_LONG_2ADDR vA, vB
625    DF_DA_WIDE | DF_UA_WIDE | DF_UB,
626
627    // C6 OP_ADD_FLOAT_2ADDR vA, vB
628    DF_DA | DF_UA | DF_UB | DF_FP_A | DF_FP_B,
629
630    // C7 OP_SUB_FLOAT_2ADDR vA, vB
631    DF_DA | DF_UA | DF_UB | DF_FP_A | DF_FP_B,
632
633    // C8 OP_MUL_FLOAT_2ADDR vA, vB
634    DF_DA | DF_UA | DF_UB | DF_FP_A | DF_FP_B,
635
636    // C9 OP_DIV_FLOAT_2ADDR vA, vB
637    DF_DA | DF_UA | DF_UB | DF_FP_A | DF_FP_B,
638
639    // CA OP_REM_FLOAT_2ADDR vA, vB
640    DF_DA | DF_UA | DF_UB | DF_FP_A | DF_FP_B,
641
642    // CB OP_ADD_DOUBLE_2ADDR vA, vB
643    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE | DF_FP_A | DF_FP_B,
644
645    // CC OP_SUB_DOUBLE_2ADDR vA, vB
646    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE | DF_FP_A | DF_FP_B,
647
648    // CD OP_MUL_DOUBLE_2ADDR vA, vB
649    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE | DF_FP_A | DF_FP_B,
650
651    // CE OP_DIV_DOUBLE_2ADDR vA, vB
652    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE | DF_FP_A | DF_FP_B,
653
654    // CF OP_REM_DOUBLE_2ADDR vA, vB
655    DF_DA_WIDE | DF_UA_WIDE | DF_UB_WIDE | DF_FP_A | DF_FP_B,
656
657    // D0 OP_ADD_INT_LIT16 vA, vB, #+CCCC
658    DF_DA | DF_UB,
659
660    // D1 OP_RSUB_INT vA, vB, #+CCCC
661    DF_DA | DF_UB,
662
663    // D2 OP_MUL_INT_LIT16 vA, vB, #+CCCC
664    DF_DA | DF_UB,
665
666    // D3 OP_DIV_INT_LIT16 vA, vB, #+CCCC
667    DF_DA | DF_UB,
668
669    // D4 OP_REM_INT_LIT16 vA, vB, #+CCCC
670    DF_DA | DF_UB,
671
672    // D5 OP_AND_INT_LIT16 vA, vB, #+CCCC
673    DF_DA | DF_UB,
674
675    // D6 OP_OR_INT_LIT16 vA, vB, #+CCCC
676    DF_DA | DF_UB,
677
678    // D7 OP_XOR_INT_LIT16 vA, vB, #+CCCC
679    DF_DA | DF_UB,
680
681    // D8 OP_ADD_INT_LIT8 vAA, vBB, #+CC
682    DF_DA | DF_UB | DF_IS_LINEAR,
683
684    // D9 OP_RSUB_INT_LIT8 vAA, vBB, #+CC
685    DF_DA | DF_UB,
686
687    // DA OP_MUL_INT_LIT8 vAA, vBB, #+CC
688    DF_DA | DF_UB,
689
690    // DB OP_DIV_INT_LIT8 vAA, vBB, #+CC
691    DF_DA | DF_UB,
692
693    // DC OP_REM_INT_LIT8 vAA, vBB, #+CC
694    DF_DA | DF_UB,
695
696    // DD OP_AND_INT_LIT8 vAA, vBB, #+CC
697    DF_DA | DF_UB,
698
699    // DE OP_OR_INT_LIT8 vAA, vBB, #+CC
700    DF_DA | DF_UB,
701
702    // DF OP_XOR_INT_LIT8 vAA, vBB, #+CC
703    DF_DA | DF_UB,
704
705    // E0 OP_SHL_INT_LIT8 vAA, vBB, #+CC
706    DF_DA | DF_UB,
707
708    // E1 OP_SHR_INT_LIT8 vAA, vBB, #+CC
709    DF_DA | DF_UB,
710
711    // E2 OP_USHR_INT_LIT8 vAA, vBB, #+CC
712    DF_DA | DF_UB,
713
714    // E3 OP_IGET_VOLATILE
715    DF_DA | DF_UB,
716
717    // E4 OP_IPUT_VOLATILE
718    DF_UA | DF_UB,
719
720    // E5 OP_SGET_VOLATILE
721    DF_DA,
722
723    // E6 OP_SPUT_VOLATILE
724    DF_UA,
725
726    // E7 OP_IGET_OBJECT_VOLATILE
727    DF_DA | DF_UB,
728
729    // E8 OP_IGET_WIDE_VOLATILE
730    DF_DA_WIDE | DF_UB,
731
732    // E9 OP_IPUT_WIDE_VOLATILE
733    DF_UA_WIDE | DF_UB,
734
735    // EA OP_SGET_WIDE_VOLATILE
736    DF_DA_WIDE,
737
738    // EB OP_SPUT_WIDE_VOLATILE
739    DF_UA_WIDE,
740
741    // EC OP_BREAKPOINT
742    DF_NOP,
743
744    // ED OP_THROW_VERIFICATION_ERROR
745    DF_NOP,
746
747    // EE OP_EXECUTE_INLINE
748    DF_FORMAT_35C,
749
750    // EF OP_EXECUTE_INLINE_RANGE
751    DF_FORMAT_3RC,
752
753    // F0 OP_INVOKE_OBJECT_INIT_RANGE
754    DF_NOP,
755
756    // F1 OP_RETURN_VOID_BARRIER
757    DF_NOP,
758
759    // F2 OP_IGET_QUICK
760    DF_DA | DF_UB | DF_IS_GETTER,
761
762    // F3 OP_IGET_WIDE_QUICK
763    DF_DA_WIDE | DF_UB | DF_IS_GETTER,
764
765    // F4 OP_IGET_OBJECT_QUICK
766    DF_DA | DF_UB | DF_IS_GETTER,
767
768    // F5 OP_IPUT_QUICK
769    DF_UA | DF_UB | DF_IS_SETTER,
770
771    // F6 OP_IPUT_WIDE_QUICK
772    DF_UA_WIDE | DF_UB | DF_IS_SETTER,
773
774    // F7 OP_IPUT_OBJECT_QUICK
775    DF_UA | DF_UB | DF_IS_SETTER,
776
777    // F8 OP_INVOKE_VIRTUAL_QUICK
778    DF_FORMAT_35C,
779
780    // F9 OP_INVOKE_VIRTUAL_QUICK_RANGE
781    DF_FORMAT_3RC,
782
783    // FA OP_INVOKE_SUPER_QUICK
784    DF_FORMAT_35C,
785
786    // FB OP_INVOKE_SUPER_QUICK_RANGE
787    DF_FORMAT_3RC,
788
789    // FC OP_IPUT_OBJECT_VOLATILE
790    DF_UA | DF_UB,
791
792    // FD OP_SGET_OBJECT_VOLATILE
793    DF_DA,
794
795    // FE OP_SPUT_OBJECT_VOLATILE
796    DF_UA,
797
798    // FF OP_UNUSED_FF
799    DF_NOP,
800
801    // Beginning of extended MIR opcodes
802    // 100 OP_MIR_PHI
803    DF_PHI | DF_DA,
804    /*
805     * For extended MIR inserted at the MIR2LIR stage, it is okay to have
806     * undefined values here.
807     */
808};
809
810/* Return the Dalvik register/subscript pair of a given SSA register */
811int dvmConvertSSARegToDalvik(const CompilationUnit *cUnit, int ssaReg)
812{
813      return GET_ELEM_N(cUnit->ssaToDalvikMap, int, ssaReg);
814}
815
816/*
817 * Utility function to convert encoded SSA register value into Dalvik register
818 * and subscript pair. Each SSA register can be used to index the
819 * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
820 */
821char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn,
822                                      const char *note)
823{
824    char buffer[256];
825    Opcode opcode = insn->opcode;
826    int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
827    int flags;
828    char *ret;
829
830    buffer[0] = 0;
831    if ((int)opcode >= (int)kMirOpFirst) {
832        if ((int)opcode == (int)kMirOpPhi) {
833            strcpy(buffer, "PHI");
834        }
835        else {
836            sprintf(buffer, "Opcode %#x", opcode);
837        }
838        flags = 0;
839    } else {
840        strcpy(buffer, dexGetOpcodeName(opcode));
841        flags = dexGetFlagsFromOpcode(insn->opcode);
842    }
843
844    if (note)
845        strcat(buffer, note);
846
847    /* For branches, decode the instructions to print out the branch targets */
848    if (flags & kInstrCanBranch) {
849        InstructionFormat dalvikFormat = dexGetFormatFromOpcode(insn->opcode);
850        int offset = 0;
851        switch (dalvikFormat) {
852            case kFmt21t:
853                snprintf(buffer + strlen(buffer), 256, " v%d,", insn->vA);
854                offset = (int) insn->vB;
855                break;
856            case kFmt22t:
857                snprintf(buffer + strlen(buffer), 256, " v%d, v%d,",
858                         insn->vA, insn->vB);
859                offset = (int) insn->vC;
860                break;
861            case kFmt10t:
862            case kFmt20t:
863            case kFmt30t:
864                offset = (int) insn->vA;
865                break;
866            default:
867                LOGE("Unexpected branch format %d / opcode %#x", dalvikFormat,
868                     opcode);
869                dvmAbort();
870                break;
871        }
872        snprintf(buffer + strlen(buffer), 256, " (%c%x)",
873                 offset > 0 ? '+' : '-',
874                 offset > 0 ? offset : -offset);
875    } else if (dfAttributes & DF_FORMAT_35C) {
876        unsigned int i;
877        for (i = 0; i < insn->vA; i++) {
878            if (i != 0) strcat(buffer, ",");
879            snprintf(buffer + strlen(buffer), 256, " v%d", insn->arg[i]);
880        }
881    }
882    else if (dfAttributes & DF_FORMAT_3RC) {
883        snprintf(buffer + strlen(buffer), 256,
884                 " v%d..v%d", insn->vC, insn->vC + insn->vA - 1);
885    }
886    else {
887        if (dfAttributes & DF_A_IS_REG) {
888            snprintf(buffer + strlen(buffer), 256, " v%d", insn->vA);
889        }
890        if (dfAttributes & DF_B_IS_REG) {
891            snprintf(buffer + strlen(buffer), 256, ", v%d", insn->vB);
892        }
893        else if ((int)opcode < (int)kMirOpFirst) {
894            snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn->vB);
895        }
896        if (dfAttributes & DF_C_IS_REG) {
897            snprintf(buffer + strlen(buffer), 256, ", v%d", insn->vC);
898        }
899        else if ((int)opcode < (int)kMirOpFirst) {
900            snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn->vC);
901        }
902    }
903    int length = strlen(buffer) + 1;
904    ret = (char *)dvmCompilerNew(length, false);
905    memcpy(ret, buffer, length);
906    return ret;
907}
908
909char *getSSAName(const CompilationUnit *cUnit, int ssaReg, char *name)
910{
911    int ssa2DalvikValue = dvmConvertSSARegToDalvik(cUnit, ssaReg);
912
913    sprintf(name, "v%d_%d",
914            DECODE_REG(ssa2DalvikValue), DECODE_SUB(ssa2DalvikValue));
915    return name;
916}
917
918/*
919 * Dalvik instruction disassembler with optional SSA printing.
920 */
921char *dvmCompilerFullDisassembler(const CompilationUnit *cUnit,
922                                  const MIR *mir)
923{
924    char buffer[256];
925    char operand0[256], operand1[256];
926    const DecodedInstruction *insn = &mir->dalvikInsn;
927    int opcode = insn->opcode;
928    int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
929    char *ret;
930    int length;
931    OpcodeFlags flags;
932
933    buffer[0] = 0;
934    if (opcode >= kMirOpFirst) {
935        if (opcode == kMirOpPhi) {
936            snprintf(buffer, 256, "PHI %s = (%s",
937                     getSSAName(cUnit, mir->ssaRep->defs[0], operand0),
938                     getSSAName(cUnit, mir->ssaRep->uses[0], operand1));
939            int i;
940            for (i = 1; i < mir->ssaRep->numUses; i++) {
941                snprintf(buffer + strlen(buffer), 256, ", %s",
942                         getSSAName(cUnit, mir->ssaRep->uses[i], operand0));
943            }
944            snprintf(buffer + strlen(buffer), 256, ")");
945        }
946        else {
947            sprintf(buffer, "Opcode %#x", opcode);
948        }
949        goto done;
950    } else {
951        strcpy(buffer, dexGetOpcodeName((Opcode)opcode));
952    }
953
954    flags = dexGetFlagsFromOpcode((Opcode)opcode);
955    /* For branches, decode the instructions to print out the branch targets */
956    if (flags & kInstrCanBranch) {
957        InstructionFormat dalvikFormat = dexGetFormatFromOpcode(insn->opcode);
958        int delta = 0;
959        switch (dalvikFormat) {
960            case kFmt21t:
961                snprintf(buffer + strlen(buffer), 256, " %s, ",
962                         getSSAName(cUnit, mir->ssaRep->uses[0], operand0));
963                delta = (int) insn->vB;
964                break;
965            case kFmt22t:
966                snprintf(buffer + strlen(buffer), 256, " %s, %s, ",
967                         getSSAName(cUnit, mir->ssaRep->uses[0], operand0),
968                         getSSAName(cUnit, mir->ssaRep->uses[1], operand1));
969                delta = (int) insn->vC;
970                break;
971            case kFmt10t:
972            case kFmt20t:
973            case kFmt30t:
974                delta = (int) insn->vA;
975                break;
976            default:
977                LOGE("Unexpected branch format: %d", dalvikFormat);
978                dvmAbort();
979                break;
980        }
981        snprintf(buffer + strlen(buffer), 256, " %04x",
982                 mir->offset + delta);
983    } else if (dfAttributes & (DF_FORMAT_35C | DF_FORMAT_3RC)) {
984        unsigned int i;
985        for (i = 0; i < insn->vA; i++) {
986            if (i != 0) strcat(buffer, ",");
987            snprintf(buffer + strlen(buffer), 256, " %s",
988                     getSSAName(cUnit, mir->ssaRep->uses[i], operand0));
989        }
990    } else {
991        int udIdx;
992        if (mir->ssaRep->numDefs) {
993
994            for (udIdx = 0; udIdx < mir->ssaRep->numDefs; udIdx++) {
995                snprintf(buffer + strlen(buffer), 256, " %s",
996                         getSSAName(cUnit, mir->ssaRep->defs[udIdx], operand0));
997            }
998            strcat(buffer, ",");
999        }
1000        if (mir->ssaRep->numUses) {
1001            /* No leading ',' for the first use */
1002            snprintf(buffer + strlen(buffer), 256, " %s",
1003                     getSSAName(cUnit, mir->ssaRep->uses[0], operand0));
1004            for (udIdx = 1; udIdx < mir->ssaRep->numUses; udIdx++) {
1005                snprintf(buffer + strlen(buffer), 256, ", %s",
1006                         getSSAName(cUnit, mir->ssaRep->uses[udIdx], operand0));
1007            }
1008        }
1009        if (opcode < kMirOpFirst) {
1010            InstructionFormat dalvikFormat =
1011                dexGetFormatFromOpcode((Opcode)opcode);
1012            switch (dalvikFormat) {
1013                case kFmt11n:        // op vA, #+B
1014                case kFmt21s:        // op vAA, #+BBBB
1015                case kFmt21h:        // op vAA, #+BBBB00000[00000000]
1016                case kFmt31i:        // op vAA, #+BBBBBBBB
1017                case kFmt51l:        // op vAA, #+BBBBBBBBBBBBBBBB
1018                    snprintf(buffer + strlen(buffer), 256, " #%#x", insn->vB);
1019                    break;
1020                case kFmt21c:        // op vAA, thing@BBBB
1021                case kFmt31c:        // op vAA, thing@BBBBBBBB
1022                    snprintf(buffer + strlen(buffer), 256, " @%#x", insn->vB);
1023                    break;
1024                case kFmt22b:        // op vAA, vBB, #+CC
1025                case kFmt22s:        // op vA, vB, #+CCCC
1026                    snprintf(buffer + strlen(buffer), 256, " #%#x", insn->vC);
1027                    break;
1028                case kFmt22c:        // op vA, vB, thing@CCCC
1029                case kFmt22cs:       // [opt] op vA, vB, field offset CCCC
1030                    snprintf(buffer + strlen(buffer), 256, " @%#x", insn->vC);
1031                    break;
1032                    /* No need for special printing */
1033                default:
1034                    break;
1035            }
1036        }
1037    }
1038
1039done:
1040    length = strlen(buffer) + 1;
1041    ret = (char *) dvmCompilerNew(length, false);
1042    memcpy(ret, buffer, length);
1043    return ret;
1044}
1045
1046/*
1047 * Utility function to convert encoded SSA register value into Dalvik register
1048 * and subscript pair. Each SSA register can be used to index the
1049 * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
1050 */
1051char *dvmCompilerGetSSAString(CompilationUnit *cUnit, SSARepresentation *ssaRep)
1052{
1053    char buffer[256];
1054    char *ret;
1055    int i;
1056
1057    buffer[0] = 0;
1058    for (i = 0; i < ssaRep->numDefs; i++) {
1059        int ssa2DalvikValue = dvmConvertSSARegToDalvik(cUnit, ssaRep->defs[i]);
1060
1061        sprintf(buffer + strlen(buffer), "s%d(v%d_%d) ",
1062                ssaRep->defs[i], DECODE_REG(ssa2DalvikValue),
1063                DECODE_SUB(ssa2DalvikValue));
1064    }
1065
1066    if (ssaRep->numDefs) {
1067        strcat(buffer, "<- ");
1068    }
1069
1070    for (i = 0; i < ssaRep->numUses; i++) {
1071        int ssa2DalvikValue = dvmConvertSSARegToDalvik(cUnit, ssaRep->uses[i]);
1072        int len = strlen(buffer);
1073
1074        if (snprintf(buffer + len, 250 - len, "s%d(v%d_%d) ",
1075                     ssaRep->uses[i], DECODE_REG(ssa2DalvikValue),
1076                     DECODE_SUB(ssa2DalvikValue)) >= (250 - len)) {
1077            strcat(buffer, "...");
1078            break;
1079        }
1080    }
1081
1082    int length = strlen(buffer) + 1;
1083    ret = (char *)dvmCompilerNew(length, false);
1084    memcpy(ret, buffer, length);
1085    return ret;
1086}
1087
1088/* Any register that is used before being defined is considered live-in */
1089static inline void handleLiveInUse(BitVector *useV, BitVector *defV,
1090                                   BitVector *liveInV, int dalvikRegId)
1091{
1092    dvmCompilerSetBit(useV, dalvikRegId);
1093    if (!dvmIsBitSet(defV, dalvikRegId)) {
1094        dvmCompilerSetBit(liveInV, dalvikRegId);
1095    }
1096}
1097
1098/* Mark a reg as being defined */
1099static inline void handleDef(BitVector *defV, int dalvikRegId)
1100{
1101    dvmCompilerSetBit(defV, dalvikRegId);
1102}
1103
1104/*
1105 * Find out live-in variables for natural loops. Variables that are live-in in
1106 * the main loop body are considered to be defined in the entry block.
1107 */
1108bool dvmCompilerFindLocalLiveIn(CompilationUnit *cUnit, BasicBlock *bb)
1109{
1110    MIR *mir;
1111    BitVector *useV, *defV, *liveInV;
1112
1113    if (bb->dataFlowInfo == NULL) return false;
1114
1115    useV = bb->dataFlowInfo->useV =
1116        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
1117    defV = bb->dataFlowInfo->defV =
1118        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
1119    liveInV = bb->dataFlowInfo->liveInV =
1120        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
1121
1122    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
1123        int dfAttributes =
1124            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opcode];
1125        DecodedInstruction *dInsn = &mir->dalvikInsn;
1126
1127        if (dfAttributes & DF_HAS_USES) {
1128            if (dfAttributes & DF_UA) {
1129                handleLiveInUse(useV, defV, liveInV, dInsn->vA);
1130            } else if (dfAttributes & DF_UA_WIDE) {
1131                handleLiveInUse(useV, defV, liveInV, dInsn->vA);
1132                handleLiveInUse(useV, defV, liveInV, dInsn->vA+1);
1133            }
1134            if (dfAttributes & DF_UB) {
1135                handleLiveInUse(useV, defV, liveInV, dInsn->vB);
1136            } else if (dfAttributes & DF_UB_WIDE) {
1137                handleLiveInUse(useV, defV, liveInV, dInsn->vB);
1138                handleLiveInUse(useV, defV, liveInV, dInsn->vB+1);
1139            }
1140            if (dfAttributes & DF_UC) {
1141                handleLiveInUse(useV, defV, liveInV, dInsn->vC);
1142            } else if (dfAttributes & DF_UC_WIDE) {
1143                handleLiveInUse(useV, defV, liveInV, dInsn->vC);
1144                handleLiveInUse(useV, defV, liveInV, dInsn->vC+1);
1145            }
1146        }
1147        if (dfAttributes & DF_HAS_DEFS) {
1148            handleDef(defV, dInsn->vA);
1149            if (dfAttributes & DF_DA_WIDE) {
1150                handleDef(defV, dInsn->vA+1);
1151            }
1152        }
1153    }
1154    return true;
1155}
1156
1157/* Find out the latest SSA register for a given Dalvik register */
1158static void handleSSAUse(CompilationUnit *cUnit, int *uses, int dalvikReg,
1159                         int regIndex)
1160{
1161    int encodedValue = cUnit->dalvikToSSAMap[dalvikReg];
1162    int ssaReg = DECODE_REG(encodedValue);
1163    uses[regIndex] = ssaReg;
1164}
1165
1166/* Setup a new SSA register for a given Dalvik register */
1167static void handleSSADef(CompilationUnit *cUnit, int *defs, int dalvikReg,
1168                         int regIndex)
1169{
1170    int encodedValue = cUnit->dalvikToSSAMap[dalvikReg];
1171    int ssaReg = cUnit->numSSARegs++;
1172    /* Bump up the subscript */
1173    int dalvikSub = DECODE_SUB(encodedValue) + 1;
1174    int newD2SMapping = ENCODE_REG_SUB(ssaReg, dalvikSub);
1175
1176    cUnit->dalvikToSSAMap[dalvikReg] = newD2SMapping;
1177
1178    int newS2DMapping = ENCODE_REG_SUB(dalvikReg, dalvikSub);
1179    dvmInsertGrowableList(cUnit->ssaToDalvikMap, newS2DMapping);
1180
1181    defs[regIndex] = ssaReg;
1182}
1183
1184/* Loop up new SSA names for format_35c instructions */
1185static void dataFlowSSAFormat35C(CompilationUnit *cUnit, MIR *mir)
1186{
1187    DecodedInstruction *dInsn = &mir->dalvikInsn;
1188    int numUses = dInsn->vA;
1189    int i;
1190
1191    mir->ssaRep->numUses = numUses;
1192    mir->ssaRep->uses = (int *)dvmCompilerNew(sizeof(int) * numUses, false);
1193
1194    for (i = 0; i < numUses; i++) {
1195        handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->arg[i], i);
1196    }
1197}
1198
1199/* Loop up new SSA names for format_3rc instructions */
1200static void dataFlowSSAFormat3RC(CompilationUnit *cUnit, MIR *mir)
1201{
1202    DecodedInstruction *dInsn = &mir->dalvikInsn;
1203    int numUses = dInsn->vA;
1204    int i;
1205
1206    mir->ssaRep->numUses = numUses;
1207    mir->ssaRep->uses = (int *)dvmCompilerNew(sizeof(int) * numUses, false);
1208
1209    for (i = 0; i < numUses; i++) {
1210        handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC+i, i);
1211    }
1212}
1213
1214/* Entry function to convert a block into SSA representation */
1215bool dvmCompilerDoSSAConversion(CompilationUnit *cUnit, BasicBlock *bb)
1216{
1217    MIR *mir;
1218
1219    if (bb->dataFlowInfo == NULL) return false;
1220
1221    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
1222        mir->ssaRep = (struct SSARepresentation *)
1223            dvmCompilerNew(sizeof(SSARepresentation), true);
1224
1225        int dfAttributes =
1226            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opcode];
1227
1228        int numUses = 0;
1229
1230        if (dfAttributes & DF_FORMAT_35C) {
1231            dataFlowSSAFormat35C(cUnit, mir);
1232            continue;
1233        }
1234
1235        if (dfAttributes & DF_FORMAT_3RC) {
1236            dataFlowSSAFormat3RC(cUnit, mir);
1237            continue;
1238        }
1239
1240        if (dfAttributes & DF_HAS_USES) {
1241            if (dfAttributes & DF_UA) {
1242                numUses++;
1243            } else if (dfAttributes & DF_UA_WIDE) {
1244                numUses += 2;
1245            }
1246            if (dfAttributes & DF_UB) {
1247                numUses++;
1248            } else if (dfAttributes & DF_UB_WIDE) {
1249                numUses += 2;
1250            }
1251            if (dfAttributes & DF_UC) {
1252                numUses++;
1253            } else if (dfAttributes & DF_UC_WIDE) {
1254                numUses += 2;
1255            }
1256        }
1257
1258        if (numUses) {
1259            mir->ssaRep->numUses = numUses;
1260            mir->ssaRep->uses = (int *)dvmCompilerNew(sizeof(int) * numUses,
1261                                                      false);
1262            mir->ssaRep->fpUse = (bool *)dvmCompilerNew(sizeof(bool) * numUses,
1263                                                false);
1264        }
1265
1266        int numDefs = 0;
1267
1268        if (dfAttributes & DF_HAS_DEFS) {
1269            numDefs++;
1270            if (dfAttributes & DF_DA_WIDE) {
1271                numDefs++;
1272            }
1273        }
1274
1275        if (numDefs) {
1276            mir->ssaRep->numDefs = numDefs;
1277            mir->ssaRep->defs = (int *)dvmCompilerNew(sizeof(int) * numDefs,
1278                                                      false);
1279            mir->ssaRep->fpDef = (bool *)dvmCompilerNew(sizeof(bool) * numDefs,
1280                                                        false);
1281        }
1282
1283        DecodedInstruction *dInsn = &mir->dalvikInsn;
1284
1285        if (dfAttributes & DF_HAS_USES) {
1286            numUses = 0;
1287            if (dfAttributes & DF_UA) {
1288                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_A;
1289                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA, numUses++);
1290            } else if (dfAttributes & DF_UA_WIDE) {
1291                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_A;
1292                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA, numUses++);
1293                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_A;
1294                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vA+1, numUses++);
1295            }
1296            if (dfAttributes & DF_UB) {
1297                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_B;
1298                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB, numUses++);
1299            } else if (dfAttributes & DF_UB_WIDE) {
1300                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_B;
1301                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB, numUses++);
1302                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_B;
1303                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vB+1, numUses++);
1304            }
1305            if (dfAttributes & DF_UC) {
1306                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_C;
1307                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC, numUses++);
1308            } else if (dfAttributes & DF_UC_WIDE) {
1309                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_C;
1310                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC, numUses++);
1311                mir->ssaRep->fpUse[numUses] = dfAttributes & DF_FP_C;
1312                handleSSAUse(cUnit, mir->ssaRep->uses, dInsn->vC+1, numUses++);
1313            }
1314        }
1315        if (dfAttributes & DF_HAS_DEFS) {
1316            mir->ssaRep->fpDef[0] = dfAttributes & DF_FP_A;
1317            handleSSADef(cUnit, mir->ssaRep->defs, dInsn->vA, 0);
1318            if (dfAttributes & DF_DA_WIDE) {
1319                mir->ssaRep->fpDef[1] = dfAttributes & DF_FP_A;
1320                handleSSADef(cUnit, mir->ssaRep->defs, dInsn->vA+1, 1);
1321            }
1322        }
1323    }
1324
1325    /*
1326     * Take a snapshot of Dalvik->SSA mapping at the end of each block. The
1327     * input to PHI nodes can be derived from the snapshot of all predecessor
1328     * blocks.
1329     */
1330    bb->dataFlowInfo->dalvikToSSAMap =
1331        (int *)dvmCompilerNew(sizeof(int) * cUnit->method->registersSize,
1332                              false);
1333
1334    memcpy(bb->dataFlowInfo->dalvikToSSAMap, cUnit->dalvikToSSAMap,
1335           sizeof(int) * cUnit->method->registersSize);
1336    return true;
1337}
1338
1339/* Setup a constant value for opcodes thare have the DF_SETS_CONST attribute */
1340static void setConstant(CompilationUnit *cUnit, int ssaReg, int value)
1341{
1342    dvmSetBit(cUnit->isConstantV, ssaReg);
1343    cUnit->constantValues[ssaReg] = value;
1344}
1345
1346bool dvmCompilerDoConstantPropagation(CompilationUnit *cUnit, BasicBlock *bb)
1347{
1348    MIR *mir;
1349    BitVector *isConstantV = cUnit->isConstantV;
1350
1351    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
1352        int dfAttributes =
1353            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opcode];
1354
1355        DecodedInstruction *dInsn = &mir->dalvikInsn;
1356
1357        if (!(dfAttributes & DF_HAS_DEFS)) continue;
1358
1359        /* Handle instructions that set up constants directly */
1360        if (dfAttributes & DF_SETS_CONST) {
1361            if (dfAttributes & DF_DA) {
1362                switch (dInsn->opcode) {
1363                    case OP_CONST_4:
1364                    case OP_CONST_16:
1365                    case OP_CONST:
1366                        setConstant(cUnit, mir->ssaRep->defs[0], dInsn->vB);
1367                        break;
1368                    case OP_CONST_HIGH16:
1369                        setConstant(cUnit, mir->ssaRep->defs[0],
1370                                    dInsn->vB << 16);
1371                        break;
1372                    default:
1373                        break;
1374                }
1375            } else if (dfAttributes & DF_DA_WIDE) {
1376                switch (dInsn->opcode) {
1377                    case OP_CONST_WIDE_16:
1378                    case OP_CONST_WIDE_32:
1379                        setConstant(cUnit, mir->ssaRep->defs[0], dInsn->vB);
1380                        setConstant(cUnit, mir->ssaRep->defs[1], 0);
1381                        break;
1382                    case OP_CONST_WIDE:
1383                        setConstant(cUnit, mir->ssaRep->defs[0],
1384                                    (int) dInsn->vB_wide);
1385                        setConstant(cUnit, mir->ssaRep->defs[1],
1386                                    (int) (dInsn->vB_wide >> 32));
1387                        break;
1388                    case OP_CONST_WIDE_HIGH16:
1389                        setConstant(cUnit, mir->ssaRep->defs[0], 0);
1390                        setConstant(cUnit, mir->ssaRep->defs[1],
1391                                    dInsn->vB << 16);
1392                        break;
1393                    default:
1394                        break;
1395                }
1396            }
1397        /* Handle instructions that set up constants directly */
1398        } else if (dfAttributes & DF_IS_MOVE) {
1399            int i;
1400
1401            for (i = 0; i < mir->ssaRep->numUses; i++) {
1402                if (!dvmIsBitSet(isConstantV, mir->ssaRep->uses[i])) break;
1403            }
1404            /* Move a register holding a constant to another register */
1405            if (i == mir->ssaRep->numUses) {
1406                setConstant(cUnit, mir->ssaRep->defs[0],
1407                            cUnit->constantValues[mir->ssaRep->uses[0]]);
1408                if (dfAttributes & DF_DA_WIDE) {
1409                    setConstant(cUnit, mir->ssaRep->defs[1],
1410                                cUnit->constantValues[mir->ssaRep->uses[1]]);
1411                }
1412            }
1413        }
1414    }
1415    /* TODO: implement code to handle arithmetic operations */
1416    return true;
1417}
1418
1419bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
1420                                       struct BasicBlock *bb)
1421{
1422    BitVector *isIndVarV = cUnit->loopAnalysis->isIndVarV;
1423    BitVector *isConstantV = cUnit->isConstantV;
1424    GrowableList *ivList = cUnit->loopAnalysis->ivList;
1425    MIR *mir;
1426
1427    if (bb->blockType != kDalvikByteCode && bb->blockType != kEntryBlock) {
1428        return false;
1429    }
1430
1431    /* If the bb doesn't have a phi it cannot contain an induction variable */
1432    if (bb->firstMIRInsn == NULL ||
1433        (int)bb->firstMIRInsn->dalvikInsn.opcode != (int)kMirOpPhi) {
1434        return false;
1435    }
1436
1437    /* Find basic induction variable first */
1438    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
1439        int dfAttributes =
1440            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opcode];
1441
1442        if (!(dfAttributes & DF_IS_LINEAR)) continue;
1443
1444        /*
1445         * For a basic induction variable:
1446         *   1) use[0] should belong to the output of a phi node
1447         *   2) def[0] should belong to the input of the same phi node
1448         *   3) the value added/subtracted is a constant
1449         */
1450        MIR *phi;
1451        for (phi = bb->firstMIRInsn; phi; phi = phi->next) {
1452            if ((int)phi->dalvikInsn.opcode != (int)kMirOpPhi) break;
1453
1454            if (phi->ssaRep->defs[0] == mir->ssaRep->uses[0] &&
1455                phi->ssaRep->uses[1] == mir->ssaRep->defs[0]) {
1456                bool deltaIsConstant = false;
1457                int deltaValue;
1458
1459                switch (mir->dalvikInsn.opcode) {
1460                    case OP_ADD_INT:
1461                        if (dvmIsBitSet(isConstantV,
1462                                        mir->ssaRep->uses[1])) {
1463                            deltaValue =
1464                                cUnit->constantValues[mir->ssaRep->uses[1]];
1465                            deltaIsConstant = true;
1466                        }
1467                        break;
1468                    case OP_SUB_INT:
1469                        if (dvmIsBitSet(isConstantV,
1470                                        mir->ssaRep->uses[1])) {
1471                            deltaValue =
1472                                -cUnit->constantValues[mir->ssaRep->uses[1]];
1473                            deltaIsConstant = true;
1474                        }
1475                        break;
1476                    case OP_ADD_INT_LIT8:
1477                        deltaValue = mir->dalvikInsn.vC;
1478                        deltaIsConstant = true;
1479                        break;
1480                    default:
1481                        break;
1482                }
1483                if (deltaIsConstant) {
1484                    dvmSetBit(isIndVarV, mir->ssaRep->uses[0]);
1485                    InductionVariableInfo *ivInfo = (InductionVariableInfo *)
1486                        dvmCompilerNew(sizeof(InductionVariableInfo),
1487                                       false);
1488
1489                    ivInfo->ssaReg = mir->ssaRep->uses[0];
1490                    ivInfo->basicSSAReg = mir->ssaRep->uses[0];
1491                    ivInfo->m = 1;         // always 1 to basic iv
1492                    ivInfo->c = 0;         // N/A to basic iv
1493                    ivInfo->inc = deltaValue;
1494                    dvmInsertGrowableList(ivList, (intptr_t) ivInfo);
1495                    cUnit->loopAnalysis->numBasicIV++;
1496                    break;
1497                }
1498            }
1499        }
1500    }
1501
1502    /* Find dependent induction variable now */
1503    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
1504        int dfAttributes =
1505            dvmCompilerDataFlowAttributes[mir->dalvikInsn.opcode];
1506
1507        if (!(dfAttributes & DF_IS_LINEAR)) continue;
1508
1509        /* Skip already identified induction variables */
1510        if (dvmIsBitSet(isIndVarV, mir->ssaRep->defs[0])) continue;
1511
1512        /*
1513         * For a dependent induction variable:
1514         *  1) use[0] should be an induction variable (basic/dependent)
1515         *  2) operand2 should be a constant
1516         */
1517        if (dvmIsBitSet(isIndVarV, mir->ssaRep->uses[0])) {
1518            int srcDalvikReg = dvmConvertSSARegToDalvik(cUnit,
1519                                                        mir->ssaRep->uses[0]);
1520            int dstDalvikReg = dvmConvertSSARegToDalvik(cUnit,
1521                                                        mir->ssaRep->defs[0]);
1522
1523            bool cIsConstant = false;
1524            int c = 0;
1525
1526            switch (mir->dalvikInsn.opcode) {
1527                case OP_ADD_INT:
1528                    if (dvmIsBitSet(isConstantV,
1529                                    mir->ssaRep->uses[1])) {
1530                        c = cUnit->constantValues[mir->ssaRep->uses[1]];
1531                        cIsConstant = true;
1532                    }
1533                    break;
1534                case OP_SUB_INT:
1535                    if (dvmIsBitSet(isConstantV,
1536                                    mir->ssaRep->uses[1])) {
1537                        c = -cUnit->constantValues[mir->ssaRep->uses[1]];
1538                        cIsConstant = true;
1539                    }
1540                    break;
1541                case OP_ADD_INT_LIT8:
1542                    c = mir->dalvikInsn.vC;
1543                    cIsConstant = true;
1544                    break;
1545                default:
1546                    break;
1547            }
1548
1549            /* Ignore the update to the basic induction variable itself */
1550            if (DECODE_REG(srcDalvikReg) == DECODE_REG(dstDalvikReg))  {
1551                cUnit->loopAnalysis->ssaBIV = mir->ssaRep->defs[0];
1552                cIsConstant = false;
1553            }
1554
1555            if (cIsConstant) {
1556                unsigned int i;
1557                dvmSetBit(isIndVarV, mir->ssaRep->defs[0]);
1558                InductionVariableInfo *ivInfo = (InductionVariableInfo *)
1559                    dvmCompilerNew(sizeof(InductionVariableInfo),
1560                                   false);
1561                InductionVariableInfo *ivInfoOld = NULL ;
1562
1563                for (i = 0; i < ivList->numUsed; i++) {
1564                    ivInfoOld = (InductionVariableInfo *) ivList->elemList[i];
1565                    if (ivInfoOld->ssaReg == mir->ssaRep->uses[0]) break;
1566                }
1567
1568                /* Guaranteed to find an element */
1569                assert(i < ivList->numUsed);
1570
1571                ivInfo->ssaReg = mir->ssaRep->defs[0];
1572                ivInfo->basicSSAReg = ivInfoOld->basicSSAReg;
1573                ivInfo->m = ivInfoOld->m;
1574                ivInfo->c = c + ivInfoOld->c;
1575                ivInfo->inc = ivInfoOld->inc;
1576                dvmInsertGrowableList(ivList, (intptr_t) ivInfo);
1577            }
1578        }
1579    }
1580    return true;
1581}
1582
1583/* Setup the basic data structures for SSA conversion */
1584void dvmInitializeSSAConversion(CompilationUnit *cUnit)
1585{
1586    int i;
1587    int numDalvikReg = cUnit->method->registersSize;
1588
1589    cUnit->ssaToDalvikMap = (GrowableList *)dvmCompilerNew(sizeof(GrowableList),
1590                                                           false);
1591    dvmInitGrowableList(cUnit->ssaToDalvikMap, numDalvikReg);
1592
1593    /*
1594     * Initial number of SSA registers is equal to the number of Dalvik
1595     * registers.
1596     */
1597    cUnit->numSSARegs = numDalvikReg;
1598
1599    /*
1600     * Initialize the SSA2Dalvik map list. For the first numDalvikReg elements,
1601     * the subscript is 0 so we use the ENCODE_REG_SUB macro to encode the value
1602     * into "(0 << 16) | i"
1603     */
1604    for (i = 0; i < numDalvikReg; i++) {
1605        dvmInsertGrowableList(cUnit->ssaToDalvikMap, ENCODE_REG_SUB(i, 0));
1606    }
1607
1608    /*
1609     * Initialize the DalvikToSSAMap map. The low 16 bit is the SSA register id,
1610     * while the high 16 bit is the current subscript. The original Dalvik
1611     * register N is mapped to SSA register N with subscript 0.
1612     */
1613    cUnit->dalvikToSSAMap = (int *)dvmCompilerNew(sizeof(int) * numDalvikReg,
1614                                                  false);
1615    for (i = 0; i < numDalvikReg; i++) {
1616        cUnit->dalvikToSSAMap[i] = i;
1617    }
1618
1619    /*
1620     * Allocate the BasicBlockDataFlow structure for the entry and code blocks
1621     */
1622    GrowableListIterator iterator;
1623
1624    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
1625
1626    while (true) {
1627        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
1628        if (bb == NULL) break;
1629        if (bb->hidden == true) continue;
1630        if (bb->blockType == kDalvikByteCode ||
1631            bb->blockType == kEntryBlock ||
1632            bb->blockType == kExitBlock) {
1633            bb->dataFlowInfo = (BasicBlockDataFlow *)
1634                dvmCompilerNew(sizeof(BasicBlockDataFlow),
1635                               true);
1636        }
1637    }
1638}
1639
1640/* Clear the visited flag for each BB */
1641bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit,
1642                                 struct BasicBlock *bb)
1643{
1644    bb->visited = false;
1645    return true;
1646}
1647
1648void dvmCompilerDataFlowAnalysisDispatcher(CompilationUnit *cUnit,
1649                bool (*func)(CompilationUnit *, BasicBlock *),
1650                DataFlowAnalysisMode dfaMode,
1651                bool isIterative)
1652{
1653    bool change = true;
1654
1655    while (change) {
1656        change = false;
1657
1658        /* Scan all blocks and perform the operations specified in func */
1659        if (dfaMode == kAllNodes) {
1660            GrowableListIterator iterator;
1661            dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
1662            while (true) {
1663                BasicBlock *bb =
1664                    (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
1665                if (bb == NULL) break;
1666                if (bb->hidden == true) continue;
1667                change |= (*func)(cUnit, bb);
1668            }
1669        }
1670        /*
1671         * Scan all reachable blocks and perform the operations specified in
1672         * func.
1673         */
1674        else if (dfaMode == kReachableNodes) {
1675            int numReachableBlocks = cUnit->numReachableBlocks;
1676            int idx;
1677            const GrowableList *blockList = &cUnit->blockList;
1678
1679            for (idx = 0; idx < numReachableBlocks; idx++) {
1680                int blockIdx = cUnit->dfsOrder.elemList[idx];
1681                BasicBlock *bb =
1682                    (BasicBlock *) dvmGrowableListGetElement(blockList,
1683                                                             blockIdx);
1684                change |= (*func)(cUnit, bb);
1685            }
1686        }
1687        /*
1688         * Scan all reachable blocks by the pre-order in the depth-first-search
1689         * CFG and perform the operations specified in func.
1690         */
1691        else if (dfaMode == kPreOrderDFSTraversal) {
1692            int numReachableBlocks = cUnit->numReachableBlocks;
1693            int idx;
1694            const GrowableList *blockList = &cUnit->blockList;
1695
1696            for (idx = 0; idx < numReachableBlocks; idx++) {
1697                int dfsIdx = cUnit->dfsOrder.elemList[idx];
1698                BasicBlock *bb =
1699                    (BasicBlock *) dvmGrowableListGetElement(blockList, dfsIdx);
1700                change |= (*func)(cUnit, bb);
1701            }
1702        }
1703        /*
1704         * Scan all reachable blocks by the post-order in the depth-first-search
1705         * CFG and perform the operations specified in func.
1706         */
1707        else if (dfaMode == kPostOrderDFSTraversal) {
1708            int numReachableBlocks = cUnit->numReachableBlocks;
1709            int idx;
1710            const GrowableList *blockList = &cUnit->blockList;
1711
1712            for (idx = numReachableBlocks - 1; idx >= 0; idx--) {
1713                int dfsIdx = cUnit->dfsOrder.elemList[idx];
1714                BasicBlock *bb =
1715                    (BasicBlock *) dvmGrowableListGetElement(blockList, dfsIdx);
1716                change |= (*func)(cUnit, bb);
1717            }
1718        }
1719        /*
1720         * Scan all reachable blocks by the post-order in the dominator tree
1721         * and perform the operations specified in func.
1722         */
1723        else if (dfaMode == kPostOrderDOMTraversal) {
1724            int numReachableBlocks = cUnit->numReachableBlocks;
1725            int idx;
1726            const GrowableList *blockList = &cUnit->blockList;
1727
1728            for (idx = 0; idx < numReachableBlocks; idx++) {
1729                int domIdx = cUnit->domPostOrderTraversal.elemList[idx];
1730                BasicBlock *bb =
1731                    (BasicBlock *) dvmGrowableListGetElement(blockList, domIdx);
1732                change |= (*func)(cUnit, bb);
1733            }
1734        }
1735        /* If isIterative is false, exit the loop after the first iteration */
1736        change &= isIterative;
1737    }
1738}
1739
1740/* Main entry point to do SSA conversion for non-loop traces */
1741void dvmCompilerNonLoopAnalysis(CompilationUnit *cUnit)
1742{
1743    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion,
1744                                          kAllNodes,
1745                                          false /* isIterative */);
1746}
1747