blob: 32f45b5669101df3473d77f243d383c789f03e3c [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
24#include "gtest/gtest.h"
25
26namespace art {
27
28TEST(GVNTest, LocalFieldElimination) {
29 ArenaPool pool;
30 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -070031 NullHandle<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);
37 HInstruction* parameter = new (&allocator) HParameterValue(0, Primitive::kPrimNot);
38 entry->AddInstruction(parameter);
39
40 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
41 graph->AddBlock(block);
42 entry->AddSuccessor(block);
43
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010044 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
45 Primitive::kPrimNot,
46 MemberOffset(42),
47 false,
48 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070049 graph->GetDexFile(),
50 dex_cache));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010051 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
52 Primitive::kPrimNot,
53 MemberOffset(42),
54 false,
55 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070056 graph->GetDexFile(),
57 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010058 HInstruction* to_remove = block->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010059 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
60 Primitive::kPrimNot,
61 MemberOffset(43),
62 false,
63 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070064 graph->GetDexFile(),
65 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010066 HInstruction* different_offset = block->GetLastInstruction();
67 // Kill the value.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010068 block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
69 parameter,
70 Primitive::kPrimNot,
71 MemberOffset(42),
72 false,
73 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070074 graph->GetDexFile(),
75 dex_cache));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010076 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
77 Primitive::kPrimNot,
78 MemberOffset(42),
79 false,
80 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070081 graph->GetDexFile(),
82 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010083 HInstruction* use_after_kill = block->GetLastInstruction();
84 block->AddInstruction(new (&allocator) HExit());
85
86 ASSERT_EQ(to_remove->GetBlock(), block);
87 ASSERT_EQ(different_offset->GetBlock(), block);
88 ASSERT_EQ(use_after_kill->GetBlock(), block);
89
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000090 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +000091 SideEffectsAnalysis side_effects(graph);
92 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +000093 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010094
95 ASSERT_TRUE(to_remove->GetBlock() == nullptr);
96 ASSERT_EQ(different_offset->GetBlock(), block);
97 ASSERT_EQ(use_after_kill->GetBlock(), block);
98}
99
100TEST(GVNTest, GlobalFieldElimination) {
101 ArenaPool pool;
102 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700103 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100104
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100105 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100106 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
107 graph->AddBlock(entry);
108 graph->SetEntryBlock(entry);
109 HInstruction* parameter = new (&allocator) HParameterValue(0, Primitive::kPrimNot);
110 entry->AddInstruction(parameter);
111
112 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
113 graph->AddBlock(block);
114 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100115 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
116 Primitive::kPrimBoolean,
117 MemberOffset(42),
118 false,
119 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700120 graph->GetDexFile(),
121 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100122
123 block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
124 HBasicBlock* then = new (&allocator) HBasicBlock(graph);
125 HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
126 HBasicBlock* join = new (&allocator) HBasicBlock(graph);
127 graph->AddBlock(then);
128 graph->AddBlock(else_);
129 graph->AddBlock(join);
130
131 block->AddSuccessor(then);
132 block->AddSuccessor(else_);
133 then->AddSuccessor(join);
134 else_->AddSuccessor(join);
135
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100136 then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
137 Primitive::kPrimBoolean,
138 MemberOffset(42),
139 false,
140 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700141 graph->GetDexFile(),
142 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100143 then->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100144 else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
145 Primitive::kPrimBoolean,
146 MemberOffset(42),
147 false,
148 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700149 graph->GetDexFile(),
150 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100151 else_->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100152 join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
153 Primitive::kPrimBoolean,
154 MemberOffset(42),
155 false,
156 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700157 graph->GetDexFile(),
158 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100159 join->AddInstruction(new (&allocator) HExit());
160
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000161 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000162 SideEffectsAnalysis side_effects(graph);
163 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000164 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100165
166 // Check that all field get instructions have been GVN'ed.
167 ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
168 ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
169 ASSERT_TRUE(join->GetFirstInstruction()->IsExit());
170}
171
172TEST(GVNTest, LoopFieldElimination) {
173 ArenaPool pool;
174 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700175 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100176
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100177 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100178 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
179 graph->AddBlock(entry);
180 graph->SetEntryBlock(entry);
181
182 HInstruction* parameter = new (&allocator) HParameterValue(0, Primitive::kPrimNot);
183 entry->AddInstruction(parameter);
184
185 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
186 graph->AddBlock(block);
187 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100188 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
189 Primitive::kPrimBoolean,
190 MemberOffset(42),
191 false,
192 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700193 graph->GetDexFile(),
194 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100195 block->AddInstruction(new (&allocator) HGoto());
196
197 HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
198 HBasicBlock* loop_body = new (&allocator) HBasicBlock(graph);
199 HBasicBlock* exit = new (&allocator) HBasicBlock(graph);
200
201 graph->AddBlock(loop_header);
202 graph->AddBlock(loop_body);
203 graph->AddBlock(exit);
204 block->AddSuccessor(loop_header);
205 loop_header->AddSuccessor(loop_body);
206 loop_header->AddSuccessor(exit);
207 loop_body->AddSuccessor(loop_header);
208
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100209 loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
210 Primitive::kPrimBoolean,
211 MemberOffset(42),
212 false,
213 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700214 graph->GetDexFile(),
215 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100216 HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
217 loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
218
219 // Kill inside the loop body to prevent field gets inside the loop header
220 // and the body to be GVN'ed.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100221 loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
222 parameter,
Aart Bik854a02b2015-07-14 16:07:00 -0700223 Primitive::kPrimBoolean,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100224 MemberOffset(42),
225 false,
226 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700227 graph->GetDexFile(),
228 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100229 HInstruction* field_set = loop_body->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100230 loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
231 Primitive::kPrimBoolean,
232 MemberOffset(42),
233 false,
234 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700235 graph->GetDexFile(),
236 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100237 HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
238 loop_body->AddInstruction(new (&allocator) HGoto());
239
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100240 exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
241 Primitive::kPrimBoolean,
242 MemberOffset(42),
243 false,
244 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700245 graph->GetDexFile(),
246 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100247 HInstruction* field_get_in_exit = exit->GetLastInstruction();
248 exit->AddInstruction(new (&allocator) HExit());
249
250 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
251 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
252 ASSERT_EQ(field_get_in_exit->GetBlock(), exit);
253
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000254 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000255 {
256 SideEffectsAnalysis side_effects(graph);
257 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000258 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000259 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100260
261 // Check that all field get instructions are still there.
262 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
263 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
264 // The exit block is dominated by the loop header, whose field get
265 // does not get killed by the loop flags.
266 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
267
268 // Now remove the field set, and check that all field get instructions have been GVN'ed.
269 loop_body->RemoveInstruction(field_set);
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000270 {
271 SideEffectsAnalysis side_effects(graph);
272 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000273 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000274 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100275
276 ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr);
277 ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr);
278 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
279}
280
281// Test that inner loops affect the side effects of the outer loop.
282TEST(GVNTest, LoopSideEffects) {
283 ArenaPool pool;
284 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700285 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100286
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100287 static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();
288
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100289 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100290 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
291 graph->AddBlock(entry);
292 graph->SetEntryBlock(entry);
293
294 HBasicBlock* outer_loop_header = new (&allocator) HBasicBlock(graph);
295 HBasicBlock* outer_loop_body = new (&allocator) HBasicBlock(graph);
296 HBasicBlock* outer_loop_exit = new (&allocator) HBasicBlock(graph);
297 HBasicBlock* inner_loop_header = new (&allocator) HBasicBlock(graph);
298 HBasicBlock* inner_loop_body = new (&allocator) HBasicBlock(graph);
299 HBasicBlock* inner_loop_exit = new (&allocator) HBasicBlock(graph);
300
301 graph->AddBlock(outer_loop_header);
302 graph->AddBlock(outer_loop_body);
303 graph->AddBlock(outer_loop_exit);
304 graph->AddBlock(inner_loop_header);
305 graph->AddBlock(inner_loop_body);
306 graph->AddBlock(inner_loop_exit);
307
308 entry->AddSuccessor(outer_loop_header);
309 outer_loop_header->AddSuccessor(outer_loop_body);
310 outer_loop_header->AddSuccessor(outer_loop_exit);
311 outer_loop_body->AddSuccessor(inner_loop_header);
312 inner_loop_header->AddSuccessor(inner_loop_body);
313 inner_loop_header->AddSuccessor(inner_loop_exit);
314 inner_loop_body->AddSuccessor(inner_loop_header);
315 inner_loop_exit->AddSuccessor(outer_loop_header);
316
317 HInstruction* parameter = new (&allocator) HParameterValue(0, Primitive::kPrimBoolean);
318 entry->AddInstruction(parameter);
319 entry->AddInstruction(new (&allocator) HGoto());
320 outer_loop_header->AddInstruction(new (&allocator) HIf(parameter));
321 outer_loop_body->AddInstruction(new (&allocator) HGoto());
322 inner_loop_header->AddInstruction(new (&allocator) HIf(parameter));
323 inner_loop_body->AddInstruction(new (&allocator) HGoto());
324 inner_loop_exit->AddInstruction(new (&allocator) HGoto());
325 outer_loop_exit->AddInstruction(new (&allocator) HExit());
326
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000327 graph->TryBuildingSsa();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100328
329 ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
330 *outer_loop_header->GetLoopInformation()));
331
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100332 // Check that the only side effect of loops is to potentially trigger GC.
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100333 {
334 // Make one block with a side effect.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100335 entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
336 parameter,
337 Primitive::kPrimNot,
338 MemberOffset(42),
339 false,
340 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700341 graph->GetDexFile(),
342 dex_cache));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100343
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000344 SideEffectsAnalysis side_effects(graph);
345 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100346
Aart Bik854a02b2015-07-14 16:07:00 -0700347 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
348 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
349 ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
350 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100351 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
352 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100353 }
354
355 // Check that the side effects of the outer loop does not affect the inner loop.
356 {
357 outer_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100358 new (&allocator) HInstanceFieldSet(parameter,
359 parameter,
360 Primitive::kPrimNot,
361 MemberOffset(42),
362 false,
363 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700364 graph->GetDexFile(),
365 dex_cache),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100366 outer_loop_body->GetLastInstruction());
367
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000368 SideEffectsAnalysis side_effects(graph);
369 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100370
Aart Bik854a02b2015-07-14 16:07:00 -0700371 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
372 ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
373 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
374 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100375 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100376 }
377
378 // Check that the side effects of the inner loop affects the outer loop.
379 {
380 outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
381 inner_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100382 new (&allocator) HInstanceFieldSet(parameter,
383 parameter,
384 Primitive::kPrimNot,
385 MemberOffset(42),
386 false,
387 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700388 graph->GetDexFile(),
389 dex_cache),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100390 inner_loop_body->GetLastInstruction());
391
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000392 SideEffectsAnalysis side_effects(graph);
393 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100394
Aart Bik854a02b2015-07-14 16:07:00 -0700395 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
396 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
397 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
398 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100399 }
400}
401} // namespace art