dominator_test.cc revision 787c3076635cf117eb646c5a89a9014b2072fb44
1/*
2 * Copyright (C) 2014 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 "builder.h"
18#include "dex_instruction.h"
19#include "nodes.h"
20#include "optimizing_unit_test.h"
21#include "utils/arena_allocator.h"
22
23#include "gtest/gtest.h"
24
25namespace art {
26
27static void TestCode(const uint16_t* data, const int* blocks, size_t blocks_length) {
28  ArenaPool pool;
29  ArenaAllocator allocator(&pool);
30  HGraphBuilder builder(&allocator);
31  const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
32  HGraph* graph = builder.BuildGraph(*item);
33  ASSERT_NE(graph, nullptr);
34  graph->BuildDominatorTree();
35  ASSERT_EQ(graph->GetBlocks()->Size(), blocks_length);
36  for (size_t i = 0; i < blocks_length; i++) {
37    if (blocks[i] == -1) {
38      ASSERT_EQ(nullptr, graph->GetBlocks()->Get(i)->GetDominator());
39    } else {
40      ASSERT_NE(nullptr, graph->GetBlocks()->Get(i)->GetDominator());
41      ASSERT_EQ(blocks[i], graph->GetBlocks()->Get(i)->GetDominator()->GetBlockId());
42    }
43  }
44}
45
46TEST(OptimizerTest, ReturnVoid) {
47  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
48      Instruction::RETURN_VOID);  // Block number 1
49
50  const int dominators[] = {
51    -1,
52    0,
53    1
54  };
55
56  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
57}
58
59TEST(OptimizerTest, CFG1) {
60  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
61    Instruction::GOTO | 0x100,  // Block number 1
62    Instruction::RETURN_VOID);  // Block number 2
63
64  const int dominators[] = {
65    -1,
66    0,
67    1,
68    2
69  };
70
71  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
72}
73
74TEST(OptimizerTest, CFG2) {
75  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
76    Instruction::GOTO | 0x100,  // Block number 1
77    Instruction::GOTO | 0x100,  // Block number 2
78    Instruction::RETURN_VOID);  // Block number 3
79
80  const int dominators[] = {
81    -1,
82    0,
83    1,
84    2,
85    3
86  };
87
88  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
89}
90
91TEST(OptimizerTest, CFG3) {
92  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
93    Instruction::GOTO | 0x200,    // Block number 1
94    Instruction::RETURN_VOID,     // Block number 2
95    Instruction::GOTO | 0xFF00);  // Block number 3
96
97  const int dominators[] = {
98    -1,
99    0,
100    3,
101    1,
102    2
103  };
104
105  TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
106
107  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
108    Instruction::GOTO_16, 3,
109    Instruction::RETURN_VOID,
110    Instruction::GOTO_16, 0xFFFF);
111
112  TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
113
114  const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
115    Instruction::GOTO_32, 4, 0,
116    Instruction::RETURN_VOID,
117    Instruction::GOTO_32, 0xFFFF, 0xFFFF);
118
119  TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
120}
121
122TEST(OptimizerTest, CFG4) {
123  const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
124    Instruction::NOP,
125    Instruction::GOTO | 0xFF00);
126
127  const int dominators[] = {
128    -1,
129    0,
130    -1
131  };
132
133  TestCode(data1, dominators, sizeof(dominators) / sizeof(int));
134
135  const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
136    Instruction::GOTO_32, 0, 0);
137
138  TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
139}
140
141TEST(OptimizerTest, CFG5) {
142  const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
143    Instruction::RETURN_VOID,     // Block number 1
144    Instruction::GOTO | 0x100,    // Dead block
145    Instruction::GOTO | 0xFE00);  // Block number 2
146
147
148  const int dominators[] = {
149    -1,
150    0,
151    -1,
152    1
153  };
154
155  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
156}
157
158TEST(OptimizerTest, CFG6) {
159  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
160    Instruction::CONST_4 | 0 | 0,
161    Instruction::IF_EQ, 3,
162    Instruction::GOTO | 0x100,
163    Instruction::RETURN_VOID);
164
165  const int dominators[] = {
166    -1,
167    0,
168    1,
169    1,
170    3
171  };
172
173  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
174}
175
176TEST(OptimizerTest, CFG7) {
177  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
178    Instruction::CONST_4 | 0 | 0,
179    Instruction::IF_EQ, 3,        // Block number 1
180    Instruction::GOTO | 0x100,    // Block number 2
181    Instruction::GOTO | 0xFF00);  // Block number 3
182
183  const int dominators[] = {
184    -1,
185    0,
186    1,
187    1,
188    -1  // exit block is not dominated by any block due to the spin loop.
189  };
190
191  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
192}
193
194TEST(OptimizerTest, CFG8) {
195  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
196    Instruction::CONST_4 | 0 | 0,
197    Instruction::IF_EQ, 3,        // Block number 1
198    Instruction::GOTO | 0x200,    // Block number 2
199    Instruction::GOTO | 0x100,    // Block number 3
200    Instruction::GOTO | 0xFF00);  // Block number 4
201
202  const int dominators[] = {
203    -1,
204    0,
205    1,
206    1,
207    1,
208    -1  // exit block is not dominated by any block due to the spin loop.
209  };
210
211  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
212}
213
214TEST(OptimizerTest, CFG9) {
215  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
216    Instruction::CONST_4 | 0 | 0,
217    Instruction::IF_EQ, 3,        // Block number 1
218    Instruction::GOTO | 0x200,    // Block number 2
219    Instruction::GOTO | 0x100,    // Block number 3
220    Instruction::GOTO | 0xFE00);  // Block number 4
221
222  const int dominators[] = {
223    -1,
224    0,
225    1,
226    1,
227    1,
228    -1  // exit block is not dominated by any block due to the spin loop.
229  };
230
231  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
232}
233
234TEST(OptimizerTest, CFG10) {
235  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
236    Instruction::CONST_4 | 0 | 0,
237    Instruction::IF_EQ, 6,  // Block number 1
238    Instruction::IF_EQ, 3,  // Block number 2
239    Instruction::GOTO | 0x100,  // Block number 3
240    Instruction::GOTO | 0x100,  // Block number 4
241    Instruction::RETURN_VOID);  // Block number 5
242
243  const int dominators[] = {
244    -1,
245    0,
246    1,
247    2,
248    2,
249    1,
250    5  // Block number 5 dominates exit block
251  };
252
253  TestCode(data, dominators, sizeof(dominators) / sizeof(int));
254}
255
256}  // namespace art
257