blob: b2a9c0a8e708fe4c79fa52a81602316b881bfc92 [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
Mark Mendellfb8d2792015-03-31 22:16:59 -040019#include "arch/x86/instruction_set_features_x86.h"
Mathieu Chartierb666f482015-02-18 14:33:14 -080020#include "base/arena_allocator.h"
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010021#include "builder.h"
Nicolas Geoffray31d76b42014-06-09 15:02:22 +010022#include "code_generator.h"
Nicolas Geoffray8a16d972014-09-11 10:30:02 +010023#include "code_generator_x86.h"
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010024#include "dex_file.h"
25#include "dex_instruction.h"
Calin Juravlecd6dffe2015-01-08 17:35:35 +000026#include "driver/compiler_options.h"
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010027#include "graph_visualizer.h"
28#include "nodes.h"
29#include "optimizing_unit_test.h"
30#include "pretty_printer.h"
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010031#include "ssa_liveness_analysis.h"
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010032
Alex Light68289a52015-12-15 17:30:30 -080033namespace art {
David Brazdild9510df2015-11-04 23:30:22 +000034
Vladimir Markoca6fff82017-10-03 14:49:14 +010035class LinearizeTest : public OptimizingUnitTest {
36 protected:
37 template <size_t number_of_blocks>
38 void TestCode(const uint16_t* data, const uint32_t (&expected_order)[number_of_blocks]);
39};
David Brazdil4833f5a2015-12-16 10:37:39 +000040
Vladimir Markofa6b93c2015-09-15 10:15:55 +010041template <size_t number_of_blocks>
Vladimir Markoca6fff82017-10-03 14:49:14 +010042void LinearizeTest::TestCode(const uint16_t* data,
43 const uint32_t (&expected_order)[number_of_blocks]) {
44 HGraph* graph = CreateCFG(data);
Mark Mendellfb8d2792015-03-31 22:16:59 -040045 std::unique_ptr<const X86InstructionSetFeatures> features_x86(
46 X86InstructionSetFeatures::FromCppDefines());
47 x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
Vladimir Markoe764d2e2017-10-05 14:35:55 +010048 SsaLivenessAnalysis liveness(graph, &codegen, GetScopedAllocator());
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010049 liveness.Analyze();
50
Vladimir Markofa6b93c2015-09-15 10:15:55 +010051 ASSERT_EQ(graph->GetLinearOrder().size(), number_of_blocks);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010052 for (size_t i = 0; i < number_of_blocks; ++i) {
Vladimir Markofa6b93c2015-09-15 10:15:55 +010053 ASSERT_EQ(graph->GetLinearOrder()[i]->GetBlockId(), expected_order[i]);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010054 }
55}
56
David Brazdil4833f5a2015-12-16 10:37:39 +000057TEST_F(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
Vladimir Markofa6b93c2015-09-15 10:15:55 +010078 const uint32_t blocks[] = {0, 1, 2, 7, 3, 4, 8, 5, 6};
79 TestCode(data, blocks);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +010080}
81
David Brazdil4833f5a2015-12-16 10:37:39 +000082TEST_F(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
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100103 const uint32_t blocks[] = {0, 1, 2, 7, 4, 5, 8, 3, 6};
104 TestCode(data, blocks);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100105}
106
David Brazdil4833f5a2015-12-16 10:37:39 +0000107TEST_F(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
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100130 const uint32_t blocks[] = {0, 1, 2, 8, 5, 6, 4, 9, 3, 7};
131 TestCode(data, blocks);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100132}
133
David Brazdil4833f5a2015-12-16 10:37:39 +0000134TEST_F(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
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100160 const uint32_t blocks[] = {0, 1, 2, 8, 3, 10, 4, 5, 11, 9, 6, 7};
161 TestCode(data, blocks);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100162}
163
David Brazdil4833f5a2015-12-16 10:37:39 +0000164TEST_F(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
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100190 const uint32_t blocks[] = {0, 1, 2, 8, 4, 10, 5, 6, 11, 9, 3, 7};
191 TestCode(data, blocks);
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100192}
193
David Brazdil4833f5a2015-12-16 10:37:39 +0000194TEST_F(LinearizeTest, CFG6) {
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000195 // 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
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100216 const uint32_t blocks[] = {0, 1, 2, 3, 4, 6, 9, 8, 5, 7};
217 TestCode(data, blocks);
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000218}
219
David Brazdil4833f5a2015-12-16 10:37:39 +0000220TEST_F(LinearizeTest, CFG7) {
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000221 // 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
Vladimir Markofa6b93c2015-09-15 10:15:55 +0100244 const uint32_t blocks[] = {0, 1, 2, 3, 4, 9, 8, 6, 5, 7};
245 TestCode(data, blocks);
Nicolas Geoffraya8eed3a2014-11-24 17:47:10 +0000246}
247
Nicolas Geoffray0d3f5782014-05-14 09:43:38 +0100248} // namespace art