blob: f8d37bd714ceb30faf50ea7d2474570745588701 [file] [log] [blame]
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +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
Mathieu Chartierb666f482015-02-18 14:33:14 -080017#include "base/arena_allocator.h"
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010018#include "builder.h"
19#include "gvn.h"
20#include "nodes.h"
21#include "optimizing_unit_test.h"
Nicolas Geoffray827eedb2015-01-26 15:18:36 +000022#include "side_effects_analysis.h"
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010023
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010024namespace art {
25
David Brazdil4833f5a2015-12-16 10:37:39 +000026class GVNTest : public CommonCompilerTest {};
27
28TEST_F(GVNTest, LocalFieldElimination) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010029 ArenaPool pool;
30 ArenaAllocator allocator(&pool);
31
Nicolas Geoffray0a23d742015-05-07 11:57:35 +010032 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010033 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
34 graph->AddBlock(entry);
35 graph->SetEntryBlock(entry);
Calin Juravlee6e3bea2015-10-14 13:53:10 +000036 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -080037 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +000038 0,
39 Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010040 entry->AddInstruction(parameter);
41
42 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
43 graph->AddBlock(block);
44 entry->AddSuccessor(block);
45
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010046 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000047 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010048 Primitive::kPrimNot,
49 MemberOffset(42),
50 false,
51 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070052 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070053 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010054 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010055 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000056 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010057 Primitive::kPrimNot,
58 MemberOffset(42),
59 false,
60 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070061 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070062 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010063 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010064 HInstruction* to_remove = block->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010065 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000066 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010067 Primitive::kPrimNot,
68 MemberOffset(43),
69 false,
70 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070071 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070072 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010073 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010074 HInstruction* different_offset = block->GetLastInstruction();
75 // Kill the value.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010076 block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
77 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000078 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010079 Primitive::kPrimNot,
80 MemberOffset(42),
81 false,
82 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070083 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070084 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010085 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010086 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000087 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010088 Primitive::kPrimNot,
89 MemberOffset(42),
90 false,
91 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070092 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070093 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010094 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010095 HInstruction* use_after_kill = block->GetLastInstruction();
96 block->AddInstruction(new (&allocator) HExit());
97
98 ASSERT_EQ(to_remove->GetBlock(), block);
99 ASSERT_EQ(different_offset->GetBlock(), block);
100 ASSERT_EQ(use_after_kill->GetBlock(), block);
101
David Brazdilbadd8262016-02-02 16:28:56 +0000102 graph->BuildDominatorTree();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000103 SideEffectsAnalysis side_effects(graph);
104 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000105 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100106
107 ASSERT_TRUE(to_remove->GetBlock() == nullptr);
108 ASSERT_EQ(different_offset->GetBlock(), block);
109 ASSERT_EQ(use_after_kill->GetBlock(), block);
110}
111
David Brazdil4833f5a2015-12-16 10:37:39 +0000112TEST_F(GVNTest, GlobalFieldElimination) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100113 ArenaPool pool;
114 ArenaAllocator allocator(&pool);
115
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100116 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100117 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
118 graph->AddBlock(entry);
119 graph->SetEntryBlock(entry);
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000120 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800121 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000122 0,
123 Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100124 entry->AddInstruction(parameter);
125
126 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
127 graph->AddBlock(block);
128 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100129 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000130 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100131 Primitive::kPrimBoolean,
132 MemberOffset(42),
133 false,
134 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700135 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700136 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100137 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100138
139 block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
140 HBasicBlock* then = new (&allocator) HBasicBlock(graph);
141 HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
142 HBasicBlock* join = new (&allocator) HBasicBlock(graph);
143 graph->AddBlock(then);
144 graph->AddBlock(else_);
145 graph->AddBlock(join);
146
147 block->AddSuccessor(then);
148 block->AddSuccessor(else_);
149 then->AddSuccessor(join);
150 else_->AddSuccessor(join);
151
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100152 then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000153 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100154 Primitive::kPrimBoolean,
155 MemberOffset(42),
156 false,
157 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700158 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700159 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100160 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100161 then->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100162 else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000163 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100164 Primitive::kPrimBoolean,
165 MemberOffset(42),
166 false,
167 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700168 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700169 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100170 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100171 else_->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100172 join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000173 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100174 Primitive::kPrimBoolean,
175 MemberOffset(42),
176 false,
177 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700178 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700179 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100180 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100181 join->AddInstruction(new (&allocator) HExit());
182
David Brazdilbadd8262016-02-02 16:28:56 +0000183 graph->BuildDominatorTree();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000184 SideEffectsAnalysis side_effects(graph);
185 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000186 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100187
188 // Check that all field get instructions have been GVN'ed.
189 ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
190 ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
191 ASSERT_TRUE(join->GetFirstInstruction()->IsExit());
192}
193
David Brazdil4833f5a2015-12-16 10:37:39 +0000194TEST_F(GVNTest, LoopFieldElimination) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100195 ArenaPool pool;
196 ArenaAllocator allocator(&pool);
197
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100198 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100199 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
200 graph->AddBlock(entry);
201 graph->SetEntryBlock(entry);
202
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000203 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800204 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000205 0,
206 Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100207 entry->AddInstruction(parameter);
208
209 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
210 graph->AddBlock(block);
211 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100212 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000213 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100214 Primitive::kPrimBoolean,
215 MemberOffset(42),
216 false,
217 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700218 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700219 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100220 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100221 block->AddInstruction(new (&allocator) HGoto());
222
223 HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
224 HBasicBlock* loop_body = new (&allocator) HBasicBlock(graph);
225 HBasicBlock* exit = new (&allocator) HBasicBlock(graph);
226
227 graph->AddBlock(loop_header);
228 graph->AddBlock(loop_body);
229 graph->AddBlock(exit);
230 block->AddSuccessor(loop_header);
231 loop_header->AddSuccessor(loop_body);
232 loop_header->AddSuccessor(exit);
233 loop_body->AddSuccessor(loop_header);
234
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100235 loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000236 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100237 Primitive::kPrimBoolean,
238 MemberOffset(42),
239 false,
240 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700241 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700242 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100243 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100244 HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
245 loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
246
247 // Kill inside the loop body to prevent field gets inside the loop header
248 // and the body to be GVN'ed.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100249 loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
250 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000251 nullptr,
Aart Bik854a02b2015-07-14 16:07:00 -0700252 Primitive::kPrimBoolean,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100253 MemberOffset(42),
254 false,
255 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700256 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700257 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100258 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100259 HInstruction* field_set = loop_body->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100260 loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000261 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100262 Primitive::kPrimBoolean,
263 MemberOffset(42),
264 false,
265 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700266 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700267 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100268 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100269 HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
270 loop_body->AddInstruction(new (&allocator) HGoto());
271
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100272 exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000273 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100274 Primitive::kPrimBoolean,
275 MemberOffset(42),
276 false,
277 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700278 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700279 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100280 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100281 HInstruction* field_get_in_exit = exit->GetLastInstruction();
282 exit->AddInstruction(new (&allocator) HExit());
283
284 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
285 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
286 ASSERT_EQ(field_get_in_exit->GetBlock(), exit);
287
David Brazdilbadd8262016-02-02 16:28:56 +0000288 graph->BuildDominatorTree();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000289 {
290 SideEffectsAnalysis side_effects(graph);
291 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000292 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000293 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100294
295 // Check that all field get instructions are still there.
296 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
297 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
298 // The exit block is dominated by the loop header, whose field get
299 // does not get killed by the loop flags.
300 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
301
302 // Now remove the field set, and check that all field get instructions have been GVN'ed.
303 loop_body->RemoveInstruction(field_set);
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000304 {
305 SideEffectsAnalysis side_effects(graph);
306 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000307 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000308 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100309
310 ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr);
311 ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr);
312 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
313}
314
315// Test that inner loops affect the side effects of the outer loop.
David Brazdil4833f5a2015-12-16 10:37:39 +0000316TEST_F(GVNTest, LoopSideEffects) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100317 ArenaPool pool;
318 ArenaAllocator allocator(&pool);
319
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100320 static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();
321
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100322 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100323 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
324 graph->AddBlock(entry);
325 graph->SetEntryBlock(entry);
326
327 HBasicBlock* outer_loop_header = new (&allocator) HBasicBlock(graph);
328 HBasicBlock* outer_loop_body = new (&allocator) HBasicBlock(graph);
329 HBasicBlock* outer_loop_exit = new (&allocator) HBasicBlock(graph);
330 HBasicBlock* inner_loop_header = new (&allocator) HBasicBlock(graph);
331 HBasicBlock* inner_loop_body = new (&allocator) HBasicBlock(graph);
332 HBasicBlock* inner_loop_exit = new (&allocator) HBasicBlock(graph);
333
334 graph->AddBlock(outer_loop_header);
335 graph->AddBlock(outer_loop_body);
336 graph->AddBlock(outer_loop_exit);
337 graph->AddBlock(inner_loop_header);
338 graph->AddBlock(inner_loop_body);
339 graph->AddBlock(inner_loop_exit);
340
341 entry->AddSuccessor(outer_loop_header);
342 outer_loop_header->AddSuccessor(outer_loop_body);
343 outer_loop_header->AddSuccessor(outer_loop_exit);
344 outer_loop_body->AddSuccessor(inner_loop_header);
345 inner_loop_header->AddSuccessor(inner_loop_body);
346 inner_loop_header->AddSuccessor(inner_loop_exit);
347 inner_loop_body->AddSuccessor(inner_loop_header);
348 inner_loop_exit->AddSuccessor(outer_loop_header);
349
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000350 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800351 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000352 0,
353 Primitive::kPrimBoolean);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100354 entry->AddInstruction(parameter);
355 entry->AddInstruction(new (&allocator) HGoto());
David Brazdildee58d62016-04-07 09:54:26 +0000356 outer_loop_header->AddInstruction(new (&allocator) HSuspendCheck());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100357 outer_loop_header->AddInstruction(new (&allocator) HIf(parameter));
358 outer_loop_body->AddInstruction(new (&allocator) HGoto());
David Brazdildee58d62016-04-07 09:54:26 +0000359 inner_loop_header->AddInstruction(new (&allocator) HSuspendCheck());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100360 inner_loop_header->AddInstruction(new (&allocator) HIf(parameter));
361 inner_loop_body->AddInstruction(new (&allocator) HGoto());
362 inner_loop_exit->AddInstruction(new (&allocator) HGoto());
363 outer_loop_exit->AddInstruction(new (&allocator) HExit());
364
David Brazdilbadd8262016-02-02 16:28:56 +0000365 graph->BuildDominatorTree();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100366
367 ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
368 *outer_loop_header->GetLoopInformation()));
369
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100370 // Check that the only side effect of loops is to potentially trigger GC.
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100371 {
372 // Make one block with a side effect.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100373 entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
374 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000375 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100376 Primitive::kPrimNot,
377 MemberOffset(42),
378 false,
379 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700380 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700381 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100382 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100383
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000384 SideEffectsAnalysis side_effects(graph);
385 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100386
Aart Bik854a02b2015-07-14 16:07:00 -0700387 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
388 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
389 ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
390 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100391 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
392 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100393 }
394
395 // Check that the side effects of the outer loop does not affect the inner loop.
396 {
397 outer_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100398 new (&allocator) HInstanceFieldSet(parameter,
399 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000400 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100401 Primitive::kPrimNot,
402 MemberOffset(42),
403 false,
404 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700405 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700406 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100407 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100408 outer_loop_body->GetLastInstruction());
409
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000410 SideEffectsAnalysis side_effects(graph);
411 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100412
Aart Bik854a02b2015-07-14 16:07:00 -0700413 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
414 ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
415 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
416 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100417 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100418 }
419
420 // Check that the side effects of the inner loop affects the outer loop.
421 {
422 outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
423 inner_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100424 new (&allocator) HInstanceFieldSet(parameter,
425 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000426 nullptr,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100427 Primitive::kPrimNot,
428 MemberOffset(42),
429 false,
430 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700431 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700432 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100433 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100434 inner_loop_body->GetLastInstruction());
435
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000436 SideEffectsAnalysis side_effects(graph);
437 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100438
Aart Bik854a02b2015-07-14 16:07:00 -0700439 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
440 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
441 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
442 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100443 }
444}
445} // namespace art