blob: 56f2718264158d44e360060bcb277e43079dcf07 [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);
Calin Juravlec05aca72015-10-13 13:10:33 +000037 HInstruction* parameter = new (&allocator) HParameterValue(0, Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010038 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(),
Calin Juravle154746b2015-10-06 15:46:54 +010050 dex_cache,
51 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010052 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
53 Primitive::kPrimNot,
54 MemberOffset(42),
55 false,
56 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070057 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010058 dex_cache,
59 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010060 HInstruction* to_remove = block->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010061 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
62 Primitive::kPrimNot,
63 MemberOffset(43),
64 false,
65 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070066 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010067 dex_cache,
68 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010069 HInstruction* different_offset = block->GetLastInstruction();
70 // Kill the value.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010071 block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
72 parameter,
73 Primitive::kPrimNot,
74 MemberOffset(42),
75 false,
76 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070077 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010078 dex_cache,
79 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010080 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
81 Primitive::kPrimNot,
82 MemberOffset(42),
83 false,
84 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070085 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010086 dex_cache,
87 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010088 HInstruction* use_after_kill = block->GetLastInstruction();
89 block->AddInstruction(new (&allocator) HExit());
90
91 ASSERT_EQ(to_remove->GetBlock(), block);
92 ASSERT_EQ(different_offset->GetBlock(), block);
93 ASSERT_EQ(use_after_kill->GetBlock(), block);
94
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000095 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +000096 SideEffectsAnalysis side_effects(graph);
97 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +000098 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010099
100 ASSERT_TRUE(to_remove->GetBlock() == nullptr);
101 ASSERT_EQ(different_offset->GetBlock(), block);
102 ASSERT_EQ(use_after_kill->GetBlock(), block);
103}
104
105TEST(GVNTest, GlobalFieldElimination) {
106 ArenaPool pool;
107 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700108 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100109
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100110 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100111 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
112 graph->AddBlock(entry);
113 graph->SetEntryBlock(entry);
Calin Juravlec05aca72015-10-13 13:10:33 +0000114 HInstruction* parameter = new (&allocator) HParameterValue(0, Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100115 entry->AddInstruction(parameter);
116
117 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
118 graph->AddBlock(block);
119 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100120 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
121 Primitive::kPrimBoolean,
122 MemberOffset(42),
123 false,
124 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700125 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100126 dex_cache,
127 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100128
129 block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
130 HBasicBlock* then = new (&allocator) HBasicBlock(graph);
131 HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
132 HBasicBlock* join = new (&allocator) HBasicBlock(graph);
133 graph->AddBlock(then);
134 graph->AddBlock(else_);
135 graph->AddBlock(join);
136
137 block->AddSuccessor(then);
138 block->AddSuccessor(else_);
139 then->AddSuccessor(join);
140 else_->AddSuccessor(join);
141
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100142 then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
143 Primitive::kPrimBoolean,
144 MemberOffset(42),
145 false,
146 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700147 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100148 dex_cache,
149 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100150 then->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100151 else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
152 Primitive::kPrimBoolean,
153 MemberOffset(42),
154 false,
155 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700156 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100157 dex_cache,
158 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100159 else_->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100160 join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
161 Primitive::kPrimBoolean,
162 MemberOffset(42),
163 false,
164 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700165 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100166 dex_cache,
167 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100168 join->AddInstruction(new (&allocator) HExit());
169
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000170 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000171 SideEffectsAnalysis side_effects(graph);
172 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000173 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100174
175 // Check that all field get instructions have been GVN'ed.
176 ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
177 ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
178 ASSERT_TRUE(join->GetFirstInstruction()->IsExit());
179}
180
181TEST(GVNTest, LoopFieldElimination) {
182 ArenaPool pool;
183 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700184 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100185
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100186 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100187 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
188 graph->AddBlock(entry);
189 graph->SetEntryBlock(entry);
190
Calin Juravlec05aca72015-10-13 13:10:33 +0000191 HInstruction* parameter = new (&allocator) HParameterValue(0, Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100192 entry->AddInstruction(parameter);
193
194 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
195 graph->AddBlock(block);
196 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100197 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
198 Primitive::kPrimBoolean,
199 MemberOffset(42),
200 false,
201 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700202 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100203 dex_cache,
204 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100205 block->AddInstruction(new (&allocator) HGoto());
206
207 HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
208 HBasicBlock* loop_body = new (&allocator) HBasicBlock(graph);
209 HBasicBlock* exit = new (&allocator) HBasicBlock(graph);
210
211 graph->AddBlock(loop_header);
212 graph->AddBlock(loop_body);
213 graph->AddBlock(exit);
214 block->AddSuccessor(loop_header);
215 loop_header->AddSuccessor(loop_body);
216 loop_header->AddSuccessor(exit);
217 loop_body->AddSuccessor(loop_header);
218
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100219 loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
220 Primitive::kPrimBoolean,
221 MemberOffset(42),
222 false,
223 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700224 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100225 dex_cache,
226 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100227 HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
228 loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
229
230 // Kill inside the loop body to prevent field gets inside the loop header
231 // and the body to be GVN'ed.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100232 loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
233 parameter,
Aart Bik854a02b2015-07-14 16:07:00 -0700234 Primitive::kPrimBoolean,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100235 MemberOffset(42),
236 false,
237 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700238 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100239 dex_cache,
240 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100241 HInstruction* field_set = loop_body->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100242 loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
243 Primitive::kPrimBoolean,
244 MemberOffset(42),
245 false,
246 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700247 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100248 dex_cache,
249 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100250 HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
251 loop_body->AddInstruction(new (&allocator) HGoto());
252
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100253 exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
254 Primitive::kPrimBoolean,
255 MemberOffset(42),
256 false,
257 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700258 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100259 dex_cache,
260 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100261 HInstruction* field_get_in_exit = exit->GetLastInstruction();
262 exit->AddInstruction(new (&allocator) HExit());
263
264 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
265 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
266 ASSERT_EQ(field_get_in_exit->GetBlock(), exit);
267
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000268 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000269 {
270 SideEffectsAnalysis side_effects(graph);
271 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000272 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000273 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100274
275 // Check that all field get instructions are still there.
276 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
277 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
278 // The exit block is dominated by the loop header, whose field get
279 // does not get killed by the loop flags.
280 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
281
282 // Now remove the field set, and check that all field get instructions have been GVN'ed.
283 loop_body->RemoveInstruction(field_set);
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000284 {
285 SideEffectsAnalysis side_effects(graph);
286 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000287 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000288 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100289
290 ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr);
291 ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr);
292 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
293}
294
295// Test that inner loops affect the side effects of the outer loop.
296TEST(GVNTest, LoopSideEffects) {
297 ArenaPool pool;
298 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700299 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100300
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100301 static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();
302
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100303 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100304 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
305 graph->AddBlock(entry);
306 graph->SetEntryBlock(entry);
307
308 HBasicBlock* outer_loop_header = new (&allocator) HBasicBlock(graph);
309 HBasicBlock* outer_loop_body = new (&allocator) HBasicBlock(graph);
310 HBasicBlock* outer_loop_exit = new (&allocator) HBasicBlock(graph);
311 HBasicBlock* inner_loop_header = new (&allocator) HBasicBlock(graph);
312 HBasicBlock* inner_loop_body = new (&allocator) HBasicBlock(graph);
313 HBasicBlock* inner_loop_exit = new (&allocator) HBasicBlock(graph);
314
315 graph->AddBlock(outer_loop_header);
316 graph->AddBlock(outer_loop_body);
317 graph->AddBlock(outer_loop_exit);
318 graph->AddBlock(inner_loop_header);
319 graph->AddBlock(inner_loop_body);
320 graph->AddBlock(inner_loop_exit);
321
322 entry->AddSuccessor(outer_loop_header);
323 outer_loop_header->AddSuccessor(outer_loop_body);
324 outer_loop_header->AddSuccessor(outer_loop_exit);
325 outer_loop_body->AddSuccessor(inner_loop_header);
326 inner_loop_header->AddSuccessor(inner_loop_body);
327 inner_loop_header->AddSuccessor(inner_loop_exit);
328 inner_loop_body->AddSuccessor(inner_loop_header);
329 inner_loop_exit->AddSuccessor(outer_loop_header);
330
Calin Juravlec05aca72015-10-13 13:10:33 +0000331 HInstruction* parameter = new (&allocator) HParameterValue(0, Primitive::kPrimBoolean);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100332 entry->AddInstruction(parameter);
333 entry->AddInstruction(new (&allocator) HGoto());
334 outer_loop_header->AddInstruction(new (&allocator) HIf(parameter));
335 outer_loop_body->AddInstruction(new (&allocator) HGoto());
336 inner_loop_header->AddInstruction(new (&allocator) HIf(parameter));
337 inner_loop_body->AddInstruction(new (&allocator) HGoto());
338 inner_loop_exit->AddInstruction(new (&allocator) HGoto());
339 outer_loop_exit->AddInstruction(new (&allocator) HExit());
340
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000341 graph->TryBuildingSsa();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100342
343 ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
344 *outer_loop_header->GetLoopInformation()));
345
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100346 // Check that the only side effect of loops is to potentially trigger GC.
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100347 {
348 // Make one block with a side effect.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100349 entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
350 parameter,
351 Primitive::kPrimNot,
352 MemberOffset(42),
353 false,
354 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700355 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100356 dex_cache,
357 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100358
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000359 SideEffectsAnalysis side_effects(graph);
360 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100361
Aart Bik854a02b2015-07-14 16:07:00 -0700362 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
363 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
364 ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
365 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100366 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
367 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100368 }
369
370 // Check that the side effects of the outer loop does not affect the inner loop.
371 {
372 outer_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100373 new (&allocator) HInstanceFieldSet(parameter,
374 parameter,
375 Primitive::kPrimNot,
376 MemberOffset(42),
377 false,
378 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700379 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100380 dex_cache,
381 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100382 outer_loop_body->GetLastInstruction());
383
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_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
389 ASSERT_TRUE(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(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100392 }
393
394 // Check that the side effects of the inner loop affects the outer loop.
395 {
396 outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
397 inner_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100398 new (&allocator) HInstanceFieldSet(parameter,
399 parameter,
400 Primitive::kPrimNot,
401 MemberOffset(42),
402 false,
403 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700404 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100405 dex_cache,
406 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100407 inner_loop_body->GetLastInstruction());
408
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000409 SideEffectsAnalysis side_effects(graph);
410 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100411
Aart Bik854a02b2015-07-14 16:07:00 -0700412 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
413 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
414 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
415 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100416 }
417}
418} // namespace art