1d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray/*
2d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray *
4d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * you may not use this file except in compliance with the License.
6d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * You may obtain a copy of the License at
7d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray *
8d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray *
10d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * See the License for the specific language governing permissions and
14d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray * limitations under the License.
15d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray */
16d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
178cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe#include "gvn.h"
188cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe
19b666f4805c8ae707ea6fd7f6c7f375e0b000dba8Mathieu Chartier#include "base/arena_allocator.h"
20d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray#include "builder.h"
21d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray#include "nodes.h"
22d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray#include "optimizing_unit_test.h"
23827eedbfa882496407375f22b08243a38a5bd53bNicolas Geoffray#include "side_effects_analysis.h"
24d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
2568289a531484d26214e09f1eadd9833531a3bc3cAlex Lightnamespace art {
26d9510dfc32349eeb4f2145c801f7ba1d5bccfb12David Brazdil
27ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Markoclass GVNTest : public OptimizingUnitTest {};
284833f5a1990c76bc2be89504225fb13cca22bedfDavid Brazdil
294833f5a1990c76bc2be89504225fb13cca22bedfDavid BrazdilTEST_F(GVNTest, LocalFieldElimination) {
30ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HGraph* graph = CreateGraph();
31ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
32d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(entry);
33d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->SetEntryBlock(entry);
34ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter = new (GetAllocator()) HParameterValue(graph->GetDexFile(),
35ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 dex::TypeIndex(0),
36ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 0,
37ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 DataType::Type::kReference);
38d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  entry->AddInstruction(parameter);
39d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
40ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph);
41d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(block);
42d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  entry->AddSuccessor(block);
43d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
44ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
45ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               nullptr,
46ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               DataType::Type::kReference,
47ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               MemberOffset(42),
48ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               false,
49ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownFieldIndex,
50ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownClassDefIndex,
51ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               graph->GetDexFile(),
52ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               0));
53ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
54ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               nullptr,
55ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               DataType::Type::kReference,
56ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               MemberOffset(42),
57ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               false,
58ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownFieldIndex,
59ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownClassDefIndex,
60ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               graph->GetDexFile(),
61ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               0));
62d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  HInstruction* to_remove = block->GetLastInstruction();
63ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
64ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               nullptr,
65ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               DataType::Type::kReference,
66ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               MemberOffset(43),
67ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               false,
68ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownFieldIndex,
69ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownClassDefIndex,
70ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               graph->GetDexFile(),
71ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               0));
72d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  HInstruction* different_offset = block->GetLastInstruction();
73d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // Kill the value.
74ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HInstanceFieldSet(parameter,
75ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               parameter,
76ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               nullptr,
77ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               DataType::Type::kReference,
78ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               MemberOffset(42),
79ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               false,
80ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownFieldIndex,
81ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownClassDefIndex,
82ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               graph->GetDexFile(),
83ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               0));
84ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
85ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               nullptr,
86ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               DataType::Type::kReference,
87ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               MemberOffset(42),
88ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               false,
89ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownFieldIndex,
90ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownClassDefIndex,
91ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               graph->GetDexFile(),
92ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               0));
93d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  HInstruction* use_after_kill = block->GetLastInstruction();
94ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HExit());
95d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
96d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(to_remove->GetBlock(), block);
97d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(different_offset->GetBlock(), block);
98d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(use_after_kill->GetBlock(), block);
99d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
100badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  graph->BuildDominatorTree();
101e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray  SideEffectsAnalysis side_effects(graph);
102e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray  side_effects.Run();
103827eedbfa882496407375f22b08243a38a5bd53bNicolas Geoffray  GVNOptimization(graph, side_effects).Run();
104d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
105d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(to_remove->GetBlock() == nullptr);
106d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(different_offset->GetBlock(), block);
107d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(use_after_kill->GetBlock(), block);
108d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray}
109d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
1104833f5a1990c76bc2be89504225fb13cca22bedfDavid BrazdilTEST_F(GVNTest, GlobalFieldElimination) {
111ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HGraph* graph = CreateGraph();
112ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
113d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(entry);
114d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->SetEntryBlock(entry);
115ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter = new (GetAllocator()) HParameterValue(graph->GetDexFile(),
116ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 dex::TypeIndex(0),
117ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 0,
118ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 DataType::Type::kReference);
119d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  entry->AddInstruction(parameter);
120d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
121ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph);
122d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(block);
123d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  entry->AddSuccessor(block);
124ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
125ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               nullptr,
126ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               DataType::Type::kBool,
127ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               MemberOffset(42),
128ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               false,
129ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownFieldIndex,
130ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownClassDefIndex,
131ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               graph->GetDexFile(),
132ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               0));
133ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko
134ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HIf(block->GetLastInstruction()));
135ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* then = new (GetAllocator()) HBasicBlock(graph);
136ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* else_ = new (GetAllocator()) HBasicBlock(graph);
137ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* join = new (GetAllocator()) HBasicBlock(graph);
138d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(then);
139d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(else_);
140d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(join);
141d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
142d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  block->AddSuccessor(then);
143d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  block->AddSuccessor(else_);
144d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  then->AddSuccessor(join);
145d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  else_->AddSuccessor(join);
146d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
147ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  then->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
148ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              nullptr,
149ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              DataType::Type::kBool,
150ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              MemberOffset(42),
151ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              false,
152ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              kUnknownFieldIndex,
153ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              kUnknownClassDefIndex,
154ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              graph->GetDexFile(),
155ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              0));
156ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  then->AddInstruction(new (GetAllocator()) HGoto());
157ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  else_->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
158ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               nullptr,
159ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               DataType::Type::kBool,
160ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               MemberOffset(42),
161ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               false,
162ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownFieldIndex,
163ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownClassDefIndex,
164ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               graph->GetDexFile(),
165ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               0));
166ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  else_->AddInstruction(new (GetAllocator()) HGoto());
167ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  join->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
168ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              nullptr,
169ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              DataType::Type::kBool,
170ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              MemberOffset(42),
171ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              false,
172ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              kUnknownFieldIndex,
173ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              kUnknownClassDefIndex,
174ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              graph->GetDexFile(),
175ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              0));
176ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  join->AddInstruction(new (GetAllocator()) HExit());
177d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
178badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  graph->BuildDominatorTree();
179e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray  SideEffectsAnalysis side_effects(graph);
180e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray  side_effects.Run();
181827eedbfa882496407375f22b08243a38a5bd53bNicolas Geoffray  GVNOptimization(graph, side_effects).Run();
182d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
183d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // Check that all field get instructions have been GVN'ed.
184d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
185d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
186d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(join->GetFirstInstruction()->IsExit());
187d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray}
188d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
1894833f5a1990c76bc2be89504225fb13cca22bedfDavid BrazdilTEST_F(GVNTest, LoopFieldElimination) {
190ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HGraph* graph = CreateGraph();
191ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
192d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(entry);
193d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->SetEntryBlock(entry);
194d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
195ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter = new (GetAllocator()) HParameterValue(graph->GetDexFile(),
196ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 dex::TypeIndex(0),
197ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 0,
198ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 DataType::Type::kReference);
199d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  entry->AddInstruction(parameter);
200d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
201ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph);
202d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(block);
203d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  entry->AddSuccessor(block);
204ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
205ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               nullptr,
206ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               DataType::Type::kBool,
207ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               MemberOffset(42),
208ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               false,
209ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownFieldIndex,
210ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               kUnknownClassDefIndex,
211ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               graph->GetDexFile(),
212ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                               0));
213ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  block->AddInstruction(new (GetAllocator()) HGoto());
214ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko
215ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* loop_header = new (GetAllocator()) HBasicBlock(graph);
216ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* loop_body = new (GetAllocator()) HBasicBlock(graph);
217ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* exit = new (GetAllocator()) HBasicBlock(graph);
218d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
219d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(loop_header);
220d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(loop_body);
221d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(exit);
222d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  block->AddSuccessor(loop_header);
223d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  loop_header->AddSuccessor(loop_body);
224d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  loop_header->AddSuccessor(exit);
225d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  loop_body->AddSuccessor(loop_header);
226d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
227ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  loop_header->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
228ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                     nullptr,
229ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                     DataType::Type::kBool,
230ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                     MemberOffset(42),
231ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                     false,
232ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                     kUnknownFieldIndex,
233ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                     kUnknownClassDefIndex,
234ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                     graph->GetDexFile(),
235ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                     0));
236d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction();
237ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  loop_header->AddInstruction(new (GetAllocator()) HIf(block->GetLastInstruction()));
238d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
239d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // Kill inside the loop body to prevent field gets inside the loop header
240d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // and the body to be GVN'ed.
241ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  loop_body->AddInstruction(new (GetAllocator()) HInstanceFieldSet(parameter,
242ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   parameter,
243ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   nullptr,
244ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   DataType::Type::kBool,
245ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   MemberOffset(42),
246ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   false,
247ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   kUnknownFieldIndex,
248ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   kUnknownClassDefIndex,
249ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   graph->GetDexFile(),
250ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   0));
251d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  HInstruction* field_set = loop_body->GetLastInstruction();
252ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  loop_body->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
253ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   nullptr,
254ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   DataType::Type::kBool,
255ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   MemberOffset(42),
256ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   false,
257ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   kUnknownFieldIndex,
258ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   kUnknownClassDefIndex,
259ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   graph->GetDexFile(),
260ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                   0));
261d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction();
262ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  loop_body->AddInstruction(new (GetAllocator()) HGoto());
263ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko
264ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  exit->AddInstruction(new (GetAllocator()) HInstanceFieldGet(parameter,
265ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              nullptr,
266ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              DataType::Type::kBool,
267ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              MemberOffset(42),
268ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              false,
269ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              kUnknownFieldIndex,
270ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              kUnknownClassDefIndex,
271ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              graph->GetDexFile(),
272ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                              0));
273d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  HInstruction* field_get_in_exit = exit->GetLastInstruction();
274ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  exit->AddInstruction(new (GetAllocator()) HExit());
275d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
276d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
277d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
278d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(field_get_in_exit->GetBlock(), exit);
279d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
280badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  graph->BuildDominatorTree();
281e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray  {
282e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    SideEffectsAnalysis side_effects(graph);
283e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    side_effects.Run();
284827eedbfa882496407375f22b08243a38a5bd53bNicolas Geoffray    GVNOptimization(graph, side_effects).Run();
285e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray  }
286d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
287d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // Check that all field get instructions are still there.
288d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
289d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
290d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // The exit block is dominated by the loop header, whose field get
291d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // does not get killed by the loop flags.
292d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
293d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
294d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // Now remove the field set, and check that all field get instructions have been GVN'ed.
295d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  loop_body->RemoveInstruction(field_set);
296e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray  {
297e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    SideEffectsAnalysis side_effects(graph);
298e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    side_effects.Run();
299827eedbfa882496407375f22b08243a38a5bd53bNicolas Geoffray    GVNOptimization(graph, side_effects).Run();
300e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray  }
301d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
302d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr);
303d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr);
304d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr);
305d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray}
306d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
307d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray// Test that inner loops affect the side effects of the outer loop.
3084833f5a1990c76bc2be89504225fb13cca22bedfDavid BrazdilTEST_F(GVNTest, LoopSideEffects) {
30978e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames  static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();
31078e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames
311ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HGraph* graph = CreateGraph();
312ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph);
313d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(entry);
314d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->SetEntryBlock(entry);
315d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
316ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* outer_loop_header = new (GetAllocator()) HBasicBlock(graph);
317ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* outer_loop_body = new (GetAllocator()) HBasicBlock(graph);
318ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* outer_loop_exit = new (GetAllocator()) HBasicBlock(graph);
319ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* inner_loop_header = new (GetAllocator()) HBasicBlock(graph);
320ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* inner_loop_body = new (GetAllocator()) HBasicBlock(graph);
321ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HBasicBlock* inner_loop_exit = new (GetAllocator()) HBasicBlock(graph);
322d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
323d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(outer_loop_header);
324d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(outer_loop_body);
325d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(outer_loop_exit);
326d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(inner_loop_header);
327d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(inner_loop_body);
328d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  graph->AddBlock(inner_loop_exit);
329d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
330d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  entry->AddSuccessor(outer_loop_header);
331d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  outer_loop_header->AddSuccessor(outer_loop_body);
332d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  outer_loop_header->AddSuccessor(outer_loop_exit);
333d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  outer_loop_body->AddSuccessor(inner_loop_header);
334d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  inner_loop_header->AddSuccessor(inner_loop_body);
335d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  inner_loop_header->AddSuccessor(inner_loop_exit);
336d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  inner_loop_body->AddSuccessor(inner_loop_header);
337d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  inner_loop_exit->AddSuccessor(outer_loop_header);
338d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
339ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  HInstruction* parameter = new (GetAllocator()) HParameterValue(graph->GetDexFile(),
340ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 dex::TypeIndex(0),
341ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 0,
342ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 DataType::Type::kBool);
343d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  entry->AddInstruction(parameter);
344ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  entry->AddInstruction(new (GetAllocator()) HGoto());
345ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  outer_loop_header->AddInstruction(new (GetAllocator()) HSuspendCheck());
346ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  outer_loop_header->AddInstruction(new (GetAllocator()) HIf(parameter));
347ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  outer_loop_body->AddInstruction(new (GetAllocator()) HGoto());
348ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  inner_loop_header->AddInstruction(new (GetAllocator()) HSuspendCheck());
349ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  inner_loop_header->AddInstruction(new (GetAllocator()) HIf(parameter));
350ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  inner_loop_body->AddInstruction(new (GetAllocator()) HGoto());
351ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  inner_loop_exit->AddInstruction(new (GetAllocator()) HGoto());
352ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko  outer_loop_exit->AddInstruction(new (GetAllocator()) HExit());
353d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
354badd826664896d4a9628a5a89b78016894aa414bDavid Brazdil  graph->BuildDominatorTree();
355d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
356d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
357d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray      *outer_loop_header->GetLoopInformation()));
358d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
35978e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames  // Check that the only side effect of loops is to potentially trigger GC.
360d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  {
361d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray    // Make one block with a side effect.
362ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko    entry->AddInstruction(new (GetAllocator()) HInstanceFieldSet(parameter,
363ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 parameter,
364ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 nullptr,
365ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 DataType::Type::kReference,
366ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 MemberOffset(42),
367ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 false,
368ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 kUnknownFieldIndex,
369ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 kUnknownClassDefIndex,
370ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 graph->GetDexFile(),
371ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                                                 0));
372d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
373e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    SideEffectsAnalysis side_effects(graph);
374e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    side_effects.Run();
375d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
376854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
377854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
378854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
379854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
38078e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames    ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).Equals(kCanTriggerGC));
38178e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames    ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
382d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  }
383d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
384d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // Check that the side effects of the outer loop does not affect the inner loop.
385d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  {
386d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray    outer_loop_body->InsertInstructionBefore(
387ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko        new (GetAllocator()) HInstanceFieldSet(parameter,
388ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               parameter,
389ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               nullptr,
390ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               DataType::Type::kReference,
391ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               MemberOffset(42),
392ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               false,
393ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               kUnknownFieldIndex,
394ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               kUnknownClassDefIndex,
395ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               graph->GetDexFile(),
396ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               0),
397d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray        outer_loop_body->GetLastInstruction());
398d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
399e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    SideEffectsAnalysis side_effects(graph);
400e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    side_effects.Run();
401d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
402854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
403854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
404854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
405854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
40678e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames    ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).Equals(kCanTriggerGC));
407d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  }
408d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
409d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  // Check that the side effects of the inner loop affects the outer loop.
410d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  {
411d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray    outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
412d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray    inner_loop_body->InsertInstructionBefore(
413ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko        new (GetAllocator()) HInstanceFieldSet(parameter,
414ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               parameter,
415ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               nullptr,
416ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               DataType::Type::kReference,
417ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               MemberOffset(42),
418ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               false,
419ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               kUnknownFieldIndex,
420ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               kUnknownClassDefIndex,
421ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               graph->GetDexFile(),
422ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko                                               0),
423d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray        inner_loop_body->GetLastInstruction());
424d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
425e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    SideEffectsAnalysis side_effects(graph);
426e6f171514c9c499bd0a137aff6bd8a7a79d2682aNicolas Geoffray    side_effects.Run();
427d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray
428854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite());
429854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite());
430854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite());
431854a02b1b488327f80c544ca1119b386b8715c26Aart Bik    ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite());
432d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray  }
433d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray}
434d31cf3d55a0847c018c4eaa2b349b8eea509de64Nicolas Geoffray}  // namespace art
435