summaryrefslogtreecommitdiff
path: root/compiler/optimizing/load_store_elimination_test.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/load_store_elimination_test.cc')
-rw-r--r--compiler/optimizing/load_store_elimination_test.cc1185
1 files changed, 0 insertions, 1185 deletions
diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc
index 8196a292d7..f71a4734a6 100644
--- a/compiler/optimizing/load_store_elimination_test.cc
+++ b/compiler/optimizing/load_store_elimination_test.cc
@@ -27,13 +27,6 @@ namespace art {
class LoadStoreEliminationTest : public OptimizingUnitTest {
public:
- AdjacencyListGraph SetupFromAdjacencyList(
- const std::string_view entry_name,
- const std::string_view exit_name,
- const std::vector<AdjacencyListGraph::Edge>& adj) {
- return AdjacencyListGraph(graph_, GetAllocator(), entry_name, exit_name, adj);
- }
-
void PerformLSE() {
graph_->BuildDominatorTree();
LoadStoreElimination lse(graph_, /*stats=*/ nullptr);
@@ -1449,1182 +1442,4 @@ TEST_F(LoadStoreEliminationTest, ArrayMergeDefault) {
EXPECT_TRUE(IsRemoved(alloc_w));
}
-// // ENTRY
-// obj = new Obj();
-// if (parameter_value) {
-// // LEFT
-// obj.field = 1;
-// call_func(obj);
-// foo_r = obj.field
-// } else {
-// // TO BE ELIMINATED
-// obj.field = 2;
-// // RIGHT
-// // TO BE ELIMINATED
-// foo_l = obj.field;
-// }
-// EXIT
-// return PHI(foo_l, foo_r)
-TEST_F(LoadStoreEliminationTest, PartialLoadElimination) {
- InitGraph();
- AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
- "exit_REAL",
- { { "entry", "left" },
- { "entry", "right" },
- { "left", "exit" },
- { "right", "exit" },
- { "exit", "exit_REAL" } }));
- HBasicBlock* entry = blks.Get("entry");
- HBasicBlock* left = blks.Get("left");
- HBasicBlock* right = blks.Get("right");
- HBasicBlock* exit = blks.Get("exit");
- HInstruction* bool_value = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
- HInstruction* c1 = graph_->GetIntConstant(1);
- HInstruction* c2 = graph_->GetIntConstant(2);
- HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- ScopedNullHandle<mirror::Class>(),
- false,
- 0,
- false);
- HInstruction* new_inst =
- new (GetAllocator()) HNewInstance(cls,
- 0,
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
- HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
- entry->AddInstruction(bool_value);
- entry->AddInstruction(cls);
- entry->AddInstruction(new_inst);
- entry->AddInstruction(if_inst);
- ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
- ManuallyBuildEnvFor(cls, &current_locals);
- new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_left = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c1,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* call_left = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 1,
- DataType::Type::kVoid,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* read_left = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(16),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_left = new (GetAllocator()) HGoto();
- call_left->AsInvoke()->SetRawInputAt(0, new_inst);
- left->AddInstruction(write_left);
- left->AddInstruction(call_left);
- left->AddInstruction(read_left);
- left->AddInstruction(goto_left);
- call_left->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c2,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(16),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* read_right = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(16),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_right = new (GetAllocator()) HGoto();
- right->AddInstruction(write_right);
- right->AddInstruction(read_right);
- right->AddInstruction(goto_right);
-
- HInstruction* phi_final =
- new (GetAllocator()) HPhi(GetAllocator(), 12, 2, DataType::Type::kInt32);
- phi_final->SetRawInputAt(0, read_left);
- phi_final->SetRawInputAt(1, read_right);
- HInstruction* return_exit = new (GetAllocator()) HReturn(phi_final);
- exit->AddPhi(phi_final->AsPhi());
- exit->AddInstruction(return_exit);
-
- // PerformLSE expects this to be empty.
- graph_->ClearDominanceInformation();
- PerformLSE();
-
- ASSERT_TRUE(IsRemoved(read_right));
- ASSERT_FALSE(IsRemoved(read_left));
- ASSERT_FALSE(IsRemoved(phi_final));
- ASSERT_TRUE(phi_final->GetInputs()[1] == c2);
- ASSERT_TRUE(phi_final->GetInputs()[0] == read_left);
- ASSERT_TRUE(IsRemoved(write_right));
-}
-
-// // ENTRY
-// obj = new Obj();
-// if (parameter_value) {
-// // LEFT
-// obj.field = 1;
-// call_func(obj);
-// // We don't know what obj.field is now we aren't able to eliminate the read below!
-// } else {
-// // DO NOT ELIMINATE
-// obj.field = 2;
-// // RIGHT
-// }
-// EXIT
-// return obj.field
-// TODO We eventually want to be able to eliminate the right write along with the final read but
-// will need either new blocks or new instructions.
-TEST_F(LoadStoreEliminationTest, PartialLoadPreserved) {
- InitGraph();
- AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
- "exit_REAL",
- { { "entry", "left" },
- { "entry", "right" },
- { "left", "exit" },
- { "right", "exit" },
- { "exit", "exit_REAL" } }));
- HBasicBlock* entry = blks.Get("entry");
- HBasicBlock* left = blks.Get("left");
- HBasicBlock* right = blks.Get("right");
- HBasicBlock* exit = blks.Get("exit");
- HInstruction* bool_value = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
- HInstruction* c1 = graph_->GetIntConstant(1);
- HInstruction* c2 = graph_->GetIntConstant(2);
- HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- ScopedNullHandle<mirror::Class>(),
- false,
- 0,
- false);
- HInstruction* new_inst =
- new (GetAllocator()) HNewInstance(cls,
- 0,
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
- HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
- entry->AddInstruction(bool_value);
- entry->AddInstruction(cls);
- entry->AddInstruction(new_inst);
- entry->AddInstruction(if_inst);
- ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
- ManuallyBuildEnvFor(cls, &current_locals);
- new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_left = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c1,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* call_left = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 1,
- DataType::Type::kVoid,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* goto_left = new (GetAllocator()) HGoto();
- call_left->AsInvoke()->SetRawInputAt(0, new_inst);
- left->AddInstruction(write_left);
- left->AddInstruction(call_left);
- left->AddInstruction(goto_left);
- call_left->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c2,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_right = new (GetAllocator()) HGoto();
- right->AddInstruction(write_right);
- right->AddInstruction(goto_right);
-
- HInstruction* read_bottom = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
- exit->AddInstruction(read_bottom);
- exit->AddInstruction(return_exit);
- // PerformLSE expects this to be empty.
- graph_->ClearDominanceInformation();
- PerformLSE();
-
- ASSERT_FALSE(IsRemoved(read_bottom));
- ASSERT_FALSE(IsRemoved(write_right));
-}
-
-// // ENTRY
-// obj = new Obj();
-// if (parameter_value) {
-// // LEFT
-// obj.field = 1;
-// call_func(obj);
-// // We don't know what obj.field is now we aren't able to eliminate the read below!
-// } else {
-// // DO NOT ELIMINATE
-// if (param2) {
-// obj.field = 2;
-// } else {
-// obj.field = 3;
-// }
-// // RIGHT
-// }
-// EXIT
-// return obj.field
-// TODO We eventually want to be able to eliminate the right write along with the final read but
-// will need either new blocks or new instructions.
-TEST_F(LoadStoreEliminationTest, PartialLoadPreserved2) {
- InitGraph();
- AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
- "exit_REAL",
- { { "entry", "left" },
- { "entry", "right_start" },
- { "left", "exit" },
- { "right_start", "right_first" },
- { "right_start", "right_second" },
- { "right_first", "right_end" },
- { "right_second", "right_end" },
- { "right_end", "exit" },
- { "exit", "exit_REAL" } }));
- HBasicBlock* entry = blks.Get("entry");
- HBasicBlock* left = blks.Get("left");
- HBasicBlock* right_start = blks.Get("right_start");
- HBasicBlock* right_first = blks.Get("right_first");
- HBasicBlock* right_second = blks.Get("right_second");
- HBasicBlock* right_end = blks.Get("right_end");
- HBasicBlock* exit = blks.Get("exit");
- HInstruction* bool_value = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
- HInstruction* bool_value_2 = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 2, DataType::Type::kBool);
- HInstruction* c1 = graph_->GetIntConstant(1);
- HInstruction* c2 = graph_->GetIntConstant(2);
- HInstruction* c3 = graph_->GetIntConstant(3);
- HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- ScopedNullHandle<mirror::Class>(),
- false,
- 0,
- false);
- HInstruction* new_inst =
- new (GetAllocator()) HNewInstance(cls,
- 0,
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
- HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
- entry->AddInstruction(bool_value);
- entry->AddInstruction(bool_value_2);
- entry->AddInstruction(cls);
- entry->AddInstruction(new_inst);
- entry->AddInstruction(if_inst);
- ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
- ManuallyBuildEnvFor(cls, &current_locals);
- new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_left = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c1,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* call_left = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 1,
- DataType::Type::kVoid,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* goto_left = new (GetAllocator()) HGoto();
- call_left->AsInvoke()->SetRawInputAt(0, new_inst);
- left->AddInstruction(write_left);
- left->AddInstruction(call_left);
- left->AddInstruction(goto_left);
- call_left->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* right_if = new (GetAllocator()) HIf(bool_value_2);
- right_start->AddInstruction(right_if);
-
- HInstruction* write_right_first = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c2,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_right_first = new (GetAllocator()) HGoto();
- right_first->AddInstruction(write_right_first);
- right_first->AddInstruction(goto_right_first);
-
- HInstruction* write_right_second = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c3,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_right_second = new (GetAllocator()) HGoto();
- right_second->AddInstruction(write_right_second);
- right_second->AddInstruction(goto_right_second);
-
- HInstruction* goto_right_end = new (GetAllocator()) HGoto();
- right_end->AddInstruction(goto_right_end);
-
- HInstruction* read_bottom = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
- exit->AddInstruction(read_bottom);
- exit->AddInstruction(return_exit);
- // PerformLSE expects this to be empty.
- graph_->ClearDominanceInformation();
- PerformLSE();
-
- ASSERT_FALSE(IsRemoved(read_bottom));
- EXPECT_FALSE(IsRemoved(write_right_first));
- EXPECT_FALSE(IsRemoved(write_right_second));
-}
-
-// // ENTRY
-// obj = new Obj();
-// if (parameter_value) {
-// // LEFT
-// // DO NOT ELIMINATE
-// escape(obj);
-// obj.field = 1;
-// } else {
-// // RIGHT
-// // ELIMINATE
-// obj.field = 2;
-// }
-// EXIT
-// ELIMINATE
-// return obj.field
-TEST_F(LoadStoreEliminationTest, PartialLoadElimination2) {
- InitGraph();
- AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
- "exit",
- { { "entry", "left" },
- { "entry", "right" },
- { "left", "breturn"},
- { "right", "breturn" },
- { "breturn", "exit" } }));
-#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
- GET_BLOCK(entry);
- GET_BLOCK(exit);
- GET_BLOCK(breturn);
- GET_BLOCK(left);
- GET_BLOCK(right);
-#undef GET_BLOCK
- HInstruction* bool_value = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
- HInstruction* c1 = graph_->GetIntConstant(1);
- HInstruction* c2 = graph_->GetIntConstant(2);
- HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- ScopedNullHandle<mirror::Class>(),
- false,
- 0,
- false);
- HInstruction* new_inst =
- new (GetAllocator()) HNewInstance(cls,
- 0,
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
- HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
- entry->AddInstruction(bool_value);
- entry->AddInstruction(cls);
- entry->AddInstruction(new_inst);
- entry->AddInstruction(if_inst);
- ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
- ManuallyBuildEnvFor(cls, &current_locals);
- new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* call_left = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 1,
- DataType::Type::kVoid,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* write_left = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c1,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_left = new (GetAllocator()) HGoto();
- call_left->AsInvoke()->SetRawInputAt(0, new_inst);
- left->AddInstruction(call_left);
- left->AddInstruction(write_left);
- left->AddInstruction(goto_left);
- call_left->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c2,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_right = new (GetAllocator()) HGoto();
- right->AddInstruction(write_right);
- right->AddInstruction(goto_right);
-
- HInstruction* read_bottom = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_exit = new (GetAllocator()) HReturn(read_bottom);
- breturn->AddInstruction(read_bottom);
- breturn->AddInstruction(return_exit);
-
- HInstruction* exit_instruction = new (GetAllocator()) HExit();
- exit->AddInstruction(exit_instruction);
- // PerformLSE expects this to be empty.
- graph_->ClearDominanceInformation();
- PerformLSE();
-
- ASSERT_TRUE(IsRemoved(read_bottom));
- ASSERT_TRUE(IsRemoved(write_right));
- ASSERT_FALSE(IsRemoved(write_left));
- ASSERT_FALSE(IsRemoved(call_left));
-}
-
-// // ENTRY
-// obj = new Obj();
-// if (parameter_value) {
-// // LEFT
-// // DO NOT ELIMINATE
-// obj.field = 1;
-// escape(obj);
-// return obj.field;
-// } else {
-// // RIGHT
-// // ELIMINATE
-// obj.field = 2;
-// return obj.field;
-// }
-// EXIT
-TEST_F(LoadStoreEliminationTest, PartialLoadElimination3) {
- InitGraph();
- AdjacencyListGraph blks(SetupFromAdjacencyList(
- "entry",
- "exit",
- { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } }));
-#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
- GET_BLOCK(entry);
- GET_BLOCK(exit);
- GET_BLOCK(left);
- GET_BLOCK(right);
-#undef GET_BLOCK
- HInstruction* bool_value = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
- HInstruction* c1 = graph_->GetIntConstant(1);
- HInstruction* c2 = graph_->GetIntConstant(2);
- HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- ScopedNullHandle<mirror::Class>(),
- false,
- 0,
- false);
- HInstruction* new_inst =
- new (GetAllocator()) HNewInstance(cls,
- 0,
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
- HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
- entry->AddInstruction(bool_value);
- entry->AddInstruction(cls);
- entry->AddInstruction(new_inst);
- entry->AddInstruction(if_inst);
- ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
- ManuallyBuildEnvFor(cls, &current_locals);
- new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_left = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c1,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* call_left = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 1,
- DataType::Type::kVoid,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* read_left = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_left = new (GetAllocator()) HReturn(read_left);
- call_left->AsInvoke()->SetRawInputAt(0, new_inst);
- left->AddInstruction(write_left);
- left->AddInstruction(call_left);
- left->AddInstruction(read_left);
- left->AddInstruction(return_left);
- call_left->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c2,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* read_right = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_right = new (GetAllocator()) HReturn(read_right);
- right->AddInstruction(write_right);
- right->AddInstruction(read_right);
- right->AddInstruction(return_right);
-
- HInstruction* exit_instruction = new (GetAllocator()) HExit();
- exit->AddInstruction(exit_instruction);
- // PerformLSE expects this to be empty.
- graph_->ClearDominanceInformation();
- PerformLSE();
-
- EXPECT_TRUE(IsRemoved(read_right));
- EXPECT_TRUE(IsRemoved(write_right));
- EXPECT_FALSE(IsRemoved(write_left));
- EXPECT_FALSE(IsRemoved(call_left));
- EXPECT_FALSE(IsRemoved(read_left));
-}
-
-// // ENTRY
-// obj = new Obj();
-// if (parameter_value) {
-// // LEFT
-// // DO NOT ELIMINATE
-// obj.field = 1;
-// while (true) {
-// bool esc = escape(obj);
-// // DO NOT ELIMINATE
-// obj.field = 3;
-// if (esc) break;
-// }
-// // ELIMINATE.
-// return obj.field;
-// } else {
-// // RIGHT
-// // ELIMINATE
-// obj.field = 2;
-// return obj.field;
-// }
-// EXIT
-TEST_F(LoadStoreEliminationTest, PartialLoadElimination4) {
- InitGraph();
- AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
- "exit",
- { { "entry", "entry_post" },
- { "entry_post", "right" },
- { "right", "exit" },
- { "entry_post", "left_pre" },
- { "left_pre", "left_loop" },
- { "left_loop", "left_loop" },
- { "left_loop", "left_finish" },
- { "left_finish", "exit" } }));
-#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
- GET_BLOCK(entry);
- GET_BLOCK(entry_post);
- GET_BLOCK(exit);
- GET_BLOCK(left_pre);
- GET_BLOCK(left_loop);
- GET_BLOCK(left_finish);
- GET_BLOCK(right);
-#undef GET_BLOCK
- // Left-loops first successor is the break.
- if (left_loop->GetSuccessors()[0] != left_finish) {
- left_loop->SwapSuccessors();
- }
- HInstruction* bool_value = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
- HInstruction* c1 = graph_->GetIntConstant(1);
- HInstruction* c2 = graph_->GetIntConstant(2);
- HInstruction* c3 = graph_->GetIntConstant(3);
- HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- ScopedNullHandle<mirror::Class>(),
- false,
- 0,
- false);
- HInstruction* new_inst =
- new (GetAllocator()) HNewInstance(cls,
- 0,
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
- HInstruction* goto_entry = new (GetAllocator()) HGoto();
- entry->AddInstruction(bool_value);
- entry->AddInstruction(cls);
- entry->AddInstruction(new_inst);
- entry->AddInstruction(goto_entry);
- ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
- ManuallyBuildEnvFor(cls, &current_locals);
- new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
- entry_post->AddInstruction(if_inst);
-
- HInstruction* write_left_pre = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c1,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_left_pre = new (GetAllocator()) HGoto();
- left_pre->AddInstruction(write_left_pre);
- left_pre->AddInstruction(goto_left_pre);
-
- HInstruction* suspend_left_loop = new (GetAllocator()) HSuspendCheck();
- HInstruction* call_left_loop = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 1,
- DataType::Type::kBool,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* write_left_loop = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c3,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* if_left_loop = new (GetAllocator()) HIf(call_left_loop);
- call_left_loop->AsInvoke()->SetRawInputAt(0, new_inst);
- left_loop->AddInstruction(suspend_left_loop);
- left_loop->AddInstruction(call_left_loop);
- left_loop->AddInstruction(write_left_loop);
- left_loop->AddInstruction(if_left_loop);
- suspend_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
- call_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* read_left_end = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_left_end = new (GetAllocator()) HReturn(read_left_end);
- left_finish->AddInstruction(read_left_end);
- left_finish->AddInstruction(return_left_end);
-
- HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c2,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* read_right = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_right = new (GetAllocator()) HReturn(read_right);
- right->AddInstruction(write_right);
- right->AddInstruction(read_right);
- right->AddInstruction(return_right);
-
- HInstruction* exit_instruction = new (GetAllocator()) HExit();
- exit->AddInstruction(exit_instruction);
- // PerformLSE expects this to be empty.
- graph_->ClearDominanceInformation();
- PerformLSE();
-
- EXPECT_FALSE(IsRemoved(write_left_pre));
- EXPECT_TRUE(IsRemoved(read_right));
- EXPECT_TRUE(IsRemoved(write_right));
- EXPECT_FALSE(IsRemoved(write_left_loop));
- EXPECT_FALSE(IsRemoved(call_left_loop));
- EXPECT_TRUE(IsRemoved(read_left_end));
-}
-
-// // ENTRY
-// obj = new Obj();
-// if (parameter_value) {
-// // LEFT
-// // DO NOT ELIMINATE
-// obj.field = 1;
-// while (true) {
-// bool esc = escape(obj);
-// if (esc) break;
-// // DO NOT ELIMINATE
-// obj.field = 3;
-// }
-// } else {
-// // RIGHT
-// // DO NOT ELIMINATE
-// obj.field = 2;
-// }
-// // DO NOT ELIMINATE
-// return obj.field;
-// EXIT
-TEST_F(LoadStoreEliminationTest, PartialLoadPreserved3) {
- InitGraph();
- AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
- "exit",
- { { "entry", "entry_post" },
- { "entry_post", "right" },
- { "right", "return_block" },
- { "entry_post", "left_pre" },
- { "left_pre", "left_loop" },
- { "left_loop", "left_loop_post" },
- { "left_loop_post", "left_loop" },
- { "left_loop", "return_block" },
- { "return_block", "exit" } }));
-#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
- GET_BLOCK(entry);
- GET_BLOCK(entry_post);
- GET_BLOCK(exit);
- GET_BLOCK(return_block);
- GET_BLOCK(left_pre);
- GET_BLOCK(left_loop);
- GET_BLOCK(left_loop_post);
- GET_BLOCK(right);
-#undef GET_BLOCK
- // Left-loops first successor is the break.
- if (left_loop->GetSuccessors()[0] != return_block) {
- left_loop->SwapSuccessors();
- }
- HInstruction* bool_value = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
- HInstruction* c1 = graph_->GetIntConstant(1);
- HInstruction* c2 = graph_->GetIntConstant(2);
- HInstruction* c3 = graph_->GetIntConstant(3);
- HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- ScopedNullHandle<mirror::Class>(),
- false,
- 0,
- false);
- HInstruction* new_inst =
- new (GetAllocator()) HNewInstance(cls,
- 0,
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
- HInstruction* goto_entry = new (GetAllocator()) HGoto();
- entry->AddInstruction(bool_value);
- entry->AddInstruction(cls);
- entry->AddInstruction(new_inst);
- entry->AddInstruction(goto_entry);
- ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
- ManuallyBuildEnvFor(cls, &current_locals);
- new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
- entry_post->AddInstruction(if_inst);
-
- HInstruction* write_left_pre = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c1,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_left_pre = new (GetAllocator()) HGoto();
- left_pre->AddInstruction(write_left_pre);
- left_pre->AddInstruction(goto_left_pre);
-
- HInstruction* suspend_left_loop = new (GetAllocator()) HSuspendCheck();
- HInstruction* call_left_loop = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 1,
- DataType::Type::kBool,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* if_left_loop = new (GetAllocator()) HIf(call_left_loop);
- call_left_loop->AsInvoke()->SetRawInputAt(0, new_inst);
- left_loop->AddInstruction(suspend_left_loop);
- left_loop->AddInstruction(call_left_loop);
- left_loop->AddInstruction(if_left_loop);
- suspend_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
- call_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_left_loop = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c3,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_left_loop = new (GetAllocator()) HGoto();
- left_loop_post->AddInstruction(write_left_loop);
- left_loop_post->AddInstruction(goto_left_loop);
-
- HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c2,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_right = new (GetAllocator()) HGoto();
- right->AddInstruction(write_right);
- right->AddInstruction(goto_right);
-
- HInstruction* read_return = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_final = new (GetAllocator()) HReturn(read_return);
- return_block->AddInstruction(read_return);
- return_block->AddInstruction(return_final);
-
- HInstruction* exit_instruction = new (GetAllocator()) HExit();
- exit->AddInstruction(exit_instruction);
- // PerformLSE expects this to be empty.
- graph_->ClearDominanceInformation();
- PerformLSE();
-
- EXPECT_FALSE(IsRemoved(write_left_pre));
- EXPECT_FALSE(IsRemoved(read_return));
- EXPECT_FALSE(IsRemoved(write_right));
- EXPECT_FALSE(IsRemoved(write_left_loop));
- EXPECT_FALSE(IsRemoved(call_left_loop));
-}
-
-// // ENTRY
-// obj = new Obj();
-// if (parameter_value) {
-// // LEFT
-// // ELIMINATE (not visible since always overridden by obj.field = 3)
-// obj.field = 1;
-// while (true) {
-// bool stop = should_stop();
-// // DO NOT ELIMINATE (visible by read at end)
-// obj.field = 3;
-// if (stop) break;
-// }
-// } else {
-// // RIGHT
-// // DO NOT ELIMINATE
-// obj.field = 2;
-// escape(obj);
-// }
-// // DO NOT ELIMINATE
-// return obj.field;
-// EXIT
-TEST_F(LoadStoreEliminationTest, PartialLoadPreserved4) {
- InitGraph();
- AdjacencyListGraph blks(SetupFromAdjacencyList("entry",
- "exit",
- { { "entry", "entry_post" },
- { "entry_post", "right" },
- { "right", "return_block" },
- { "entry_post", "left_pre" },
- { "left_pre", "left_loop" },
- { "left_loop", "left_loop" },
- { "left_loop", "return_block" },
- { "return_block", "exit" } }));
-#define GET_BLOCK(name) HBasicBlock* name = blks.Get(#name)
- GET_BLOCK(entry);
- GET_BLOCK(entry_post);
- GET_BLOCK(exit);
- GET_BLOCK(return_block);
- GET_BLOCK(left_pre);
- GET_BLOCK(left_loop);
- GET_BLOCK(right);
-#undef GET_BLOCK
- // Left-loops first successor is the break.
- if (left_loop->GetSuccessors()[0] != return_block) {
- left_loop->SwapSuccessors();
- }
- HInstruction* bool_value = new (GetAllocator())
- HParameterValue(graph_->GetDexFile(), dex::TypeIndex(1), 1, DataType::Type::kBool);
- HInstruction* c1 = graph_->GetIntConstant(1);
- HInstruction* c2 = graph_->GetIntConstant(2);
- HInstruction* c3 = graph_->GetIntConstant(3);
- HInstruction* cls = new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- ScopedNullHandle<mirror::Class>(),
- false,
- 0,
- false);
- HInstruction* new_inst =
- new (GetAllocator()) HNewInstance(cls,
- 0,
- dex::TypeIndex(10),
- graph_->GetDexFile(),
- false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
- HInstruction* goto_entry = new (GetAllocator()) HGoto();
- entry->AddInstruction(bool_value);
- entry->AddInstruction(cls);
- entry->AddInstruction(new_inst);
- entry->AddInstruction(goto_entry);
- ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction));
- ManuallyBuildEnvFor(cls, &current_locals);
- new_inst->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* if_inst = new (GetAllocator()) HIf(bool_value);
- entry_post->AddInstruction(if_inst);
-
- HInstruction* write_left_pre = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c1,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* goto_left_pre = new (GetAllocator()) HGoto();
- left_pre->AddInstruction(write_left_pre);
- left_pre->AddInstruction(goto_left_pre);
-
- HInstruction* suspend_left_loop = new (GetAllocator()) HSuspendCheck();
- HInstruction* call_left_loop = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 0,
- DataType::Type::kBool,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* write_left_loop = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c3,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* if_left_loop = new (GetAllocator()) HIf(call_left_loop);
- left_loop->AddInstruction(suspend_left_loop);
- left_loop->AddInstruction(call_left_loop);
- left_loop->AddInstruction(write_left_loop);
- left_loop->AddInstruction(if_left_loop);
- suspend_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
- call_left_loop->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
- c2,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* call_right = new (GetAllocator())
- HInvokeStaticOrDirect(GetAllocator(),
- 1,
- DataType::Type::kBool,
- 0,
- { nullptr, 0 },
- nullptr,
- {},
- InvokeType::kStatic,
- { nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
- HInstruction* goto_right = new (GetAllocator()) HGoto();
- call_right->AsInvoke()->SetRawInputAt(0, new_inst);
- right->AddInstruction(write_right);
- right->AddInstruction(call_right);
- right->AddInstruction(goto_right);
- call_right->CopyEnvironmentFrom(cls->GetEnvironment());
-
- HInstruction* read_return = new (GetAllocator()) HInstanceFieldGet(new_inst,
- nullptr,
- DataType::Type::kInt32,
- MemberOffset(10),
- false,
- 0,
- 0,
- graph_->GetDexFile(),
- 0);
- HInstruction* return_final = new (GetAllocator()) HReturn(read_return);
- return_block->AddInstruction(read_return);
- return_block->AddInstruction(return_final);
-
- HInstruction* exit_instruction = new (GetAllocator()) HExit();
- exit->AddInstruction(exit_instruction);
- // PerformLSE expects this to be empty.
- graph_->ClearDominanceInformation();
- PerformLSE();
-
- EXPECT_FALSE(IsRemoved(read_return));
- EXPECT_FALSE(IsRemoved(write_right));
- EXPECT_FALSE(IsRemoved(write_left_loop));
- EXPECT_FALSE(IsRemoved(call_left_loop));
- EXPECT_TRUE(IsRemoved(write_left_pre));
- EXPECT_FALSE(IsRemoved(call_right));
-}
} // namespace art