// Check that all field get instructions have been GVN'ed.
ASSERT_TRUE(then->GetFirstInstruction()->IsGoto());
ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto());
ASSERT_TRUE(join->GetFirstInstruction()->IsReturnVoid());
}
TEST_F(GVNTest, LoopFieldElimination) {
HBasicBlock* return_block = InitEntryMainExitGraphWithReturnVoid(); auto [pre_header, loop_header, loop_body] = CreateWhileLoop(return_block);
loop_header->SwapSuccessors(); // Move the loop exit to the "else" successor.
// Kill inside the loop body to prevent field gets inside the loop header // and the body to be GVN'ed.
HInstruction* field_set =
MakeIFieldSet(loop_body, parameter, parameter, DataType::Type::kBool, MemberOffset(42));
HInstruction* field_get_in_loop_body =
MakeIFieldGet(loop_body, parameter, DataType::Type::kBool, MemberOffset(42));
// Check that all field get instructions are still there.
ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header);
ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body); // The `return_block` is dominated by the `loop_header`, whose field get // does not get killed by the loop flags.
ASSERT_TRUE(field_get_in_return_block->GetBlock() == nullptr);
// Now remove the field set, and check that all field get instructions have been GVN'ed.
loop_body->RemoveInstruction(field_set);
GVNOptimization(graph_).Run();
// Test that inner loops affect the side effects of the outer loop.
TEST_F(GVNTest, LoopSideEffects) { staticconst SideEffects kCanTriggerGC = SideEffects::CanTriggerGC();
HBasicBlock* outer_loop_exit = InitEntryMainExitGraphWithReturnVoid(); auto [outer_preheader, outer_loop_header, inner_loop_exit] = CreateWhileLoop(outer_loop_exit);
outer_loop_header->SwapSuccessors(); // Move the loop exit to the "else" successor. auto [outer_loop_body, inner_loop_header, inner_loop_body] = CreateWhileLoop(inner_loop_exit);
inner_loop_header->SwapSuccessors(); // Move the loop exit to the "else" successor.
// Check that the only side effect of loops is to potentially trigger GC.
{ // Make one block with a side effect.
MakeIFieldSet(entry_block_, parameter, parameter, DataType::Type::kReference, MemberOffset(42));
// Check that the side effects of the outer loop does not affect the inner loop.
{
MakeIFieldSet(
outer_loop_body, parameter, parameter, DataType::Type::kReference, MemberOffset(42));
// Check that the side effects of the inner loop affects the outer loop.
{
outer_loop_body->RemoveInstruction(outer_loop_body->GetFirstInstruction());
MakeIFieldSet(
inner_loop_body, parameter, parameter, DataType::Type::kReference, MemberOffset(42));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.