blob: aa375f697baf11ef964a7e8f225d558e57f84522 [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 Juravle2c1ffc32015-10-12 15:01:58 +010037 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
38 0,
39 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,
Mathieu Chartier736b5602015-09-02 14:54:11 -070052 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010053 dex_cache,
54 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010055 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
56 Primitive::kPrimNot,
57 MemberOffset(42),
58 false,
59 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070060 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010061 dex_cache,
62 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010063 HInstruction* to_remove = block->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010064 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
65 Primitive::kPrimNot,
66 MemberOffset(43),
67 false,
68 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070069 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010070 dex_cache,
71 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010072 HInstruction* different_offset = block->GetLastInstruction();
73 // Kill the value.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010074 block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
75 parameter,
76 Primitive::kPrimNot,
77 MemberOffset(42),
78 false,
79 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070080 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010081 dex_cache,
82 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010083 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
84 Primitive::kPrimNot,
85 MemberOffset(42),
86 false,
87 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070088 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010089 dex_cache,
90 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010091 HInstruction* use_after_kill = block->GetLastInstruction();
92 block->AddInstruction(new (&allocator) HExit());
93
94 ASSERT_EQ(to_remove->GetBlock(), block);
95 ASSERT_EQ(different_offset->GetBlock(), block);
96 ASSERT_EQ(use_after_kill->GetBlock(), block);
97
Nicolas Geoffraye53798a2014-12-01 10:31:54 +000098 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +000099 SideEffectsAnalysis side_effects(graph);
100 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000101 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100102
103 ASSERT_TRUE(to_remove->GetBlock() == nullptr);
104 ASSERT_EQ(different_offset->GetBlock(), block);
105 ASSERT_EQ(use_after_kill->GetBlock(), block);
106}
107
108TEST(GVNTest, GlobalFieldElimination) {
109 ArenaPool pool;
110 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700111 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100112
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100113 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100114 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
115 graph->AddBlock(entry);
116 graph->SetEntryBlock(entry);
Calin Juravle2c1ffc32015-10-12 15:01:58 +0100117 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
118 0,
119 0,
120 Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100121 entry->AddInstruction(parameter);
122
123 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
124 graph->AddBlock(block);
125 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100126 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
127 Primitive::kPrimBoolean,
128 MemberOffset(42),
129 false,
130 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700131 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100132 dex_cache,
133 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100134
135 block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
136 HBasicBlock* then = new (&allocator) HBasicBlock(graph);
137 HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
138 HBasicBlock* join = new (&allocator) HBasicBlock(graph);
139 graph->AddBlock(then);
140 graph->AddBlock(else_);
141 graph->AddBlock(join);
142
143 block->AddSuccessor(then);
144 block->AddSuccessor(else_);
145 then->AddSuccessor(join);
146 else_->AddSuccessor(join);
147
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100148 then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
149 Primitive::kPrimBoolean,
150 MemberOffset(42),
151 false,
152 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700153 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100154 dex_cache,
155 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100156 then->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100157 else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
158 Primitive::kPrimBoolean,
159 MemberOffset(42),
160 false,
161 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700162 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100163 dex_cache,
164 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100165 else_->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100166 join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
167 Primitive::kPrimBoolean,
168 MemberOffset(42),
169 false,
170 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700171 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100172 dex_cache,
173 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100174 join->AddInstruction(new (&allocator) HExit());
175
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000176 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000177 SideEffectsAnalysis side_effects(graph);
178 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000179 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100180
181 // Check that all field get instructions have been GVN'ed.
182 ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
183 ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
184 ASSERT_TRUE(join->GetFirstInstruction()->IsExit());
185}
186
187TEST(GVNTest, LoopFieldElimination) {
188 ArenaPool pool;
189 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700190 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100191
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100192 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100193 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
194 graph->AddBlock(entry);
195 graph->SetEntryBlock(entry);
196
Calin Juravle2c1ffc32015-10-12 15:01:58 +0100197 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
198 0,
199 0,
200 Primitive::kPrimNot);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100201 entry->AddInstruction(parameter);
202
203 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
204 graph->AddBlock(block);
205 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100206 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
207 Primitive::kPrimBoolean,
208 MemberOffset(42),
209 false,
210 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700211 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100212 dex_cache,
213 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100214 block->AddInstruction(new (&allocator) HGoto());
215
216 HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
217 HBasicBlock* loop_body = new (&allocator) HBasicBlock(graph);
218 HBasicBlock* exit = new (&allocator) HBasicBlock(graph);
219
220 graph->AddBlock(loop_header);
221 graph->AddBlock(loop_body);
222 graph->AddBlock(exit);
223 block->AddSuccessor(loop_header);
224 loop_header->AddSuccessor(loop_body);
225 loop_header->AddSuccessor(exit);
226 loop_body->AddSuccessor(loop_header);
227
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100228 loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
229 Primitive::kPrimBoolean,
230 MemberOffset(42),
231 false,
232 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700233 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100234 dex_cache,
235 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100236 HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
237 loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
238
239 // Kill inside the loop body to prevent field gets inside the loop header
240 // and the body to be GVN'ed.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100241 loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
242 parameter,
Aart Bik854a02b2015-07-14 16:07:00 -0700243 Primitive::kPrimBoolean,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100244 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_set = loop_body->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100251 loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
252 Primitive::kPrimBoolean,
253 MemberOffset(42),
254 false,
255 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700256 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100257 dex_cache,
258 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100259 HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
260 loop_body->AddInstruction(new (&allocator) HGoto());
261
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100262 exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
263 Primitive::kPrimBoolean,
264 MemberOffset(42),
265 false,
266 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700267 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100268 dex_cache,
269 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100270 HInstruction* field_get_in_exit = exit->GetLastInstruction();
271 exit->AddInstruction(new (&allocator) HExit());
272
273 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
274 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
275 ASSERT_EQ(field_get_in_exit->GetBlock(), exit);
276
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000277 graph->TryBuildingSsa();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000278 {
279 SideEffectsAnalysis side_effects(graph);
280 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000281 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000282 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100283
284 // Check that all field get instructions are still there.
285 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
286 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
287 // The exit block is dominated by the loop header, whose field get
288 // does not get killed by the loop flags.
289 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
290
291 // Now remove the field set, and check that all field get instructions have been GVN'ed.
292 loop_body->RemoveInstruction(field_set);
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000293 {
294 SideEffectsAnalysis side_effects(graph);
295 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000296 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000297 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100298
299 ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr);
300 ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr);
301 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
302}
303
304// Test that inner loops affect the side effects of the outer loop.
305TEST(GVNTest, LoopSideEffects) {
306 ArenaPool pool;
307 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700308 NullHandle<mirror::DexCache> dex_cache;
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100309
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100310 static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();
311
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100312 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100313 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
314 graph->AddBlock(entry);
315 graph->SetEntryBlock(entry);
316
317 HBasicBlock* outer_loop_header = new (&allocator) HBasicBlock(graph);
318 HBasicBlock* outer_loop_body = new (&allocator) HBasicBlock(graph);
319 HBasicBlock* outer_loop_exit = new (&allocator) HBasicBlock(graph);
320 HBasicBlock* inner_loop_header = new (&allocator) HBasicBlock(graph);
321 HBasicBlock* inner_loop_body = new (&allocator) HBasicBlock(graph);
322 HBasicBlock* inner_loop_exit = new (&allocator) HBasicBlock(graph);
323
324 graph->AddBlock(outer_loop_header);
325 graph->AddBlock(outer_loop_body);
326 graph->AddBlock(outer_loop_exit);
327 graph->AddBlock(inner_loop_header);
328 graph->AddBlock(inner_loop_body);
329 graph->AddBlock(inner_loop_exit);
330
331 entry->AddSuccessor(outer_loop_header);
332 outer_loop_header->AddSuccessor(outer_loop_body);
333 outer_loop_header->AddSuccessor(outer_loop_exit);
334 outer_loop_body->AddSuccessor(inner_loop_header);
335 inner_loop_header->AddSuccessor(inner_loop_body);
336 inner_loop_header->AddSuccessor(inner_loop_exit);
337 inner_loop_body->AddSuccessor(inner_loop_header);
338 inner_loop_exit->AddSuccessor(outer_loop_header);
339
Calin Juravle2c1ffc32015-10-12 15:01:58 +0100340 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
341 0,
342 0,
343 Primitive::kPrimBoolean);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100344 entry->AddInstruction(parameter);
345 entry->AddInstruction(new (&allocator) HGoto());
346 outer_loop_header->AddInstruction(new (&allocator) HIf(parameter));
347 outer_loop_body->AddInstruction(new (&allocator) HGoto());
348 inner_loop_header->AddInstruction(new (&allocator) HIf(parameter));
349 inner_loop_body->AddInstruction(new (&allocator) HGoto());
350 inner_loop_exit->AddInstruction(new (&allocator) HGoto());
351 outer_loop_exit->AddInstruction(new (&allocator) HExit());
352
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000353 graph->TryBuildingSsa();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100354
355 ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
356 *outer_loop_header->GetLoopInformation()));
357
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100358 // Check that the only side effect of loops is to potentially trigger GC.
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100359 {
360 // Make one block with a side effect.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100361 entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
362 parameter,
363 Primitive::kPrimNot,
364 MemberOffset(42),
365 false,
366 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700367 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100368 dex_cache,
369 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100370
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000371 SideEffectsAnalysis side_effects(graph);
372 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100373
Aart Bik854a02b2015-07-14 16:07:00 -0700374 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
375 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
376 ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
377 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100378 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
379 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100380 }
381
382 // Check that the side effects of the outer loop does not affect the inner loop.
383 {
384 outer_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100385 new (&allocator) HInstanceFieldSet(parameter,
386 parameter,
387 Primitive::kPrimNot,
388 MemberOffset(42),
389 false,
390 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700391 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100392 dex_cache,
393 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100394 outer_loop_body->GetLastInstruction());
395
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000396 SideEffectsAnalysis side_effects(graph);
397 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100398
Aart Bik854a02b2015-07-14 16:07:00 -0700399 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
400 ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
401 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
402 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100403 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100404 }
405
406 // Check that the side effects of the inner loop affects the outer loop.
407 {
408 outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
409 inner_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100410 new (&allocator) HInstanceFieldSet(parameter,
411 parameter,
412 Primitive::kPrimNot,
413 MemberOffset(42),
414 false,
415 kUnknownFieldIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700416 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100417 dex_cache,
418 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100419 inner_loop_body->GetLastInstruction());
420
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000421 SideEffectsAnalysis side_effects(graph);
422 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100423
Aart Bik854a02b2015-07-14 16:07:00 -0700424 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
425 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
426 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
427 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100428 }
429}
430} // namespace art