blob: de60cf21aaa8906a21338aea6e033c9858a12e32 [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 Juravlee6e3bea2015-10-14 13:53:10 +000037 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,
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
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000103 graph->TryBuildingSsa();
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
113TEST(GVNTest, GlobalFieldElimination) {
114 ArenaPool pool;
115 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700116 NullHandle<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(),
123 0,
124 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
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000185 graph->TryBuildingSsa();
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
196TEST(GVNTest, LoopFieldElimination) {
197 ArenaPool pool;
198 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700199 NullHandle<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(),
207 0,
208 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
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000291 graph->TryBuildingSsa();
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.
319TEST(GVNTest, LoopSideEffects) {
320 ArenaPool pool;
321 ArenaAllocator allocator(&pool);
Mathieu Chartier736b5602015-09-02 14:54:11 -0700322 NullHandle<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(),
355 0,
356 0,
357 Primitive::kPrimBoolean);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100358 entry->AddInstruction(parameter);
359 entry->AddInstruction(new (&allocator) HGoto());
360 outer_loop_header->AddInstruction(new (&allocator) HIf(parameter));
361 outer_loop_body->AddInstruction(new (&allocator) HGoto());
362 inner_loop_header->AddInstruction(new (&allocator) HIf(parameter));
363 inner_loop_body->AddInstruction(new (&allocator) HGoto());
364 inner_loop_exit->AddInstruction(new (&allocator) HGoto());
365 outer_loop_exit->AddInstruction(new (&allocator) HExit());
366
Nicolas Geoffraye53798a2014-12-01 10:31:54 +0000367 graph->TryBuildingSsa();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100368
369 ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
370 *outer_loop_header->GetLoopInformation()));
371
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100372 // Check that the only side effect of loops is to potentially trigger GC.
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100373 {
374 // Make one block with a side effect.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100375 entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
376 parameter,
377 Primitive::kPrimNot,
378 MemberOffset(42),
379 false,
380 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700381 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700382 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100383 dex_cache,
384 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100385
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000386 SideEffectsAnalysis side_effects(graph);
387 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100388
Aart Bik854a02b2015-07-14 16:07:00 -0700389 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
390 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
391 ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
392 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100393 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
394 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100395 }
396
397 // Check that the side effects of the outer loop does not affect the inner loop.
398 {
399 outer_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100400 new (&allocator) HInstanceFieldSet(parameter,
401 parameter,
402 Primitive::kPrimNot,
403 MemberOffset(42),
404 false,
405 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700406 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700407 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100408 dex_cache,
409 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100410 outer_loop_body->GetLastInstruction());
411
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000412 SideEffectsAnalysis side_effects(graph);
413 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100414
Aart Bik854a02b2015-07-14 16:07:00 -0700415 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
416 ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
417 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
418 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100419 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100420 }
421
422 // Check that the side effects of the inner loop affects the outer loop.
423 {
424 outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
425 inner_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100426 new (&allocator) HInstanceFieldSet(parameter,
427 parameter,
428 Primitive::kPrimNot,
429 MemberOffset(42),
430 false,
431 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700432 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700433 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100434 dex_cache,
435 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100436 inner_loop_body->GetLastInstruction());
437
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000438 SideEffectsAnalysis side_effects(graph);
439 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100440
Aart Bik854a02b2015-07-14 16:07:00 -0700441 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
442 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
443 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
444 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100445 }
446}
447} // namespace art