blob: 437d35ccb752bbe2adcd98ec33439948ba87de21 [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);
Mathieu Chartier9865bde2015-12-21 09:58:16 -080031 ScopedNullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010032
Nicolas Geoffray0a23d742015-05-07 11:57:35 +010033 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010034 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
35 graph->AddBlock(entry);
36 graph->SetEntryBlock(entry);
Calin Juravlee6e3bea2015-10-14 13:53:10 +000037 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -080038 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +000039 0,
40 Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010041 entry->AddInstruction(parameter);
42
43 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
44 graph->AddBlock(block);
45 entry->AddSuccessor(block);
46
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010047 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
48 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 dex_cache,
55 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010056 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
57 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 dex_cache,
64 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010065 HInstruction* to_remove = block->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010066 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
67 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 dex_cache,
74 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010075 HInstruction* different_offset = block->GetLastInstruction();
76 // Kill the value.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010077 block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
78 parameter,
79 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 dex_cache,
86 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010087 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
88 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 dex_cache,
95 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010096 HInstruction* use_after_kill = block->GetLastInstruction();
97 block->AddInstruction(new (&allocator) HExit());
98
99 ASSERT_EQ(to_remove->GetBlock(), block);
100 ASSERT_EQ(different_offset->GetBlock(), block);
101 ASSERT_EQ(use_after_kill->GetBlock(), block);
102
David Brazdilbadd8262016-02-02 16:28:56 +0000103 graph->BuildDominatorTree();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000104 SideEffectsAnalysis side_effects(graph);
105 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000106 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100107
108 ASSERT_TRUE(to_remove->GetBlock() == nullptr);
109 ASSERT_EQ(different_offset->GetBlock(), block);
110 ASSERT_EQ(use_after_kill->GetBlock(), block);
111}
112
David Brazdil4833f5a2015-12-16 10:37:39 +0000113TEST_F(GVNTest, GlobalFieldElimination) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100114 ArenaPool pool;
115 ArenaAllocator allocator(&pool);
Mathieu Chartier9865bde2015-12-21 09:58:16 -0800116 ScopedNullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100117
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100118 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100119 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
120 graph->AddBlock(entry);
121 graph->SetEntryBlock(entry);
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000122 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800123 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000124 0,
125 Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100126 entry->AddInstruction(parameter);
127
128 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
129 graph->AddBlock(block);
130 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100131 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
132 Primitive::kPrimBoolean,
133 MemberOffset(42),
134 false,
135 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700136 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700137 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100138 dex_cache,
139 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100140
141 block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
142 HBasicBlock* then = new (&allocator) HBasicBlock(graph);
143 HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
144 HBasicBlock* join = new (&allocator) HBasicBlock(graph);
145 graph->AddBlock(then);
146 graph->AddBlock(else_);
147 graph->AddBlock(join);
148
149 block->AddSuccessor(then);
150 block->AddSuccessor(else_);
151 then->AddSuccessor(join);
152 else_->AddSuccessor(join);
153
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100154 then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
155 Primitive::kPrimBoolean,
156 MemberOffset(42),
157 false,
158 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700159 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700160 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100161 dex_cache,
162 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100163 then->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100164 else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
165 Primitive::kPrimBoolean,
166 MemberOffset(42),
167 false,
168 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700169 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700170 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100171 dex_cache,
172 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100173 else_->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100174 join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
175 Primitive::kPrimBoolean,
176 MemberOffset(42),
177 false,
178 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700179 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700180 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100181 dex_cache,
182 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100183 join->AddInstruction(new (&allocator) HExit());
184
David Brazdilbadd8262016-02-02 16:28:56 +0000185 graph->BuildDominatorTree();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000186 SideEffectsAnalysis side_effects(graph);
187 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000188 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100189
190 // Check that all field get instructions have been GVN'ed.
191 ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
192 ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
193 ASSERT_TRUE(join->GetFirstInstruction()->IsExit());
194}
195
David Brazdil4833f5a2015-12-16 10:37:39 +0000196TEST_F(GVNTest, LoopFieldElimination) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100197 ArenaPool pool;
198 ArenaAllocator allocator(&pool);
Mathieu Chartier9865bde2015-12-21 09:58:16 -0800199 ScopedNullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100200
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100201 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100202 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
203 graph->AddBlock(entry);
204 graph->SetEntryBlock(entry);
205
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000206 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800207 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000208 0,
209 Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100210 entry->AddInstruction(parameter);
211
212 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
213 graph->AddBlock(block);
214 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100215 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
216 Primitive::kPrimBoolean,
217 MemberOffset(42),
218 false,
219 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700220 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700221 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100222 dex_cache,
223 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100224 block->AddInstruction(new (&allocator) HGoto());
225
226 HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
227 HBasicBlock* loop_body = new (&allocator) HBasicBlock(graph);
228 HBasicBlock* exit = new (&allocator) HBasicBlock(graph);
229
230 graph->AddBlock(loop_header);
231 graph->AddBlock(loop_body);
232 graph->AddBlock(exit);
233 block->AddSuccessor(loop_header);
234 loop_header->AddSuccessor(loop_body);
235 loop_header->AddSuccessor(exit);
236 loop_body->AddSuccessor(loop_header);
237
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100238 loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
239 Primitive::kPrimBoolean,
240 MemberOffset(42),
241 false,
242 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700243 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700244 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100245 dex_cache,
246 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100247 HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
248 loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
249
250 // Kill inside the loop body to prevent field gets inside the loop header
251 // and the body to be GVN'ed.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100252 loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
253 parameter,
Aart Bik854a02b2015-07-14 16:07:00 -0700254 Primitive::kPrimBoolean,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100255 MemberOffset(42),
256 false,
257 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700258 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700259 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100260 dex_cache,
261 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100262 HInstruction* field_set = loop_body->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100263 loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
264 Primitive::kPrimBoolean,
265 MemberOffset(42),
266 false,
267 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700268 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700269 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100270 dex_cache,
271 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100272 HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
273 loop_body->AddInstruction(new (&allocator) HGoto());
274
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100275 exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
276 Primitive::kPrimBoolean,
277 MemberOffset(42),
278 false,
279 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700280 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700281 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100282 dex_cache,
283 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100284 HInstruction* field_get_in_exit = exit->GetLastInstruction();
285 exit->AddInstruction(new (&allocator) HExit());
286
287 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
288 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
289 ASSERT_EQ(field_get_in_exit->GetBlock(), exit);
290
David Brazdilbadd8262016-02-02 16:28:56 +0000291 graph->BuildDominatorTree();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000292 {
293 SideEffectsAnalysis side_effects(graph);
294 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000295 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000296 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100297
298 // Check that all field get instructions are still there.
299 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
300 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
301 // The exit block is dominated by the loop header, whose field get
302 // does not get killed by the loop flags.
303 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
304
305 // Now remove the field set, and check that all field get instructions have been GVN'ed.
306 loop_body->RemoveInstruction(field_set);
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000307 {
308 SideEffectsAnalysis side_effects(graph);
309 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000310 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000311 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100312
313 ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr);
314 ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr);
315 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
316}
317
318// Test that inner loops affect the side effects of the outer loop.
David Brazdil4833f5a2015-12-16 10:37:39 +0000319TEST_F(GVNTest, LoopSideEffects) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100320 ArenaPool pool;
321 ArenaAllocator allocator(&pool);
Mathieu Chartier9865bde2015-12-21 09:58:16 -0800322 ScopedNullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100323
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100324 static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();
325
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100326 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100327 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
328 graph->AddBlock(entry);
329 graph->SetEntryBlock(entry);
330
331 HBasicBlock* outer_loop_header = new (&allocator) HBasicBlock(graph);
332 HBasicBlock* outer_loop_body = new (&allocator) HBasicBlock(graph);
333 HBasicBlock* outer_loop_exit = new (&allocator) HBasicBlock(graph);
334 HBasicBlock* inner_loop_header = new (&allocator) HBasicBlock(graph);
335 HBasicBlock* inner_loop_body = new (&allocator) HBasicBlock(graph);
336 HBasicBlock* inner_loop_exit = new (&allocator) HBasicBlock(graph);
337
338 graph->AddBlock(outer_loop_header);
339 graph->AddBlock(outer_loop_body);
340 graph->AddBlock(outer_loop_exit);
341 graph->AddBlock(inner_loop_header);
342 graph->AddBlock(inner_loop_body);
343 graph->AddBlock(inner_loop_exit);
344
345 entry->AddSuccessor(outer_loop_header);
346 outer_loop_header->AddSuccessor(outer_loop_body);
347 outer_loop_header->AddSuccessor(outer_loop_exit);
348 outer_loop_body->AddSuccessor(inner_loop_header);
349 inner_loop_header->AddSuccessor(inner_loop_body);
350 inner_loop_header->AddSuccessor(inner_loop_exit);
351 inner_loop_body->AddSuccessor(inner_loop_header);
352 inner_loop_exit->AddSuccessor(outer_loop_header);
353
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000354 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800355 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000356 0,
357 Primitive::kPrimBoolean);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100358 entry->AddInstruction(parameter);
359 entry->AddInstruction(new (&allocator) HGoto());
David Brazdildee58d62016-04-07 09:54:26 +0000360 outer_loop_header->AddInstruction(new (&allocator) HSuspendCheck());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100361 outer_loop_header->AddInstruction(new (&allocator) HIf(parameter));
362 outer_loop_body->AddInstruction(new (&allocator) HGoto());
David Brazdildee58d62016-04-07 09:54:26 +0000363 inner_loop_header->AddInstruction(new (&allocator) HSuspendCheck());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100364 inner_loop_header->AddInstruction(new (&allocator) HIf(parameter));
365 inner_loop_body->AddInstruction(new (&allocator) HGoto());
366 inner_loop_exit->AddInstruction(new (&allocator) HGoto());
367 outer_loop_exit->AddInstruction(new (&allocator) HExit());
368
David Brazdilbadd8262016-02-02 16:28:56 +0000369 graph->BuildDominatorTree();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100370
371 ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
372 *outer_loop_header->GetLoopInformation()));
373
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100374 // Check that the only side effect of loops is to potentially trigger GC.
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100375 {
376 // Make one block with a side effect.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100377 entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
378 parameter,
379 Primitive::kPrimNot,
380 MemberOffset(42),
381 false,
382 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700383 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700384 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100385 dex_cache,
386 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100387
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000388 SideEffectsAnalysis side_effects(graph);
389 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100390
Aart Bik854a02b2015-07-14 16:07:00 -0700391 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
392 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
393 ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
394 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100395 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
396 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100397 }
398
399 // Check that the side effects of the outer loop does not affect the inner loop.
400 {
401 outer_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100402 new (&allocator) HInstanceFieldSet(parameter,
403 parameter,
404 Primitive::kPrimNot,
405 MemberOffset(42),
406 false,
407 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700408 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700409 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100410 dex_cache,
411 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100412 outer_loop_body->GetLastInstruction());
413
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000414 SideEffectsAnalysis side_effects(graph);
415 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100416
Aart Bik854a02b2015-07-14 16:07:00 -0700417 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
418 ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
419 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
420 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100421 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100422 }
423
424 // Check that the side effects of the inner loop affects the outer loop.
425 {
426 outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
427 inner_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100428 new (&allocator) HInstanceFieldSet(parameter,
429 parameter,
430 Primitive::kPrimNot,
431 MemberOffset(42),
432 false,
433 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700434 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700435 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100436 dex_cache,
437 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100438 inner_loop_body->GetLastInstruction());
439
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000440 SideEffectsAnalysis side_effects(graph);
441 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100442
Aart Bik854a02b2015-07-14 16:07:00 -0700443 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
444 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
445 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
446 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100447 }
448}
449} // namespace art