blob: ac0dbee2c564bbb623de2c154501ba32adae51bd [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
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070017#include "gvn.h"
18
Mathieu Chartierb666f482015-02-18 14:33:14 -080019#include "base/arena_allocator.h"
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010020#include "builder.h"
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010021#include "nodes.h"
22#include "optimizing_unit_test.h"
Nicolas Geoffray827eedb2015-01-26 15:18:36 +000023#include "side_effects_analysis.h"
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010024
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010025namespace art {
26
David Brazdil4833f5a2015-12-16 10:37:39 +000027class GVNTest : public CommonCompilerTest {};
28
29TEST_F(GVNTest, LocalFieldElimination) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +010030 ArenaPool pool;
31 ArenaAllocator allocator(&pool);
32
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,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010040 DataType::Type::kReference);
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,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000048 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010049 DataType::Type::kReference,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010050 MemberOffset(42),
51 false,
52 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070053 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070054 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010055 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010056 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000057 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010058 DataType::Type::kReference,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010059 MemberOffset(42),
60 false,
61 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070062 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070063 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010064 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,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000067 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010068 DataType::Type::kReference,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010069 MemberOffset(43),
70 false,
71 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070072 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070073 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010074 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,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000079 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010080 DataType::Type::kReference,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010081 MemberOffset(42),
82 false,
83 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070084 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070085 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010086 0));
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010087 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +000088 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +010089 DataType::Type::kReference,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +010090 MemberOffset(42),
91 false,
92 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -070093 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -070094 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +010095 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);
116
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100117 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100118 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
119 graph->AddBlock(entry);
120 graph->SetEntryBlock(entry);
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000121 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800122 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000123 0,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100124 DataType::Type::kReference);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100125 entry->AddInstruction(parameter);
126
127 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
128 graph->AddBlock(block);
129 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100130 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000131 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100132 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100133 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 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100139
140 block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
141 HBasicBlock* then = new (&allocator) HBasicBlock(graph);
142 HBasicBlock* else_ = new (&allocator) HBasicBlock(graph);
143 HBasicBlock* join = new (&allocator) HBasicBlock(graph);
144 graph->AddBlock(then);
145 graph->AddBlock(else_);
146 graph->AddBlock(join);
147
148 block->AddSuccessor(then);
149 block->AddSuccessor(else_);
150 then->AddSuccessor(join);
151 else_->AddSuccessor(join);
152
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100153 then->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000154 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100155 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100156 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 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100162 then->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100163 else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000164 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100165 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100166 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 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100172 else_->AddInstruction(new (&allocator) HGoto());
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100173 join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000174 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100175 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100176 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 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100182 join->AddInstruction(new (&allocator) HExit());
183
David Brazdilbadd8262016-02-02 16:28:56 +0000184 graph->BuildDominatorTree();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000185 SideEffectsAnalysis side_effects(graph);
186 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000187 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100188
189 // Check that all field get instructions have been GVN'ed.
190 ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
191 ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
192 ASSERT_TRUE(join->GetFirstInstruction()->IsExit());
193}
194
David Brazdil4833f5a2015-12-16 10:37:39 +0000195TEST_F(GVNTest, LoopFieldElimination) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100196 ArenaPool pool;
197 ArenaAllocator allocator(&pool);
198
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100199 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100200 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
201 graph->AddBlock(entry);
202 graph->SetEntryBlock(entry);
203
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000204 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800205 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000206 0,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100207 DataType::Type::kReference);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100208 entry->AddInstruction(parameter);
209
210 HBasicBlock* block = new (&allocator) HBasicBlock(graph);
211 graph->AddBlock(block);
212 entry->AddSuccessor(block);
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100213 block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000214 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100215 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100216 MemberOffset(42),
217 false,
218 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700219 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700220 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100221 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100222 block->AddInstruction(new (&allocator) HGoto());
223
224 HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph);
225 HBasicBlock* loop_body = new (&allocator) HBasicBlock(graph);
226 HBasicBlock* exit = new (&allocator) HBasicBlock(graph);
227
228 graph->AddBlock(loop_header);
229 graph->AddBlock(loop_body);
230 graph->AddBlock(exit);
231 block->AddSuccessor(loop_header);
232 loop_header->AddSuccessor(loop_body);
233 loop_header->AddSuccessor(exit);
234 loop_body->AddSuccessor(loop_header);
235
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100236 loop_header->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000237 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100238 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100239 MemberOffset(42),
240 false,
241 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700242 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700243 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100244 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100245 HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
246 loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction()));
247
248 // Kill inside the loop body to prevent field gets inside the loop header
249 // and the body to be GVN'ed.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100250 loop_body->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
251 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000252 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100253 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100254 MemberOffset(42),
255 false,
256 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700257 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700258 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100259 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100260 HInstruction* field_set = loop_body->GetLastInstruction();
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100261 loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000262 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100263 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100264 MemberOffset(42),
265 false,
266 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700267 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700268 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100269 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100270 HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
271 loop_body->AddInstruction(new (&allocator) HGoto());
272
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100273 exit->AddInstruction(new (&allocator) HInstanceFieldGet(parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000274 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100275 DataType::Type::kBool,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100276 MemberOffset(42),
277 false,
278 kUnknownFieldIndex,
Mingyao Yang8df69d42015-10-22 15:40:58 -0700279 kUnknownClassDefIndex,
Mathieu Chartier736b5602015-09-02 14:54:11 -0700280 graph->GetDexFile(),
Calin Juravle154746b2015-10-06 15:46:54 +0100281 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100282 HInstruction* field_get_in_exit = exit->GetLastInstruction();
283 exit->AddInstruction(new (&allocator) HExit());
284
285 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
286 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
287 ASSERT_EQ(field_get_in_exit->GetBlock(), exit);
288
David Brazdilbadd8262016-02-02 16:28:56 +0000289 graph->BuildDominatorTree();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000290 {
291 SideEffectsAnalysis side_effects(graph);
292 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000293 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000294 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100295
296 // Check that all field get instructions are still there.
297 ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
298 ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
299 // The exit block is dominated by the loop header, whose field get
300 // does not get killed by the loop flags.
301 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
302
303 // Now remove the field set, and check that all field get instructions have been GVN'ed.
304 loop_body->RemoveInstruction(field_set);
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000305 {
306 SideEffectsAnalysis side_effects(graph);
307 side_effects.Run();
Nicolas Geoffray827eedb2015-01-26 15:18:36 +0000308 GVNOptimization(graph, side_effects).Run();
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000309 }
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100310
311 ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr);
312 ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr);
313 ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
314}
315
316// Test that inner loops affect the side effects of the outer loop.
David Brazdil4833f5a2015-12-16 10:37:39 +0000317TEST_F(GVNTest, LoopSideEffects) {
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100318 ArenaPool pool;
319 ArenaAllocator allocator(&pool);
320
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100321 static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();
322
Nicolas Geoffray0a23d742015-05-07 11:57:35 +0100323 HGraph* graph = CreateGraph(&allocator);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100324 HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
325 graph->AddBlock(entry);
326 graph->SetEntryBlock(entry);
327
328 HBasicBlock* outer_loop_header = new (&allocator) HBasicBlock(graph);
329 HBasicBlock* outer_loop_body = new (&allocator) HBasicBlock(graph);
330 HBasicBlock* outer_loop_exit = new (&allocator) HBasicBlock(graph);
331 HBasicBlock* inner_loop_header = new (&allocator) HBasicBlock(graph);
332 HBasicBlock* inner_loop_body = new (&allocator) HBasicBlock(graph);
333 HBasicBlock* inner_loop_exit = new (&allocator) HBasicBlock(graph);
334
335 graph->AddBlock(outer_loop_header);
336 graph->AddBlock(outer_loop_body);
337 graph->AddBlock(outer_loop_exit);
338 graph->AddBlock(inner_loop_header);
339 graph->AddBlock(inner_loop_body);
340 graph->AddBlock(inner_loop_exit);
341
342 entry->AddSuccessor(outer_loop_header);
343 outer_loop_header->AddSuccessor(outer_loop_body);
344 outer_loop_header->AddSuccessor(outer_loop_exit);
345 outer_loop_body->AddSuccessor(inner_loop_header);
346 inner_loop_header->AddSuccessor(inner_loop_body);
347 inner_loop_header->AddSuccessor(inner_loop_exit);
348 inner_loop_body->AddSuccessor(inner_loop_header);
349 inner_loop_exit->AddSuccessor(outer_loop_header);
350
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000351 HInstruction* parameter = new (&allocator) HParameterValue(graph->GetDexFile(),
Andreas Gampea5b09a62016-11-17 15:21:22 -0800352 dex::TypeIndex(0),
Calin Juravlee6e3bea2015-10-14 13:53:10 +0000353 0,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100354 DataType::Type::kBool);
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100355 entry->AddInstruction(parameter);
356 entry->AddInstruction(new (&allocator) HGoto());
David Brazdildee58d62016-04-07 09:54:26 +0000357 outer_loop_header->AddInstruction(new (&allocator) HSuspendCheck());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100358 outer_loop_header->AddInstruction(new (&allocator) HIf(parameter));
359 outer_loop_body->AddInstruction(new (&allocator) HGoto());
David Brazdildee58d62016-04-07 09:54:26 +0000360 inner_loop_header->AddInstruction(new (&allocator) HSuspendCheck());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100361 inner_loop_header->AddInstruction(new (&allocator) HIf(parameter));
362 inner_loop_body->AddInstruction(new (&allocator) HGoto());
363 inner_loop_exit->AddInstruction(new (&allocator) HGoto());
364 outer_loop_exit->AddInstruction(new (&allocator) HExit());
365
David Brazdilbadd8262016-02-02 16:28:56 +0000366 graph->BuildDominatorTree();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100367
368 ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
369 *outer_loop_header->GetLoopInformation()));
370
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100371 // Check that the only side effect of loops is to potentially trigger GC.
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100372 {
373 // Make one block with a side effect.
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100374 entry->AddInstruction(new (&allocator) HInstanceFieldSet(parameter,
375 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000376 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100377 DataType::Type::kReference,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100378 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 0));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100384
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000385 SideEffectsAnalysis side_effects(graph);
386 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100387
Aart Bik854a02b2015-07-14 16:07:00 -0700388 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
389 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
390 ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
391 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100392 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
393 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100394 }
395
396 // Check that the side effects of the outer loop does not affect the inner loop.
397 {
398 outer_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100399 new (&allocator) HInstanceFieldSet(parameter,
400 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000401 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100402 DataType::Type::kReference,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100403 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 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100409 outer_loop_body->GetLastInstruction());
410
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000411 SideEffectsAnalysis side_effects(graph);
412 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100413
Aart Bik854a02b2015-07-14 16:07:00 -0700414 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
415 ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
416 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
417 ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100418 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100419 }
420
421 // Check that the side effects of the inner loop affects the outer loop.
422 {
423 outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
424 inner_loop_body->InsertInstructionBefore(
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100425 new (&allocator) HInstanceFieldSet(parameter,
426 parameter,
Nicolas Geoffrayc52b26d2016-12-19 09:18:07 +0000427 nullptr,
Vladimir Marko0ebe0d82017-09-21 22:50:39 +0100428 DataType::Type::kReference,
Guillaume "Vermeille" Sanchez104fd8a2015-05-20 17:52:13 +0100429 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 0),
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100435 inner_loop_body->GetLastInstruction());
436
Nicolas Geoffraye6f17152015-01-26 15:13:47 +0000437 SideEffectsAnalysis side_effects(graph);
438 side_effects.Run();
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100439
Aart Bik854a02b2015-07-14 16:07:00 -0700440 ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
441 ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
442 ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
443 ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
Nicolas Geoffrayd31cf3d2014-09-08 17:30:24 +0100444 }
445}
446} // namespace art