blob: 9c69f8c75bbe39999a1b66adbdb601461db1896d [file] [log] [blame]
Roland Levillain556c3d12014-09-18 15:25:07 +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
Roland Levillain93445682014-10-06 19:24:02 +010017#include <functional>
18
Mark Mendellfb8d2792015-03-31 22:16:59 -040019#include "arch/x86/instruction_set_features_x86.h"
Roland Levillain75be2832014-10-17 17:02:00 +010020#include "code_generator_x86.h"
21#include "constant_folding.h"
Roland Levillain556c3d12014-09-18 15:25:07 +010022#include "dead_code_elimination.h"
Calin Juravlecd6dffe2015-01-08 17:35:35 +000023#include "driver/compiler_options.h"
Roland Levillain556c3d12014-09-18 15:25:07 +010024#include "graph_checker.h"
25#include "optimizing_unit_test.h"
Roland Levillain75be2832014-10-17 17:02:00 +010026#include "pretty_printer.h"
Roland Levillain556c3d12014-09-18 15:25:07 +010027
28#include "gtest/gtest.h"
29
30namespace art {
31
Aart Bik96709f12015-10-28 17:49:07 -070032/**
33 * Fixture class for the constant folding and dce tests.
34 */
David Brazdil4833f5a2015-12-16 10:37:39 +000035class ConstantFoldingTest : public CommonCompilerTest {
Aart Bik96709f12015-10-28 17:49:07 -070036 public:
37 ConstantFoldingTest() : pool_(), allocator_(&pool_) {
38 graph_ = CreateGraph(&allocator_);
39 }
Roland Levillain556c3d12014-09-18 15:25:07 +010040
Aart Bik96709f12015-10-28 17:49:07 -070041 void TestCode(const uint16_t* data,
42 const std::string& expected_before,
43 const std::string& expected_after_cf,
44 const std::string& expected_after_dce,
45 std::function<void(HGraph*)> check_after_cf,
46 Primitive::Type return_type = Primitive::kPrimInt) {
47 graph_ = CreateCFG(&allocator_, data, return_type);
48 TestCodeOnReadyGraph(expected_before,
49 expected_after_cf,
50 expected_after_dce,
51 check_after_cf);
52 }
Roland Levillain556c3d12014-09-18 15:25:07 +010053
Aart Bik96709f12015-10-28 17:49:07 -070054 void TestCodeOnReadyGraph(const std::string& expected_before,
55 const std::string& expected_after_cf,
56 const std::string& expected_after_dce,
57 std::function<void(HGraph*)> check_after_cf) {
58 ASSERT_NE(graph_, nullptr);
Roland Levillain556c3d12014-09-18 15:25:07 +010059
Aart Bik96709f12015-10-28 17:49:07 -070060 StringPrettyPrinter printer_before(graph_);
61 printer_before.VisitInsertionOrder();
62 std::string actual_before = printer_before.str();
63 EXPECT_EQ(expected_before, actual_before);
Roland Levillain556c3d12014-09-18 15:25:07 +010064
Aart Bik96709f12015-10-28 17:49:07 -070065 std::unique_ptr<const X86InstructionSetFeatures> features_x86(
66 X86InstructionSetFeatures::FromCppDefines());
67 x86::CodeGeneratorX86 codegenX86(graph_, *features_x86.get(), CompilerOptions());
68 HConstantFolding(graph_).Run();
David Brazdilbadd8262016-02-02 16:28:56 +000069 GraphChecker graph_checker_cf(graph_);
70 graph_checker_cf.Run();
71 ASSERT_TRUE(graph_checker_cf.IsValid());
Roland Levillain556c3d12014-09-18 15:25:07 +010072
Aart Bik96709f12015-10-28 17:49:07 -070073 StringPrettyPrinter printer_after_cf(graph_);
74 printer_after_cf.VisitInsertionOrder();
75 std::string actual_after_cf = printer_after_cf.str();
76 EXPECT_EQ(expected_after_cf, actual_after_cf);
Roland Levillain93445682014-10-06 19:24:02 +010077
Aart Bik96709f12015-10-28 17:49:07 -070078 check_after_cf(graph_);
Roland Levillain556c3d12014-09-18 15:25:07 +010079
Aart Bik96709f12015-10-28 17:49:07 -070080 HDeadCodeElimination(graph_).Run();
David Brazdilbadd8262016-02-02 16:28:56 +000081 GraphChecker graph_checker_dce(graph_);
82 graph_checker_dce.Run();
83 ASSERT_TRUE(graph_checker_dce.IsValid());
Roland Levillain556c3d12014-09-18 15:25:07 +010084
Aart Bik96709f12015-10-28 17:49:07 -070085 StringPrettyPrinter printer_after_dce(graph_);
86 printer_after_dce.VisitInsertionOrder();
87 std::string actual_after_dce = printer_after_dce.str();
88 EXPECT_EQ(expected_after_dce, actual_after_dce);
89 }
90
91 ArenaPool pool_;
92 ArenaAllocator allocator_;
93 HGraph* graph_;
94};
Roland Levillain556c3d12014-09-18 15:25:07 +010095
96/**
Roland Levillain9240d6a2014-10-20 16:47:04 +010097 * Tiny three-register program exercising int constant folding on negation.
98 *
99 * 16-bit
100 * offset
101 * ------
102 * v0 <- 1 0. const/4 v0, #+1
Roland Levillainc90bc7c2014-12-11 12:14:33 +0000103 * v1 <- -v0 1. neg-int v1, v0
Roland Levillain9240d6a2014-10-20 16:47:04 +0100104 * return v1 2. return v1
105 */
Aart Bik96709f12015-10-28 17:49:07 -0700106TEST_F(ConstantFoldingTest, IntConstantFoldingNegation) {
Roland Levillain9240d6a2014-10-20 16:47:04 +0100107 const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
108 Instruction::CONST_4 | 0 << 8 | 1 << 12,
109 Instruction::NEG_INT | 1 << 8 | 0 << 12,
110 Instruction::RETURN | 1 << 8);
111
112 std::string expected_before =
113 "BasicBlock 0, succ: 1\n"
114 " 2: IntConstant [5]\n"
115 " 10: SuspendCheck\n"
116 " 11: Goto 1\n"
117 "BasicBlock 1, pred: 0, succ: 2\n"
118 " 5: Neg(2) [8]\n"
119 " 8: Return(5)\n"
120 "BasicBlock 2, pred: 1\n"
121 " 9: Exit\n";
122
123 // Expected difference after constant folding.
124 diff_t expected_cf_diff = {
125 { " 2: IntConstant [5]\n", " 2: IntConstant\n" },
David Brazdil8d5b8b22015-03-24 10:51:52 +0000126 { " 10: SuspendCheck\n", " 10: SuspendCheck\n"
127 " 12: IntConstant [8]\n" },
128 { " 5: Neg(2) [8]\n", removed },
Roland Levillain9240d6a2014-10-20 16:47:04 +0100129 { " 8: Return(5)\n", " 8: Return(12)\n" }
130 };
131 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
132
133 // Check the value of the computed constant.
134 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100135 HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
Roland Levillain9240d6a2014-10-20 16:47:04 +0100136 ASSERT_TRUE(inst->IsIntConstant());
137 ASSERT_EQ(inst->AsIntConstant()->GetValue(), -1);
138 };
139
140 // Expected difference after dead code elimination.
141 diff_t expected_dce_diff = {
142 { " 2: IntConstant\n", removed },
143 };
144 std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
145
146 TestCode(data,
147 expected_before,
148 expected_after_cf,
149 expected_after_dce,
150 check_after_cf);
151}
152
153/**
Roland Levillainc90bc7c2014-12-11 12:14:33 +0000154 * Tiny three-register program exercising long constant folding on negation.
155 *
156 * 16-bit
157 * offset
158 * ------
159 * (v0, v1) <- 4294967296 0. const-wide v0 #+4294967296
160 * (v2, v3) <- -(v0, v1) 1. neg-long v2, v0
161 * return (v2, v3) 2. return-wide v2
162 */
Aart Bik96709f12015-10-28 17:49:07 -0700163TEST_F(ConstantFoldingTest, LongConstantFoldingNegation) {
Roland Levillainc90bc7c2014-12-11 12:14:33 +0000164 const int64_t input = INT64_C(4294967296); // 2^32
165 const uint16_t word0 = Low16Bits(Low32Bits(input)); // LSW.
166 const uint16_t word1 = High16Bits(Low32Bits(input));
167 const uint16_t word2 = Low16Bits(High32Bits(input));
168 const uint16_t word3 = High16Bits(High32Bits(input)); // MSW.
169 const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(
170 Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
171 Instruction::NEG_LONG | 2 << 8 | 0 << 12,
172 Instruction::RETURN_WIDE | 2 << 8);
173
174 std::string expected_before =
175 "BasicBlock 0, succ: 1\n"
176 " 4: LongConstant [7]\n"
177 " 12: SuspendCheck\n"
178 " 13: Goto 1\n"
179 "BasicBlock 1, pred: 0, succ: 2\n"
180 " 7: Neg(4) [10]\n"
181 " 10: Return(7)\n"
182 "BasicBlock 2, pred: 1\n"
183 " 11: Exit\n";
184
185 // Expected difference after constant folding.
186 diff_t expected_cf_diff = {
187 { " 4: LongConstant [7]\n", " 4: LongConstant\n" },
188 { " 12: SuspendCheck\n", " 12: SuspendCheck\n"
189 " 14: LongConstant [10]\n" },
190 { " 7: Neg(4) [10]\n", removed },
191 { " 10: Return(7)\n", " 10: Return(14)\n" }
192 };
193 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
194
195 // Check the value of the computed constant.
196 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100197 HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
Roland Levillainc90bc7c2014-12-11 12:14:33 +0000198 ASSERT_TRUE(inst->IsLongConstant());
199 ASSERT_EQ(inst->AsLongConstant()->GetValue(), INT64_C(-4294967296));
200 };
201
202 // Expected difference after dead code elimination.
203 diff_t expected_dce_diff = {
204 { " 4: LongConstant\n", removed },
205 };
206 std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
207
208 TestCode(data,
209 expected_before,
210 expected_after_cf,
211 expected_after_dce,
212 check_after_cf,
213 Primitive::kPrimLong);
214}
215
216/**
Roland Levillain556c3d12014-09-18 15:25:07 +0100217 * Tiny three-register program exercising int constant folding on addition.
218 *
219 * 16-bit
220 * offset
221 * ------
222 * v0 <- 1 0. const/4 v0, #+1
223 * v1 <- 2 1. const/4 v1, #+2
224 * v2 <- v0 + v1 2. add-int v2, v0, v1
225 * return v2 4. return v2
226 */
Aart Bik96709f12015-10-28 17:49:07 -0700227TEST_F(ConstantFoldingTest, IntConstantFoldingOnAddition1) {
Roland Levillain556c3d12014-09-18 15:25:07 +0100228 const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
229 Instruction::CONST_4 | 0 << 8 | 1 << 12,
230 Instruction::CONST_4 | 1 << 8 | 2 << 12,
231 Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
232 Instruction::RETURN | 2 << 8);
233
234 std::string expected_before =
235 "BasicBlock 0, succ: 1\n"
236 " 3: IntConstant [9]\n"
237 " 5: IntConstant [9]\n"
238 " 14: SuspendCheck\n"
239 " 15: Goto 1\n"
240 "BasicBlock 1, pred: 0, succ: 2\n"
241 " 9: Add(3, 5) [12]\n"
242 " 12: Return(9)\n"
243 "BasicBlock 2, pred: 1\n"
244 " 13: Exit\n";
245
Roland Levillain75be2832014-10-17 17:02:00 +0100246 // Expected difference after constant folding.
247 diff_t expected_cf_diff = {
Roland Levillain556c3d12014-09-18 15:25:07 +0100248 { " 3: IntConstant [9]\n", " 3: IntConstant\n" },
249 { " 5: IntConstant [9]\n", " 5: IntConstant\n" },
David Brazdil8d5b8b22015-03-24 10:51:52 +0000250 { " 14: SuspendCheck\n", " 14: SuspendCheck\n"
251 " 16: IntConstant [12]\n" },
252 { " 9: Add(3, 5) [12]\n", removed },
Roland Levillain556c3d12014-09-18 15:25:07 +0100253 { " 12: Return(9)\n", " 12: Return(16)\n" }
254 };
Roland Levillain75be2832014-10-17 17:02:00 +0100255 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100256
Roland Levillain93445682014-10-06 19:24:02 +0100257 // Check the value of the computed constant.
Roland Levillain75be2832014-10-17 17:02:00 +0100258 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100259 HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
Roland Levillain93445682014-10-06 19:24:02 +0100260 ASSERT_TRUE(inst->IsIntConstant());
261 ASSERT_EQ(inst->AsIntConstant()->GetValue(), 3);
262 };
263
Roland Levillain556c3d12014-09-18 15:25:07 +0100264 // Expected difference after dead code elimination.
265 diff_t expected_dce_diff = {
266 { " 3: IntConstant\n", removed },
267 { " 5: IntConstant\n", removed }
268 };
Roland Levillain75be2832014-10-17 17:02:00 +0100269 std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100270
Roland Levillain93445682014-10-06 19:24:02 +0100271 TestCode(data,
272 expected_before,
Roland Levillain75be2832014-10-17 17:02:00 +0100273 expected_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100274 expected_after_dce,
Roland Levillain75be2832014-10-17 17:02:00 +0100275 check_after_cf);
Roland Levillain556c3d12014-09-18 15:25:07 +0100276}
277
278/**
279 * Small three-register program exercising int constant folding on addition.
280 *
281 * 16-bit
282 * offset
283 * ------
284 * v0 <- 1 0. const/4 v0, #+1
285 * v1 <- 2 1. const/4 v1, #+2
286 * v0 <- v0 + v1 2. add-int/2addr v0, v1
David Brazdil8d5b8b22015-03-24 10:51:52 +0000287 * v1 <- 4 3. const/4 v1, #+4
288 * v2 <- 5 4. const/4 v2, #+5
Roland Levillain556c3d12014-09-18 15:25:07 +0100289 * v1 <- v1 + v2 5. add-int/2addr v1, v2
290 * v2 <- v0 + v1 6. add-int v2, v0, v1
291 * return v2 8. return v2
292 */
Aart Bik96709f12015-10-28 17:49:07 -0700293TEST_F(ConstantFoldingTest, IntConstantFoldingOnAddition2) {
Roland Levillain556c3d12014-09-18 15:25:07 +0100294 const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
295 Instruction::CONST_4 | 0 << 8 | 1 << 12,
296 Instruction::CONST_4 | 1 << 8 | 2 << 12,
297 Instruction::ADD_INT_2ADDR | 0 << 8 | 1 << 12,
David Brazdil8d5b8b22015-03-24 10:51:52 +0000298 Instruction::CONST_4 | 1 << 8 | 4 << 12,
299 Instruction::CONST_4 | 2 << 8 | 5 << 12,
Roland Levillain556c3d12014-09-18 15:25:07 +0100300 Instruction::ADD_INT_2ADDR | 1 << 8 | 2 << 12,
301 Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
302 Instruction::RETURN | 2 << 8);
303
304 std::string expected_before =
305 "BasicBlock 0, succ: 1\n"
306 " 3: IntConstant [9]\n"
307 " 5: IntConstant [9]\n"
308 " 11: IntConstant [17]\n"
309 " 13: IntConstant [17]\n"
310 " 26: SuspendCheck\n"
311 " 27: Goto 1\n"
312 "BasicBlock 1, pred: 0, succ: 2\n"
313 " 9: Add(3, 5) [21]\n"
314 " 17: Add(11, 13) [21]\n"
315 " 21: Add(9, 17) [24]\n"
316 " 24: Return(21)\n"
317 "BasicBlock 2, pred: 1\n"
318 " 25: Exit\n";
319
Roland Levillain75be2832014-10-17 17:02:00 +0100320 // Expected difference after constant folding.
321 diff_t expected_cf_diff = {
Roland Levillain556c3d12014-09-18 15:25:07 +0100322 { " 3: IntConstant [9]\n", " 3: IntConstant\n" },
323 { " 5: IntConstant [9]\n", " 5: IntConstant\n" },
324 { " 11: IntConstant [17]\n", " 11: IntConstant\n" },
325 { " 13: IntConstant [17]\n", " 13: IntConstant\n" },
David Brazdil8d5b8b22015-03-24 10:51:52 +0000326 { " 26: SuspendCheck\n", " 26: SuspendCheck\n"
327 " 28: IntConstant\n"
328 " 29: IntConstant\n"
329 " 30: IntConstant [24]\n" },
330 { " 9: Add(3, 5) [21]\n", removed },
331 { " 17: Add(11, 13) [21]\n", removed },
332 { " 21: Add(9, 17) [24]\n", removed },
Roland Levillain556c3d12014-09-18 15:25:07 +0100333 { " 24: Return(21)\n", " 24: Return(30)\n" }
334 };
Roland Levillain75be2832014-10-17 17:02:00 +0100335 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100336
Roland Levillain93445682014-10-06 19:24:02 +0100337 // Check the values of the computed constants.
Roland Levillain75be2832014-10-17 17:02:00 +0100338 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100339 HInstruction* inst1 = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
Roland Levillain93445682014-10-06 19:24:02 +0100340 ASSERT_TRUE(inst1->IsIntConstant());
David Brazdil8d5b8b22015-03-24 10:51:52 +0000341 ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 12);
342 HInstruction* inst2 = inst1->GetPrevious();
Roland Levillain93445682014-10-06 19:24:02 +0100343 ASSERT_TRUE(inst2->IsIntConstant());
David Brazdil8d5b8b22015-03-24 10:51:52 +0000344 ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 9);
345 HInstruction* inst3 = inst2->GetPrevious();
Roland Levillain93445682014-10-06 19:24:02 +0100346 ASSERT_TRUE(inst3->IsIntConstant());
David Brazdil8d5b8b22015-03-24 10:51:52 +0000347 ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 3);
Roland Levillain93445682014-10-06 19:24:02 +0100348 };
349
Roland Levillain556c3d12014-09-18 15:25:07 +0100350 // Expected difference after dead code elimination.
351 diff_t expected_dce_diff = {
352 { " 3: IntConstant\n", removed },
353 { " 5: IntConstant\n", removed },
354 { " 11: IntConstant\n", removed },
355 { " 13: IntConstant\n", removed },
356 { " 28: IntConstant\n", removed },
357 { " 29: IntConstant\n", removed }
358 };
Roland Levillain75be2832014-10-17 17:02:00 +0100359 std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100360
Roland Levillain93445682014-10-06 19:24:02 +0100361 TestCode(data,
362 expected_before,
Roland Levillain75be2832014-10-17 17:02:00 +0100363 expected_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100364 expected_after_dce,
Roland Levillain75be2832014-10-17 17:02:00 +0100365 check_after_cf);
Roland Levillain556c3d12014-09-18 15:25:07 +0100366}
367
368/**
369 * Tiny three-register program exercising int constant folding on subtraction.
370 *
371 * 16-bit
372 * offset
373 * ------
374 * v0 <- 3 0. const/4 v0, #+3
375 * v1 <- 2 1. const/4 v1, #+2
376 * v2 <- v0 - v1 2. sub-int v2, v0, v1
377 * return v2 4. return v2
378 */
Aart Bik96709f12015-10-28 17:49:07 -0700379TEST_F(ConstantFoldingTest, IntConstantFoldingOnSubtraction) {
Roland Levillain556c3d12014-09-18 15:25:07 +0100380 const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
381 Instruction::CONST_4 | 0 << 8 | 3 << 12,
382 Instruction::CONST_4 | 1 << 8 | 2 << 12,
383 Instruction::SUB_INT | 2 << 8, 0 | 1 << 8,
384 Instruction::RETURN | 2 << 8);
385
386 std::string expected_before =
387 "BasicBlock 0, succ: 1\n"
388 " 3: IntConstant [9]\n"
389 " 5: IntConstant [9]\n"
390 " 14: SuspendCheck\n"
391 " 15: Goto 1\n"
392 "BasicBlock 1, pred: 0, succ: 2\n"
393 " 9: Sub(3, 5) [12]\n"
394 " 12: Return(9)\n"
395 "BasicBlock 2, pred: 1\n"
396 " 13: Exit\n";
397
Roland Levillain75be2832014-10-17 17:02:00 +0100398 // Expected difference after constant folding.
399 diff_t expected_cf_diff = {
Roland Levillain556c3d12014-09-18 15:25:07 +0100400 { " 3: IntConstant [9]\n", " 3: IntConstant\n" },
401 { " 5: IntConstant [9]\n", " 5: IntConstant\n" },
David Brazdil8d5b8b22015-03-24 10:51:52 +0000402 { " 14: SuspendCheck\n", " 14: SuspendCheck\n"
403 " 16: IntConstant [12]\n" },
404 { " 9: Sub(3, 5) [12]\n", removed },
Roland Levillain556c3d12014-09-18 15:25:07 +0100405 { " 12: Return(9)\n", " 12: Return(16)\n" }
406 };
Roland Levillain75be2832014-10-17 17:02:00 +0100407 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100408
Roland Levillain93445682014-10-06 19:24:02 +0100409 // Check the value of the computed constant.
Roland Levillain75be2832014-10-17 17:02:00 +0100410 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100411 HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
Roland Levillain93445682014-10-06 19:24:02 +0100412 ASSERT_TRUE(inst->IsIntConstant());
413 ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
414 };
415
Roland Levillain556c3d12014-09-18 15:25:07 +0100416 // Expected difference after dead code elimination.
417 diff_t expected_dce_diff = {
418 { " 3: IntConstant\n", removed },
419 { " 5: IntConstant\n", removed }
420 };
Roland Levillain75be2832014-10-17 17:02:00 +0100421 std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100422
Roland Levillain93445682014-10-06 19:24:02 +0100423 TestCode(data,
424 expected_before,
Roland Levillain75be2832014-10-17 17:02:00 +0100425 expected_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100426 expected_after_dce,
Roland Levillain75be2832014-10-17 17:02:00 +0100427 check_after_cf);
Roland Levillain556c3d12014-09-18 15:25:07 +0100428}
429
Roland Levillain556c3d12014-09-18 15:25:07 +0100430/**
431 * Tiny three-register-pair program exercising long constant folding
432 * on addition.
433 *
434 * 16-bit
435 * offset
436 * ------
437 * (v0, v1) <- 1 0. const-wide/16 v0, #+1
438 * (v2, v3) <- 2 2. const-wide/16 v2, #+2
439 * (v4, v5) <-
440 * (v0, v1) + (v1, v2) 4. add-long v4, v0, v2
441 * return (v4, v5) 6. return-wide v4
442 */
Aart Bik96709f12015-10-28 17:49:07 -0700443TEST_F(ConstantFoldingTest, LongConstantFoldingOnAddition) {
Roland Levillain556c3d12014-09-18 15:25:07 +0100444 const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
445 Instruction::CONST_WIDE_16 | 0 << 8, 1,
446 Instruction::CONST_WIDE_16 | 2 << 8, 2,
447 Instruction::ADD_LONG | 4 << 8, 0 | 2 << 8,
448 Instruction::RETURN_WIDE | 4 << 8);
449
450 std::string expected_before =
451 "BasicBlock 0, succ: 1\n"
452 " 6: LongConstant [12]\n"
453 " 8: LongConstant [12]\n"
454 " 17: SuspendCheck\n"
455 " 18: Goto 1\n"
456 "BasicBlock 1, pred: 0, succ: 2\n"
457 " 12: Add(6, 8) [15]\n"
458 " 15: Return(12)\n"
459 "BasicBlock 2, pred: 1\n"
460 " 16: Exit\n";
461
Roland Levillain75be2832014-10-17 17:02:00 +0100462 // Expected difference after constant folding.
463 diff_t expected_cf_diff = {
Roland Levillain556c3d12014-09-18 15:25:07 +0100464 { " 6: LongConstant [12]\n", " 6: LongConstant\n" },
465 { " 8: LongConstant [12]\n", " 8: LongConstant\n" },
David Brazdil8d5b8b22015-03-24 10:51:52 +0000466 { " 17: SuspendCheck\n", " 17: SuspendCheck\n"
467 " 19: LongConstant [15]\n" },
468 { " 12: Add(6, 8) [15]\n", removed },
Roland Levillain556c3d12014-09-18 15:25:07 +0100469 { " 15: Return(12)\n", " 15: Return(19)\n" }
470 };
Roland Levillain75be2832014-10-17 17:02:00 +0100471 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100472
Roland Levillain93445682014-10-06 19:24:02 +0100473 // Check the value of the computed constant.
Roland Levillain75be2832014-10-17 17:02:00 +0100474 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100475 HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
Roland Levillain93445682014-10-06 19:24:02 +0100476 ASSERT_TRUE(inst->IsLongConstant());
477 ASSERT_EQ(inst->AsLongConstant()->GetValue(), 3);
478 };
479
Roland Levillain556c3d12014-09-18 15:25:07 +0100480 // Expected difference after dead code elimination.
481 diff_t expected_dce_diff = {
482 { " 6: LongConstant\n", removed },
483 { " 8: LongConstant\n", removed }
484 };
Roland Levillain75be2832014-10-17 17:02:00 +0100485 std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100486
Roland Levillain93445682014-10-06 19:24:02 +0100487 TestCode(data,
488 expected_before,
Roland Levillain75be2832014-10-17 17:02:00 +0100489 expected_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100490 expected_after_dce,
Roland Levillain75be2832014-10-17 17:02:00 +0100491 check_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100492 Primitive::kPrimLong);
Roland Levillain556c3d12014-09-18 15:25:07 +0100493}
494
495/**
496 * Tiny three-register-pair program exercising long constant folding
497 * on subtraction.
498 *
499 * 16-bit
500 * offset
501 * ------
502 * (v0, v1) <- 3 0. const-wide/16 v0, #+3
503 * (v2, v3) <- 2 2. const-wide/16 v2, #+2
504 * (v4, v5) <-
505 * (v0, v1) - (v1, v2) 4. sub-long v4, v0, v2
506 * return (v4, v5) 6. return-wide v4
507 */
Aart Bik96709f12015-10-28 17:49:07 -0700508TEST_F(ConstantFoldingTest, LongConstantFoldingOnSubtraction) {
Roland Levillain556c3d12014-09-18 15:25:07 +0100509 const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
510 Instruction::CONST_WIDE_16 | 0 << 8, 3,
511 Instruction::CONST_WIDE_16 | 2 << 8, 2,
512 Instruction::SUB_LONG | 4 << 8, 0 | 2 << 8,
513 Instruction::RETURN_WIDE | 4 << 8);
514
515 std::string expected_before =
516 "BasicBlock 0, succ: 1\n"
517 " 6: LongConstant [12]\n"
518 " 8: LongConstant [12]\n"
519 " 17: SuspendCheck\n"
520 " 18: Goto 1\n"
521 "BasicBlock 1, pred: 0, succ: 2\n"
522 " 12: Sub(6, 8) [15]\n"
523 " 15: Return(12)\n"
524 "BasicBlock 2, pred: 1\n"
525 " 16: Exit\n";
526
Roland Levillain75be2832014-10-17 17:02:00 +0100527 // Expected difference after constant folding.
528 diff_t expected_cf_diff = {
Roland Levillain556c3d12014-09-18 15:25:07 +0100529 { " 6: LongConstant [12]\n", " 6: LongConstant\n" },
530 { " 8: LongConstant [12]\n", " 8: LongConstant\n" },
David Brazdil8d5b8b22015-03-24 10:51:52 +0000531 { " 17: SuspendCheck\n", " 17: SuspendCheck\n"
532 " 19: LongConstant [15]\n" },
533 { " 12: Sub(6, 8) [15]\n", removed },
Roland Levillain556c3d12014-09-18 15:25:07 +0100534 { " 15: Return(12)\n", " 15: Return(19)\n" }
535 };
Roland Levillain75be2832014-10-17 17:02:00 +0100536 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100537
Roland Levillain93445682014-10-06 19:24:02 +0100538 // Check the value of the computed constant.
Roland Levillain75be2832014-10-17 17:02:00 +0100539 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100540 HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
Roland Levillain93445682014-10-06 19:24:02 +0100541 ASSERT_TRUE(inst->IsLongConstant());
542 ASSERT_EQ(inst->AsLongConstant()->GetValue(), 1);
543 };
544
Roland Levillain556c3d12014-09-18 15:25:07 +0100545 // Expected difference after dead code elimination.
546 diff_t expected_dce_diff = {
547 { " 6: LongConstant\n", removed },
548 { " 8: LongConstant\n", removed }
549 };
Roland Levillain75be2832014-10-17 17:02:00 +0100550 std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100551
Roland Levillain93445682014-10-06 19:24:02 +0100552 TestCode(data,
553 expected_before,
Roland Levillain75be2832014-10-17 17:02:00 +0100554 expected_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100555 expected_after_dce,
Roland Levillain75be2832014-10-17 17:02:00 +0100556 check_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100557 Primitive::kPrimLong);
Roland Levillain556c3d12014-09-18 15:25:07 +0100558}
559
560/**
561 * Three-register program with jumps leading to the creation of many
562 * blocks.
563 *
564 * The intent of this test is to ensure that all constant expressions
565 * are actually evaluated at compile-time, thanks to the reverse
566 * (forward) post-order traversal of the the dominator tree.
567 *
568 * 16-bit
569 * offset
570 * ------
David Brazdil8d5b8b22015-03-24 10:51:52 +0000571 * v0 <- 1 0. const/4 v0, #+1
572 * v1 <- 2 1. const/4 v1, #+2
Roland Levillain556c3d12014-09-18 15:25:07 +0100573 * v2 <- v0 + v1 2. add-int v2, v0, v1
574 * goto L2 4. goto +4
David Brazdil8d5b8b22015-03-24 10:51:52 +0000575 * L1: v1 <- v0 + 5 5. add-int/lit16 v1, v0, #+5
Roland Levillain556c3d12014-09-18 15:25:07 +0100576 * goto L3 7. goto +4
David Brazdil8d5b8b22015-03-24 10:51:52 +0000577 * L2: v0 <- v2 + 4 8. add-int/lit16 v0, v2, #+4
Roland Levillain556c3d12014-09-18 15:25:07 +0100578 * goto L1 10. goto +(-5)
David Brazdil8d5b8b22015-03-24 10:51:52 +0000579 * L3: v2 <- v1 + 8 11. add-int/lit16 v2, v1, #+8
Roland Levillain556c3d12014-09-18 15:25:07 +0100580 * return v2 13. return v2
581 */
Aart Bik96709f12015-10-28 17:49:07 -0700582TEST_F(ConstantFoldingTest, IntConstantFoldingAndJumps) {
Roland Levillain556c3d12014-09-18 15:25:07 +0100583 const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
David Brazdil8d5b8b22015-03-24 10:51:52 +0000584 Instruction::CONST_4 | 0 << 8 | 1 << 12,
585 Instruction::CONST_4 | 1 << 8 | 2 << 12,
Roland Levillain556c3d12014-09-18 15:25:07 +0100586 Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
587 Instruction::GOTO | 4 << 8,
David Brazdil8d5b8b22015-03-24 10:51:52 +0000588 Instruction::ADD_INT_LIT16 | 1 << 8 | 0 << 12, 5,
Roland Levillain556c3d12014-09-18 15:25:07 +0100589 Instruction::GOTO | 4 << 8,
David Brazdil8d5b8b22015-03-24 10:51:52 +0000590 Instruction::ADD_INT_LIT16 | 0 << 8 | 2 << 12, 4,
Andreas Gampe58554b72015-10-20 21:08:52 -0700591 static_cast<uint16_t>(Instruction::GOTO | 0xFFFFFFFB << 8),
David Brazdil8d5b8b22015-03-24 10:51:52 +0000592 Instruction::ADD_INT_LIT16 | 2 << 8 | 1 << 12, 8,
Roland Levillain556c3d12014-09-18 15:25:07 +0100593 Instruction::RETURN | 2 << 8);
594
595 std::string expected_before =
596 "BasicBlock 0, succ: 1\n"
David Brazdil8d5b8b22015-03-24 10:51:52 +0000597 " 3: IntConstant [9]\n" // v0 <- 1
598 " 5: IntConstant [9]\n" // v1 <- 2
599 " 13: IntConstant [14]\n" // const 5
600 " 18: IntConstant [19]\n" // const 4
601 " 24: IntConstant [25]\n" // const 8
Roland Levillain556c3d12014-09-18 15:25:07 +0100602 " 30: SuspendCheck\n"
603 " 31: Goto 1\n"
604 "BasicBlock 1, pred: 0, succ: 3\n"
David Brazdil8d5b8b22015-03-24 10:51:52 +0000605 " 9: Add(3, 5) [19]\n" // v2 <- v0 + v1 = 1 + 2 = 3
Roland Levillain93445682014-10-06 19:24:02 +0100606 " 11: Goto 3\n" // goto L2
607 "BasicBlock 2, pred: 3, succ: 4\n" // L1:
David Brazdil8d5b8b22015-03-24 10:51:52 +0000608 " 14: Add(19, 13) [25]\n" // v1 <- v0 + 3 = 7 + 5 = 12
Roland Levillain93445682014-10-06 19:24:02 +0100609 " 16: Goto 4\n" // goto L3
610 "BasicBlock 3, pred: 1, succ: 2\n" // L2:
David Brazdil8d5b8b22015-03-24 10:51:52 +0000611 " 19: Add(9, 18) [14]\n" // v0 <- v2 + 2 = 3 + 4 = 7
Roland Levillain556c3d12014-09-18 15:25:07 +0100612 " 21: SuspendCheck\n"
Roland Levillain93445682014-10-06 19:24:02 +0100613 " 22: Goto 2\n" // goto L1
614 "BasicBlock 4, pred: 2, succ: 5\n" // L3:
David Brazdil8d5b8b22015-03-24 10:51:52 +0000615 " 25: Add(14, 24) [28]\n" // v2 <- v1 + 4 = 12 + 8 = 20
Roland Levillain93445682014-10-06 19:24:02 +0100616 " 28: Return(25)\n" // return v2
Roland Levillain556c3d12014-09-18 15:25:07 +0100617 "BasicBlock 5, pred: 4\n"
618 " 29: Exit\n";
619
Roland Levillain75be2832014-10-17 17:02:00 +0100620 // Expected difference after constant folding.
621 diff_t expected_cf_diff = {
Roland Levillain556c3d12014-09-18 15:25:07 +0100622 { " 3: IntConstant [9]\n", " 3: IntConstant\n" },
623 { " 5: IntConstant [9]\n", " 5: IntConstant []\n" },
624 { " 13: IntConstant [14]\n", " 13: IntConstant\n" },
625 { " 18: IntConstant [19]\n", " 18: IntConstant\n" },
626 { " 24: IntConstant [25]\n", " 24: IntConstant\n" },
David Brazdil8d5b8b22015-03-24 10:51:52 +0000627 { " 30: SuspendCheck\n", " 30: SuspendCheck\n"
628 " 32: IntConstant []\n"
629 " 33: IntConstant []\n"
630 " 34: IntConstant\n"
631 " 35: IntConstant [28]\n" },
632 { " 9: Add(3, 5) [19]\n", removed },
633 { " 14: Add(19, 13) [25]\n", removed },
634 { " 19: Add(9, 18) [14]\n", removed },
635 { " 25: Add(14, 24) [28]\n", removed },
Roland Levillain556c3d12014-09-18 15:25:07 +0100636 { " 28: Return(25)\n", " 28: Return(35)\n"}
637 };
Roland Levillain75be2832014-10-17 17:02:00 +0100638 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100639
Roland Levillain93445682014-10-06 19:24:02 +0100640 // Check the values of the computed constants.
Roland Levillain75be2832014-10-17 17:02:00 +0100641 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100642 HInstruction* inst1 = graph->GetBlocks()[4]->GetFirstInstruction()->InputAt(0);
Roland Levillain93445682014-10-06 19:24:02 +0100643 ASSERT_TRUE(inst1->IsIntConstant());
David Brazdil8d5b8b22015-03-24 10:51:52 +0000644 ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 20);
645 HInstruction* inst2 = inst1->GetPrevious();
Roland Levillain93445682014-10-06 19:24:02 +0100646 ASSERT_TRUE(inst2->IsIntConstant());
David Brazdil8d5b8b22015-03-24 10:51:52 +0000647 ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 12);
648 HInstruction* inst3 = inst2->GetPrevious();
Roland Levillain93445682014-10-06 19:24:02 +0100649 ASSERT_TRUE(inst3->IsIntConstant());
David Brazdil8d5b8b22015-03-24 10:51:52 +0000650 ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 7);
651 HInstruction* inst4 = inst3->GetPrevious();
Roland Levillain93445682014-10-06 19:24:02 +0100652 ASSERT_TRUE(inst4->IsIntConstant());
David Brazdil8d5b8b22015-03-24 10:51:52 +0000653 ASSERT_EQ(inst4->AsIntConstant()->GetValue(), 3);
Roland Levillain93445682014-10-06 19:24:02 +0100654 };
655
Roland Levillain556c3d12014-09-18 15:25:07 +0100656 // Expected difference after dead code elimination.
David Brazdil1c533c12015-04-24 17:04:38 +0100657 std::string expected_after_dce =
658 "BasicBlock 0, succ: 1\n"
659 " 5: IntConstant []\n"
660 " 30: SuspendCheck\n"
661 " 32: IntConstant []\n"
662 " 33: IntConstant []\n"
663 " 35: IntConstant [28]\n"
664 " 31: Goto 1\n"
665 "BasicBlock 1, pred: 0, succ: 5\n"
666 " 21: SuspendCheck\n"
667 " 28: Return(35)\n"
668 "BasicBlock 5, pred: 1\n"
669 " 29: Exit\n";
Roland Levillain556c3d12014-09-18 15:25:07 +0100670
Roland Levillain93445682014-10-06 19:24:02 +0100671 TestCode(data,
672 expected_before,
Roland Levillain75be2832014-10-17 17:02:00 +0100673 expected_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100674 expected_after_dce,
Roland Levillain75be2832014-10-17 17:02:00 +0100675 check_after_cf);
Roland Levillain556c3d12014-09-18 15:25:07 +0100676}
677
Roland Levillain556c3d12014-09-18 15:25:07 +0100678/**
679 * Three-register program with a constant (static) condition.
680 *
681 * 16-bit
682 * offset
683 * ------
684 * v1 <- 1 0. const/4 v1, #+1
685 * v0 <- 0 1. const/4 v0, #+0
686 * if v1 >= 0 goto L1 2. if-gez v1, +3
687 * v0 <- v1 4. move v0, v1
688 * L1: v2 <- v0 + v1 5. add-int v2, v0, v1
689 * return-void 7. return
690 */
Aart Bik96709f12015-10-28 17:49:07 -0700691TEST_F(ConstantFoldingTest, ConstantCondition) {
Roland Levillain556c3d12014-09-18 15:25:07 +0100692 const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
693 Instruction::CONST_4 | 1 << 8 | 1 << 12,
694 Instruction::CONST_4 | 0 << 8 | 0 << 12,
695 Instruction::IF_GEZ | 1 << 8, 3,
696 Instruction::MOVE | 0 << 8 | 1 << 12,
697 Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
698 Instruction::RETURN_VOID);
699
700 std::string expected_before =
701 "BasicBlock 0, succ: 1\n"
702 " 3: IntConstant [15, 22, 8]\n"
703 " 5: IntConstant [22, 8]\n"
704 " 19: SuspendCheck\n"
705 " 20: Goto 1\n"
706 "BasicBlock 1, pred: 0, succ: 5, 2\n"
707 " 8: GreaterThanOrEqual(3, 5) [9]\n"
708 " 9: If(8)\n"
709 "BasicBlock 2, pred: 1, succ: 3\n"
710 " 12: Goto 3\n"
Nicolas Geoffray8b20f882015-06-19 16:17:05 +0100711 "BasicBlock 3, pred: 5, 2, succ: 4\n"
712 " 22: Phi(5, 3) [15]\n"
Roland Levillain556c3d12014-09-18 15:25:07 +0100713 " 15: Add(22, 3)\n"
714 " 17: ReturnVoid\n"
715 "BasicBlock 4, pred: 3\n"
716 " 18: Exit\n"
717 "BasicBlock 5, pred: 1, succ: 3\n"
718 " 21: Goto 3\n";
719
Roland Levillain75be2832014-10-17 17:02:00 +0100720 // Expected difference after constant folding.
721 diff_t expected_cf_diff = {
David Brazdil8d5b8b22015-03-24 10:51:52 +0000722 { " 3: IntConstant [15, 22, 8]\n", " 3: IntConstant [9, 15, 22]\n" },
Roland Levillain556c3d12014-09-18 15:25:07 +0100723 { " 5: IntConstant [22, 8]\n", " 5: IntConstant [22]\n" },
David Brazdil8d5b8b22015-03-24 10:51:52 +0000724 { " 8: GreaterThanOrEqual(3, 5) [9]\n", removed },
725 { " 9: If(8)\n", " 9: If(3)\n" }
Roland Levillain556c3d12014-09-18 15:25:07 +0100726 };
Roland Levillain75be2832014-10-17 17:02:00 +0100727 std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
Roland Levillain556c3d12014-09-18 15:25:07 +0100728
Roland Levillain93445682014-10-06 19:24:02 +0100729 // Check the values of the computed constants.
Roland Levillain75be2832014-10-17 17:02:00 +0100730 auto check_after_cf = [](HGraph* graph) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100731 HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
Roland Levillain93445682014-10-06 19:24:02 +0100732 ASSERT_TRUE(inst->IsIntConstant());
733 ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
734 };
735
David Brazdil1c533c12015-04-24 17:04:38 +0100736 // Expected graph after dead code elimination.
737 std::string expected_after_dce =
738 "BasicBlock 0, succ: 1\n"
739 " 19: SuspendCheck\n"
740 " 20: Goto 1\n"
741 "BasicBlock 1, pred: 0, succ: 4\n"
742 " 17: ReturnVoid\n"
743 "BasicBlock 4, pred: 1\n"
744 " 18: Exit\n";
Roland Levillain556c3d12014-09-18 15:25:07 +0100745
Roland Levillain93445682014-10-06 19:24:02 +0100746 TestCode(data,
747 expected_before,
Roland Levillain75be2832014-10-17 17:02:00 +0100748 expected_after_cf,
Roland Levillain93445682014-10-06 19:24:02 +0100749 expected_after_dce,
Roland Levillain75be2832014-10-17 17:02:00 +0100750 check_after_cf);
Roland Levillain556c3d12014-09-18 15:25:07 +0100751}
752
Aart Bik96709f12015-10-28 17:49:07 -0700753/**
754 * Unsigned comparisons with zero. Since these instructions are not present
755 * in the bytecode, we need to set up the graph explicitly.
756 */
757TEST_F(ConstantFoldingTest, UnsignedComparisonsWithZero) {
758 graph_ = CreateGraph(&allocator_);
759 HBasicBlock* entry_block = new (&allocator_) HBasicBlock(graph_);
760 graph_->AddBlock(entry_block);
761 graph_->SetEntryBlock(entry_block);
762 HBasicBlock* block = new (&allocator_) HBasicBlock(graph_);
763 graph_->AddBlock(block);
764 HBasicBlock* exit_block = new (&allocator_) HBasicBlock(graph_);
765 graph_->AddBlock(exit_block);
766 graph_->SetExitBlock(exit_block);
767 entry_block->AddSuccessor(block);
768 block->AddSuccessor(exit_block);
769
770 // Make various unsigned comparisons with zero against a parameter.
771 HInstruction* parameter = new (&allocator_) HParameterValue(
772 graph_->GetDexFile(), 0, 0, Primitive::kPrimInt, true);
773 entry_block->AddInstruction(parameter);
774 HInstruction* zero = graph_->GetIntConstant(0);
775 HInstruction* last;
776 block->AddInstruction(last = new (&allocator_) HAbove(zero, parameter));
David Brazdilbadd8262016-02-02 16:28:56 +0000777 block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
Aart Bik96709f12015-10-28 17:49:07 -0700778 block->AddInstruction(last = new (&allocator_) HAbove(parameter, zero));
David Brazdilbadd8262016-02-02 16:28:56 +0000779 block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
Aart Bik96709f12015-10-28 17:49:07 -0700780 block->AddInstruction(last = new (&allocator_) HAboveOrEqual(zero, parameter));
David Brazdilbadd8262016-02-02 16:28:56 +0000781 block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
Aart Bik96709f12015-10-28 17:49:07 -0700782 block->AddInstruction(last = new (&allocator_) HAboveOrEqual(parameter, zero));
David Brazdilbadd8262016-02-02 16:28:56 +0000783 block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
Aart Bik96709f12015-10-28 17:49:07 -0700784 block->AddInstruction(last = new (&allocator_) HBelow(zero, parameter));
David Brazdilbadd8262016-02-02 16:28:56 +0000785 block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
Aart Bik96709f12015-10-28 17:49:07 -0700786 block->AddInstruction(last = new (&allocator_) HBelow(parameter, zero));
David Brazdilbadd8262016-02-02 16:28:56 +0000787 block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
Aart Bik96709f12015-10-28 17:49:07 -0700788 block->AddInstruction(last = new (&allocator_) HBelowOrEqual(zero, parameter));
David Brazdilbadd8262016-02-02 16:28:56 +0000789 block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
Aart Bik96709f12015-10-28 17:49:07 -0700790 block->AddInstruction(last = new (&allocator_) HBelowOrEqual(parameter, zero));
David Brazdilbadd8262016-02-02 16:28:56 +0000791 block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
Aart Bik96709f12015-10-28 17:49:07 -0700792
793 entry_block->AddInstruction(new (&allocator_) HGoto());
794 block->AddInstruction(new (&allocator_) HReturn(zero));
795 exit_block->AddInstruction(new (&allocator_) HExit());
796
David Brazdilbadd8262016-02-02 16:28:56 +0000797 graph_->BuildDominatorTree();
798
Aart Bik96709f12015-10-28 17:49:07 -0700799 const std::string expected_before =
800 "BasicBlock 0, succ: 1\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000801 " 0: ParameterValue [17, 17, 16, 15, 15, 14, 13, 13, 12, 11, 11, 10, 9, 9, "
802 "8, 7, 7, 6, 5, 5, 4, 3, 3, 2]\n"
Aart Bik96709f12015-10-28 17:49:07 -0700803 " 1: IntConstant [19, 16, 14, 12, 10, 8, 6, 4, 2]\n"
804 " 18: Goto 1\n"
805 "BasicBlock 1, pred: 0, succ: 2\n"
806 " 2: Above(1, 0) [3]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000807 " 3: Select(0, 0, 2)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700808 " 4: Above(0, 1) [5]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000809 " 5: Select(0, 0, 4)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700810 " 6: AboveOrEqual(1, 0) [7]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000811 " 7: Select(0, 0, 6)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700812 " 8: AboveOrEqual(0, 1) [9]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000813 " 9: Select(0, 0, 8)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700814 " 10: Below(1, 0) [11]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000815 " 11: Select(0, 0, 10)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700816 " 12: Below(0, 1) [13]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000817 " 13: Select(0, 0, 12)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700818 " 14: BelowOrEqual(1, 0) [15]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000819 " 15: Select(0, 0, 14)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700820 " 16: BelowOrEqual(0, 1) [17]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000821 " 17: Select(0, 0, 16)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700822 " 19: Return(1)\n"
823 "BasicBlock 2, pred: 1\n"
824 " 20: Exit\n";
825
826 const std::string expected_after_cf =
827 "BasicBlock 0, succ: 1\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000828 " 0: ParameterValue [17, 17, 16, 15, 15, 13, 13, 11, 11, 10, 9, 9, 7, 7, 6, 5, 5, 4, 3, 3]\n"
Aart Bik96709f12015-10-28 17:49:07 -0700829 " 1: IntConstant [13, 3, 19, 16, 10, 6, 4]\n"
830 " 21: IntConstant [15, 9]\n"
831 " 18: Goto 1\n"
832 "BasicBlock 1, pred: 0, succ: 2\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000833 " 3: Select(0, 0, 1)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700834 " 4: Above(0, 1) [5]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000835 " 5: Select(0, 0, 4)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700836 " 6: AboveOrEqual(1, 0) [7]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000837 " 7: Select(0, 0, 6)\n"
838 " 9: Select(0, 0, 21)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700839 " 10: Below(1, 0) [11]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000840 " 11: Select(0, 0, 10)\n"
841 " 13: Select(0, 0, 1)\n"
842 " 15: Select(0, 0, 21)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700843 " 16: BelowOrEqual(0, 1) [17]\n"
David Brazdilbadd8262016-02-02 16:28:56 +0000844 " 17: Select(0, 0, 16)\n"
Aart Bik96709f12015-10-28 17:49:07 -0700845 " 19: Return(1)\n"
846 "BasicBlock 2, pred: 1\n"
847 " 20: Exit\n";
848
David Brazdilbadd8262016-02-02 16:28:56 +0000849 const std::string expected_after_dce =
850 "BasicBlock 0, succ: 1\n"
851 " 0: ParameterValue\n"
852 " 1: IntConstant [19]\n"
853 " 18: Goto 1\n"
854 "BasicBlock 1, pred: 0, succ: 2\n"
855 " 19: Return(1)\n"
856 "BasicBlock 2, pred: 1\n"
857 " 20: Exit\n";
Aart Bik96709f12015-10-28 17:49:07 -0700858
859 auto check_after_cf = [](HGraph* graph) {
860 CHECK(graph != nullptr);
861 };
862
863 TestCodeOnReadyGraph(expected_before,
864 expected_after_cf,
865 expected_after_dce,
866 check_after_cf);
867}
868
Roland Levillain556c3d12014-09-18 15:25:07 +0100869} // namespace art