blob: 59404dcb14185406e9a739831b5e322ce3b4a698 [file] [log] [blame]
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +01001/*
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 <fstream>
18
19#include "base/stringprintf.h"
20#include "builder.h"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010021#include "code_generator.h"
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010022#include "code_generator_x86.h"
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010023#include "dex_file.h"
24#include "dex_instruction.h"
25#include "graph_visualizer.h"
26#include "nodes.h"
27#include "optimizing_unit_test.h"
28#include "pretty_printer.h"
29#include "ssa_builder.h"
30#include "ssa_liveness_analysis.h"
31#include "utils/arena_allocator.h"
32
33#include "gtest/gtest.h"
34
35namespace art {
36
37static void TestCode(const uint16_t* data, const int* expected_order, size_t number_of_blocks) {
38 ArenaPool pool;
39 ArenaAllocator allocator(&pool);
40 HGraphBuilder builder(&allocator);
41 const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
42 HGraph* graph = builder.BuildGraph(*item);
43 ASSERT_NE(graph, nullptr);
44
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000045 graph->TryBuildingSsa();
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010046
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010047 x86::CodeGeneratorX86 codegen(graph);
48 SsaLivenessAnalysis liveness(*graph, &codegen);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010049 liveness.Analyze();
50
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +000051 ASSERT_EQ(liveness.GetLinearOrder().Size(), number_of_blocks);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010052 for (size_t i = 0; i < number_of_blocks; ++i) {
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +000053 ASSERT_EQ(liveness.GetLinearOrder().Get(i)->GetBlockId(), expected_order[i]);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010054 }
55}
56
57TEST(LinearizeTest, CFG1) {
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +010058 // Structure of this graph (+ are back edges)
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010059 // Block0
60 // |
61 // Block1
62 // |
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +010063 // Block2 ++++++
64 // / \ +
65 // Block5 Block7 +
66 // | | +
67 // Block6 Block3 +
68 // + / \ +
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010069 // Block4 Block8
70
71 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
72 Instruction::CONST_4 | 0 | 0,
73 Instruction::IF_EQ, 5,
74 Instruction::IF_EQ, 0xFFFE,
75 Instruction::GOTO | 0xFE00,
76 Instruction::RETURN_VOID);
77
78 const int blocks[] = {0, 1, 2, 7, 3, 4, 8, 5, 6};
79 TestCode(data, blocks, 9);
80}
81
82TEST(LinearizeTest, CFG2) {
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +010083 // Structure of this graph (+ are back edges)
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010084 // Block0
85 // |
86 // Block1
87 // |
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +010088 // Block2 ++++++
89 // / \ +
90 // Block3 Block7 +
91 // | | +
92 // Block6 Block4 +
93 // + / \ +
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010094 // Block5 Block8
95
96 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
97 Instruction::CONST_4 | 0 | 0,
98 Instruction::IF_EQ, 3,
99 Instruction::RETURN_VOID,
100 Instruction::IF_EQ, 0xFFFD,
101 Instruction::GOTO | 0xFE00);
102
103 const int blocks[] = {0, 1, 2, 7, 4, 5, 8, 3, 6};
104 TestCode(data, blocks, 9);
105}
106
107TEST(LinearizeTest, CFG3) {
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +0100108 // Structure of this graph (+ are back edges)
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100109 // Block0
110 // |
111 // Block1
112 // |
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +0100113 // Block2 ++++++
114 // / \ +
115 // Block3 Block8 +
116 // | | +
117 // Block7 Block5 +
118 // / + \ +
119 // Block6 + Block9
120 // | +
121 // Block4 ++
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100122 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
123 Instruction::CONST_4 | 0 | 0,
124 Instruction::IF_EQ, 4,
125 Instruction::RETURN_VOID,
126 Instruction::GOTO | 0x0100,
127 Instruction::IF_EQ, 0xFFFC,
128 Instruction::GOTO | 0xFD00);
129
130 const int blocks[] = {0, 1, 2, 8, 5, 6, 4, 9, 3, 7};
131 TestCode(data, blocks, 10);
132}
133
134TEST(LinearizeTest, CFG4) {
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +0100135 /* Structure of this graph (+ are back edges)
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100136 // Block0
137 // |
138 // Block1
139 // |
140 // Block2
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +0100141 // / + \
142 // Block6 + Block8
143 // | + |
144 // Block7 + Block3 +++++++
145 // + / \ +
146 // Block9 Block10 +
147 // | +
148 // Block4 +
149 // + / \ +
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100150 // Block5 Block11
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +0100151 */
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100152 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
153 Instruction::CONST_4 | 0 | 0,
154 Instruction::IF_EQ, 7,
155 Instruction::IF_EQ, 0xFFFE,
156 Instruction::IF_EQ, 0xFFFE,
157 Instruction::GOTO | 0xFE00,
158 Instruction::RETURN_VOID);
159
160 const int blocks[] = {0, 1, 2, 8, 3, 10, 4, 5, 11, 9, 6, 7};
161 TestCode(data, blocks, 12);
162}
163
164TEST(LinearizeTest, CFG5) {
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +0100165 /* Structure of this graph (+ are back edges)
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100166 // Block0
167 // |
168 // Block1
169 // |
170 // Block2
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +0100171 // / + \
172 // Block3 + Block8
173 // | + |
174 // Block7 + Block4 +++++++
175 // + / \ +
176 // Block9 Block10 +
177 // | +
178 // Block5 +
179 // +/ \ +
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100180 // Block6 Block11
Nicolas Geoffray8f1a4d42014-05-16 09:36:00 +0100181 */
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100182 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
183 Instruction::CONST_4 | 0 | 0,
184 Instruction::IF_EQ, 3,
185 Instruction::RETURN_VOID,
186 Instruction::IF_EQ, 0xFFFD,
187 Instruction::IF_EQ, 0xFFFE,
188 Instruction::GOTO | 0xFE00);
189
190 const int blocks[] = {0, 1, 2, 8, 4, 10, 5, 6, 11, 9, 3, 7};
191 TestCode(data, blocks, 12);
192}
193
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000194TEST(LinearizeTest, CFG6) {
195 // Block0
196 // |
197 // Block1
198 // |
199 // Block2 ++++++++++++++
200 // | +
201 // Block3 +
202 // / \ +
203 // Block8 Block4 +
204 // | / \ +
205 // Block5 <- Block9 Block6 +
206 // |
207 // Block7
208 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
209 Instruction::CONST_4 | 0 | 0,
210 Instruction::GOTO | 0x0100,
211 Instruction::IF_EQ, 0x0004,
212 Instruction::IF_EQ, 0x0003,
213 Instruction::RETURN_VOID,
214 Instruction::GOTO | 0xFA00);
215
216 const int blocks[] = {0, 1, 2, 3, 4, 6, 9, 8, 5, 7};
217 TestCode(data, blocks, arraysize(blocks));
218}
219
220TEST(LinearizeTest, CFG7) {
221 // Structure of this graph (+ are back edges)
222 // Block0
223 // |
224 // Block1
225 // |
226 // Block2 ++++++++
227 // | +
228 // Block3 +
229 // / \ +
230 // Block4 Block8 +
231 // / \ | +
232 // Block5 Block9 - Block6 +
233 // |
234 // Block7
235 //
236 const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
237 Instruction::CONST_4 | 0 | 0,
238 Instruction::GOTO | 0x0100,
239 Instruction::IF_EQ, 0x0005,
240 Instruction::IF_EQ, 0x0003,
241 Instruction::RETURN_VOID,
242 Instruction::GOTO | 0xFA00);
243
244 const int blocks[] = {0, 1, 2, 3, 4, 9, 8, 6, 5, 7};
245 TestCode(data, blocks, arraysize(blocks));
246}
247
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100248} // namespace art