diff options
author | 2024-08-15 07:40:38 +0000 | |
---|---|---|
committer | 2024-08-21 09:12:50 +0000 | |
commit | c08fb725b561ead05dc120f2e92ea5228d14eec0 (patch) | |
tree | c306cd68d8f26a33b3c45e2f07db695dccc00e6e | |
parent | 1ea8807afeea6cd48127449cbd10458cc32cf4ce (diff) |
Change `MakeCondition()` to take `IfCondition`...
... instead of the instruction type argument.
And continue with loop construction cleanup in gtests.
Test: m test-art-host-gtest
Change-Id: I8cb83ae0c6d3cdb2a2ee4da0608cfeb69df722eb
-rw-r--r-- | compiler/optimizing/bounds_check_elimination_test.cc | 56 | ||||
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 48 | ||||
-rw-r--r-- | compiler/optimizing/constant_folding_test.cc | 145 | ||||
-rw-r--r-- | compiler/optimizing/graph_test.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/gvn_test.cc | 155 | ||||
-rw-r--r-- | compiler/optimizing/induction_var_analysis_test.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/induction_var_range_test.cc | 7 | ||||
-rw-r--r-- | compiler/optimizing/licm_test.cc | 52 | ||||
-rw-r--r-- | compiler/optimizing/load_store_analysis_test.cc | 303 | ||||
-rw-r--r-- | compiler/optimizing/load_store_elimination_test.cc | 12 | ||||
-rw-r--r-- | compiler/optimizing/nodes_test.cc | 22 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_unit_test.h | 23 | ||||
-rw-r--r-- | compiler/optimizing/ssa_liveness_analysis_test.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/superblock_cloner_test.cc | 7 |
14 files changed, 279 insertions, 557 deletions
diff --git a/compiler/optimizing/bounds_check_elimination_test.cc b/compiler/optimizing/bounds_check_elimination_test.cc index 05bd35dbc7..246cd10ca7 100644 --- a/compiler/optimizing/bounds_check_elimination_test.cc +++ b/compiler/optimizing/bounds_check_elimination_test.cc @@ -73,7 +73,7 @@ TEST_F(BoundsCheckEliminationTest, NarrowingRangeArrayBoundsElimination) { HInstruction* constant_0 = graph_->GetIntConstant(0); HBasicBlock* block1 = AddNewBlock(); - HInstruction* cmp = MakeCondition<HGreaterThanOrEqual>(block1, parameter2, constant_0); + HInstruction* cmp = MakeCondition(block1, kCondGE, parameter2, constant_0); MakeIf(block1, cmp); entry->AddSuccessor(block1); @@ -86,7 +86,7 @@ TEST_F(BoundsCheckEliminationTest, NarrowingRangeArrayBoundsElimination) { HBasicBlock* block3 = AddNewBlock(); null_check = MakeNullCheck(block3, parameter1); array_length = MakeArrayLength(block3, null_check); - cmp = MakeCondition<HLessThan>(block3, parameter2, array_length); + cmp = MakeCondition(block3, kCondLT, parameter2, array_length); MakeIf(block3, cmp); HBasicBlock* block4 = AddNewBlock(); @@ -137,7 +137,7 @@ TEST_F(BoundsCheckEliminationTest, OverflowArrayBoundsElimination) { HInstruction* constant_max_int = graph_->GetIntConstant(INT_MAX); HBasicBlock* block1 = AddNewBlock(); - HInstruction* cmp = MakeCondition<HLessThanOrEqual>(block1, parameter2, constant_0); + HInstruction* cmp = MakeCondition(block1, kCondLE, parameter2, constant_0); MakeIf(block1, cmp); entry->AddSuccessor(block1); @@ -145,7 +145,7 @@ TEST_F(BoundsCheckEliminationTest, OverflowArrayBoundsElimination) { HInstruction* add = MakeBinOp<HAdd>(block2, DataType::Type::kInt32, parameter2, constant_max_int); HNullCheck* null_check = MakeNullCheck(block2, parameter1); HArrayLength* array_length = MakeArrayLength(block2, null_check); - HInstruction* cmp2 = MakeCondition<HGreaterThanOrEqual>(block2, add, array_length); + HInstruction* cmp2 = MakeCondition(block2, kCondGE, add, array_length); MakeIf(block2, cmp2); HBasicBlock* block3 = AddNewBlock(); @@ -184,7 +184,7 @@ TEST_F(BoundsCheckEliminationTest, UnderflowArrayBoundsElimination) { HBasicBlock* block1 = AddNewBlock(); HNullCheck* null_check = MakeNullCheck(block1, parameter1); HArrayLength* array_length = MakeArrayLength(block1, null_check); - HInstruction* cmp = MakeCondition<HGreaterThanOrEqual>(block1, parameter2, array_length); + HInstruction* cmp = MakeCondition(block1, kCondGE, parameter2, array_length); MakeIf(block1, cmp); entry->AddSuccessor(block1); @@ -192,7 +192,7 @@ TEST_F(BoundsCheckEliminationTest, UnderflowArrayBoundsElimination) { HInstruction* sub1 = MakeBinOp<HSub>(block2, DataType::Type::kInt32, parameter2, constant_max_int); HInstruction* sub2 = MakeBinOp<HSub>(block2, DataType::Type::kInt32, sub1, constant_max_int); - HInstruction* cmp2 = MakeCondition<HLessThanOrEqual>(block2, sub2, constant_0); + HInstruction* cmp2 = MakeCondition(block2, kCondLE, sub2, constant_0); MakeIf(block2, cmp2); HBasicBlock* block3 = AddNewBlock(); @@ -259,13 +259,8 @@ HInstruction* BoundsCheckEliminationTest::BuildSSAGraph1(int initial, auto [phi, add] = MakeLinearLoopVar(loop_header, loop_body, initial, increment); HInstruction* null_check = MakeNullCheck(loop_header, parameter); HInstruction* array_length = MakeArrayLength(loop_header, null_check); - HInstruction* cmp = nullptr; - if (cond == kCondGE) { - cmp = MakeCondition<HGreaterThanOrEqual>(loop_header, phi, array_length); - } else { - DCHECK(cond == kCondGT); - cmp = MakeCondition<HGreaterThan>(loop_header, phi, array_length); - } + DCHECK(cond == kCondGE || cond == kCondGT) << cond; + HInstruction* cmp = MakeCondition(loop_header, cond, phi, array_length); MakeIf(loop_header, cmp); null_check = MakeNullCheck(loop_body, parameter); @@ -336,13 +331,8 @@ HInstruction* BoundsCheckEliminationTest::BuildSSAGraph2(int initial, HInstruction* array_length = MakeArrayLength(pre_header, null_check); auto [phi, add] = MakeLinearLoopVar(loop_header, loop_body, array_length, constant_minus_1); - HInstruction* cmp = nullptr; - if (cond == kCondLE) { - cmp = MakeCondition<HLessThanOrEqual>(loop_header, phi, constant_initial); - } else { - DCHECK(cond == kCondLT); - cmp = MakeCondition<HLessThan>(loop_header, phi, constant_initial); - } + DCHECK(cond == kCondLE || cond == kCondLT) << cond; + HInstruction* cmp = MakeCondition(loop_header, cond, phi, constant_initial); MakeIf(loop_header, cmp); null_check = MakeNullCheck(loop_body, parameter); @@ -403,13 +393,8 @@ HInstruction* BoundsCheckEliminationTest::BuildSSAGraph3(int initial, MakeNewArray(pre_header, /* cls= */ constant_10, /* length= */ constant_10); auto [phi, add] = MakeLinearLoopVar(loop_header, loop_body, initial, increment); - HInstruction* cmp = nullptr; - if (cond == kCondGE) { - cmp = MakeCondition<HGreaterThanOrEqual>(loop_header, phi, constant_10); - } else { - DCHECK(cond == kCondGT); - cmp = MakeCondition<HGreaterThan>(loop_header, phi, constant_10); - } + DCHECK(cond == kCondGE || cond == kCondGT) << cond; + HInstruction* cmp = MakeCondition(loop_header, cond, phi, constant_10); MakeIf(loop_header, cmp); HNullCheck* null_check = MakeNullCheck(loop_body, new_array); @@ -464,13 +449,8 @@ HInstruction* BoundsCheckEliminationTest::BuildSSAGraph4(int initial, IfConditio auto [phi, add] = MakeLinearLoopVar(loop_header, loop_body, initial, /*increment=*/ 1); HInstruction* null_check = MakeNullCheck(loop_header, parameter); HInstruction* array_length = MakeArrayLength(loop_header, null_check); - HInstruction* cmp = nullptr; - if (cond == kCondGE) { - cmp = MakeCondition<HGreaterThanOrEqual>(loop_header, phi, array_length); - } else { - DCHECK(cond == kCondGT); - cmp = MakeCondition<HGreaterThan>(loop_header, phi, array_length); - } + DCHECK(cond == kCondGE || cond == kCondGT) << cond; + HInstruction* cmp = MakeCondition(loop_header, cond, phi, array_length); MakeIf(loop_header, cmp); null_check = MakeNullCheck(loop_body, parameter); @@ -532,7 +512,7 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { HNullCheck* null_check = MakeNullCheck(outer_header, parameter); HArrayLength* array_length = MakeArrayLength(outer_header, null_check); HAdd* add = MakeBinOp<HAdd>(outer_header, DataType::Type::kInt32, array_length, constant_minus_1); - HInstruction* cmp = MakeCondition<HGreaterThanOrEqual>(outer_header, phi_i, add); + HInstruction* cmp = MakeCondition(outer_header, kCondGE, phi_i, add); MakeIf(outer_header, cmp); auto [phi_j, add_j] = @@ -541,7 +521,7 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { array_length = MakeArrayLength(inner_header, null_check); HSub* sub = MakeBinOp<HSub>(inner_header, DataType::Type::kInt32, array_length, phi_i); add = MakeBinOp<HAdd>(inner_header, DataType::Type::kInt32, sub, constant_minus_1); - cmp = MakeCondition<HGreaterThanOrEqual>(inner_header, phi_j, add); + cmp = MakeCondition(inner_header, kCondGE, phi_j, add); MakeIf(inner_header, cmp); null_check = MakeNullCheck(inner_body_compare, parameter); @@ -556,7 +536,7 @@ TEST_F(BoundsCheckEliminationTest, BubbleSortArrayBoundsElimination) { HBoundsCheck* bounds_check2 = MakeBoundsCheck(inner_body_compare, j_plus_1, array_length); HArrayGet* array_get_j_plus_1 = MakeArrayGet(inner_body_compare, null_check, bounds_check2, DataType::Type::kInt32); - cmp = MakeCondition<HGreaterThanOrEqual>(inner_body_compare, array_get_j, array_get_j_plus_1); + cmp = MakeCondition(inner_body_compare, kCondGE, array_get_j, array_get_j_plus_1); MakeIf(inner_body_compare, cmp); j_plus_1 = MakeBinOp<HAdd>(inner_body_swap, DataType::Type::kInt32, phi_j, constant_1); @@ -616,7 +596,7 @@ TEST_F(BoundsCheckEliminationTest, ModArrayBoundsElimination) { MakeNewArray(pre_header, /* cls= */ constant_10, /* length= */ constant_10); auto [phi, add] = MakeLinearLoopVar(loop_header, loop_body, /*initial=*/ 0, /*increment=*/ 1); - HInstruction* cmp = MakeCondition<HGreaterThanOrEqual>(loop_header, phi, constant_200); + HInstruction* cmp = MakeCondition(loop_header, kCondGE, phi, constant_200); MakeIf(loop_header, cmp); ////////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index e3366760ca..7365f0fb7f 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -424,7 +424,7 @@ TEST_F(CodegenTest, NonMaterializedCondition) { entry->AddSuccessor(first_block); HIntConstant* constant0 = graph->GetIntConstant(0); HIntConstant* constant1 = graph->GetIntConstant(1); - HEqual* equal = MakeCondition<HEqual>(first_block, constant0, constant0); + HInstruction* equal = MakeCondition(first_block, kCondEQ, constant0, constant0); MakeIf(first_block, equal); HBasicBlock* then_block = new (GetAllocator()) HBasicBlock(graph); @@ -491,7 +491,7 @@ TEST_F(CodegenTest, MaterializedCondition1) { HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]); HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]); - HInstruction* cmp_lt = MakeCondition<HLessThan>(code_block, cst_lhs, cst_rhs); + HInstruction* cmp_lt = MakeCondition(code_block, kCondLT, cst_lhs, cst_rhs); MakeReturn(code_block, cmp_lt); graph->BuildDominatorTree(); @@ -547,7 +547,7 @@ TEST_F(CodegenTest, MaterializedCondition2) { HIntConstant* cst_lhs = graph->GetIntConstant(lhs[i]); HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]); - HInstruction* cmp_lt = MakeCondition<HLessThan>(if_block, cst_lhs, cst_rhs); + HInstruction* cmp_lt = MakeCondition(if_block, kCondLT, cst_lhs, cst_rhs); // We insert a fake instruction to separate the HIf from the HLessThan // and force the materialization of the condition. HInstruction* force_materialization = @@ -599,87 +599,61 @@ void CodegenTest::TestComparison(IfCondition condition, int64_t j, DataType::Type type, const CodegenTargetConfig target_config) { - HGraph* graph = CreateGraph(); - - HBasicBlock* entry_block = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(entry_block); - graph->SetEntryBlock(entry_block); - MakeGoto(entry_block); - - HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(block); - - HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(exit_block); - graph->SetExitBlock(exit_block); - MakeExit(exit_block); - - entry_block->AddSuccessor(block); - block->AddSuccessor(exit_block); + HBasicBlock* block = InitEntryMainExitGraph(); HInstruction* op1; HInstruction* op2; if (type == DataType::Type::kInt32) { - op1 = graph->GetIntConstant(i); - op2 = graph->GetIntConstant(j); + op1 = graph_->GetIntConstant(i); + op2 = graph_->GetIntConstant(j); } else { DCHECK_EQ(type, DataType::Type::kInt64); - op1 = graph->GetLongConstant(i); - op2 = graph->GetLongConstant(j); + op1 = graph_->GetLongConstant(i); + op2 = graph_->GetLongConstant(j); } - HInstruction* comparison = nullptr; bool expected_result = false; const uint64_t x = i; const uint64_t y = j; switch (condition) { case kCondEQ: - comparison = MakeCondition<HEqual>(block, op1, op2); expected_result = (i == j); break; case kCondNE: - comparison = MakeCondition<HNotEqual>(block, op1, op2); expected_result = (i != j); break; case kCondLT: - comparison = MakeCondition<HLessThan>(block, op1, op2); expected_result = (i < j); break; case kCondLE: - comparison = MakeCondition<HLessThanOrEqual>(block, op1, op2); expected_result = (i <= j); break; case kCondGT: - comparison = MakeCondition<HGreaterThan>(block, op1, op2); expected_result = (i > j); break; case kCondGE: - comparison = MakeCondition<HGreaterThanOrEqual>(block, op1, op2); expected_result = (i >= j); break; case kCondB: - comparison = MakeCondition<HBelow>(block, op1, op2); expected_result = (x < y); break; case kCondBE: - comparison = MakeCondition<HBelowOrEqual>(block, op1, op2); expected_result = (x <= y); break; case kCondA: - comparison = MakeCondition<HAbove>(block, op1, op2); expected_result = (x > y); break; case kCondAE: - comparison = MakeCondition<HAboveOrEqual>(block, op1, op2); expected_result = (x >= y); break; } + HInstruction* comparison = MakeCondition(block, condition, op1, op2); MakeReturn(block, comparison); - graph->BuildDominatorTree(); + graph_->BuildDominatorTree(); std::unique_ptr<CompilerOptions> compiler_options = CommonCompilerTest::CreateCompilerOptions(target_config.GetInstructionSet(), "default"); - RunCode(target_config, *compiler_options, graph, [](HGraph*) {}, true, expected_result); + RunCode(target_config, *compiler_options, graph_, [](HGraph*) {}, true, expected_result); } TEST_F(CodegenTest, ComparisonsInt) { diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc index 7ff8649fa9..95d3c67957 100644 --- a/compiler/optimizing/constant_folding_test.cc +++ b/compiler/optimizing/constant_folding_test.cc @@ -34,7 +34,7 @@ namespace art HIDDEN { */ class ConstantFoldingTest : public CommonCompilerTest, public OptimizingUnitTestHelper { public: - ConstantFoldingTest() : graph_(nullptr) { } + ConstantFoldingTest() { } void TestCode(const std::vector<uint16_t>& data, const std::string& expected_before, @@ -82,8 +82,6 @@ class ConstantFoldingTest : public CommonCompilerTest, public OptimizingUnitTest std::string actual_after_dce = printer_after_dce.str(); EXPECT_EQ(expected_after_dce, actual_after_dce); } - - HGraph* graph_; }; /** @@ -735,107 +733,92 @@ TEST_F(ConstantFoldingTest, ConstantCondition) { * in the bytecode, we need to set up the graph explicitly. */ TEST_F(ConstantFoldingTest, UnsignedComparisonsWithZero) { - graph_ = CreateGraph(); - HBasicBlock* entry_block = new (GetAllocator()) HBasicBlock(graph_); - graph_->AddBlock(entry_block); - graph_->SetEntryBlock(entry_block); - HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph_); - graph_->AddBlock(block); - HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph_); - graph_->AddBlock(exit_block); - graph_->SetExitBlock(exit_block); - entry_block->AddSuccessor(block); - block->AddSuccessor(exit_block); + HBasicBlock* block = InitEntryMainExitGraph(); // Make various unsigned comparisons with zero against a parameter. HInstruction* parameter = MakeParam(DataType::Type::kInt32); - MakeGoto(entry_block); - HInstruction* zero = graph_->GetIntConstant(0); - HInstruction* last; - block->AddInstruction(last = new (GetAllocator()) HAbove(zero, parameter)); - block->AddInstruction(new (GetAllocator()) HSelect(last, parameter, parameter, 0)); - block->AddInstruction(last = new (GetAllocator()) HAbove(parameter, zero)); - block->AddInstruction(new (GetAllocator()) HSelect(last, parameter, parameter, 0)); - block->AddInstruction(last = new (GetAllocator()) HAboveOrEqual(zero, parameter)); - block->AddInstruction(new (GetAllocator()) HSelect(last, parameter, parameter, 0)); - block->AddInstruction(last = new (GetAllocator()) HAboveOrEqual(parameter, zero)); - block->AddInstruction(new (GetAllocator()) HSelect(last, parameter, parameter, 0)); - block->AddInstruction(last = new (GetAllocator()) HBelow(zero, parameter)); - block->AddInstruction(new (GetAllocator()) HSelect(last, parameter, parameter, 0)); - block->AddInstruction(last = new (GetAllocator()) HBelow(parameter, zero)); - block->AddInstruction(new (GetAllocator()) HSelect(last, parameter, parameter, 0)); - block->AddInstruction(last = new (GetAllocator()) HBelowOrEqual(zero, parameter)); - block->AddInstruction(new (GetAllocator()) HSelect(last, parameter, parameter, 0)); - block->AddInstruction(last = new (GetAllocator()) HBelowOrEqual(parameter, zero)); - block->AddInstruction(new (GetAllocator()) HSelect(last, parameter, parameter, 0)); + HInstruction* a1 = MakeCondition(block, kCondA, zero, parameter); + MakeSelect(block, a1, parameter, parameter); + HInstruction* a2 = MakeCondition(block, kCondA, parameter, zero); + MakeSelect(block, a2, parameter, parameter); + HInstruction* ae1 = MakeCondition(block, kCondAE, zero, parameter); + MakeSelect(block, ae1, parameter, parameter); + HInstruction* ae2 = MakeCondition(block, kCondAE, parameter, zero); + MakeSelect(block, ae2, parameter, parameter); + HInstruction* b1 = MakeCondition(block, kCondB, zero, parameter); + MakeSelect(block, b1, parameter, parameter); + HInstruction* b2 = MakeCondition(block, kCondB, parameter, zero); + MakeSelect(block, b2, parameter, parameter); + HInstruction* be1 = MakeCondition(block, kCondBE, zero, parameter); + MakeSelect(block, be1, parameter, parameter); + HInstruction* be2 = MakeCondition(block, kCondBE, parameter, zero); + MakeSelect(block, be2, parameter, parameter); MakeReturn(block, zero); - MakeExit(exit_block); - graph_->BuildDominatorTree(); const std::string expected_before = "BasicBlock 0, succ: 1\n" - " 0: ParameterValue [18, 18, 17, 16, 16, 15, 14, 14, 13, 12, 12, 11, 10, 10, 9, " - "8, 8, 7, 6, 6, 5, 4, 4, 3]\n" - " 2: IntConstant [19, 17, 15, 13, 11, 9, 7, 5, 3]\n" - " 1: Goto 1\n" + " 2: ParameterValue [19, 19, 18, 17, 17, 16, 15, 15, 14, 13, 13, 12, 11, 11, 10, " + "9, 9, 8, 7, 7, 6, 5, 5, 4]\n" + " 3: IntConstant [20, 18, 16, 14, 12, 10, 8, 6, 4]\n" + " 0: Goto 1\n" "BasicBlock 1, pred: 0, succ: 2\n" - " 3: Above(2, 0) [4]\n" - " 4: Select(0, 0, 3)\n" - " 5: Above(0, 2) [6]\n" - " 6: Select(0, 0, 5)\n" - " 7: AboveOrEqual(2, 0) [8]\n" - " 8: Select(0, 0, 7)\n" - " 9: AboveOrEqual(0, 2) [10]\n" - " 10: Select(0, 0, 9)\n" - " 11: Below(2, 0) [12]\n" - " 12: Select(0, 0, 11)\n" - " 13: Below(0, 2) [14]\n" - " 14: Select(0, 0, 13)\n" - " 15: BelowOrEqual(2, 0) [16]\n" - " 16: Select(0, 0, 15)\n" - " 17: BelowOrEqual(0, 2) [18]\n" - " 18: Select(0, 0, 17)\n" - " 19: Return(2)\n" + " 4: Above(3, 2) [5]\n" + " 5: Select(2, 2, 4)\n" + " 6: Above(2, 3) [7]\n" + " 7: Select(2, 2, 6)\n" + " 8: AboveOrEqual(3, 2) [9]\n" + " 9: Select(2, 2, 8)\n" + " 10: AboveOrEqual(2, 3) [11]\n" + " 11: Select(2, 2, 10)\n" + " 12: Below(3, 2) [13]\n" + " 13: Select(2, 2, 12)\n" + " 14: Below(2, 3) [15]\n" + " 15: Select(2, 2, 14)\n" + " 16: BelowOrEqual(3, 2) [17]\n" + " 17: Select(2, 2, 16)\n" + " 18: BelowOrEqual(2, 3) [19]\n" + " 19: Select(2, 2, 18)\n" + " 20: Return(3)\n" "BasicBlock 2, pred: 1\n" - " 20: Exit\n"; + " 1: Exit\n"; const std::string expected_after_cf = "BasicBlock 0, succ: 1\n" - " 0: ParameterValue [18, 18, 17, 16, 16, 14, 14, 12, 12, 11, 10, 10, " - "8, 8, 7, 6, 6, 5, 4, 4]\n" - " 2: IntConstant [14, 4, 19, 17, 11, 7, 5]\n" - " 21: IntConstant [16, 10]\n" - " 1: Goto 1\n" + " 2: ParameterValue [19, 19, 18, 17, 17, 15, 15, 13, 13, 12, 11, 11, " + "9, 9, 8, 7, 7, 6, 5, 5]\n" + " 3: IntConstant [15, 5, 20, 18, 12, 8, 6]\n" + " 21: IntConstant [17, 11]\n" + " 0: Goto 1\n" "BasicBlock 1, pred: 0, succ: 2\n" - " 4: Select(0, 0, 2)\n" - " 5: Above(0, 2) [6]\n" - " 6: Select(0, 0, 5)\n" - " 7: AboveOrEqual(2, 0) [8]\n" - " 8: Select(0, 0, 7)\n" - " 10: Select(0, 0, 21)\n" - " 11: Below(2, 0) [12]\n" - " 12: Select(0, 0, 11)\n" - " 14: Select(0, 0, 2)\n" - " 16: Select(0, 0, 21)\n" - " 17: BelowOrEqual(0, 2) [18]\n" - " 18: Select(0, 0, 17)\n" - " 19: Return(2)\n" + " 5: Select(2, 2, 3)\n" + " 6: Above(2, 3) [7]\n" + " 7: Select(2, 2, 6)\n" + " 8: AboveOrEqual(3, 2) [9]\n" + " 9: Select(2, 2, 8)\n" + " 11: Select(2, 2, 21)\n" + " 12: Below(3, 2) [13]\n" + " 13: Select(2, 2, 12)\n" + " 15: Select(2, 2, 3)\n" + " 17: Select(2, 2, 21)\n" + " 18: BelowOrEqual(2, 3) [19]\n" + " 19: Select(2, 2, 18)\n" + " 20: Return(3)\n" "BasicBlock 2, pred: 1\n" - " 20: Exit\n"; + " 1: Exit\n"; const std::string expected_after_dce = "BasicBlock 0, succ: 1\n" - " 0: ParameterValue\n" - " 2: IntConstant [19]\n" - " 1: Goto 1\n" + " 2: ParameterValue\n" + " 3: IntConstant [20]\n" + " 0: Goto 1\n" "BasicBlock 1, pred: 0, succ: 2\n" - " 19: Return(2)\n" + " 20: Return(3)\n" "BasicBlock 2, pred: 1\n" - " 20: Exit\n"; + " 1: Exit\n"; auto check_after_cf = [](HGraph* graph) { CHECK(graph != nullptr); diff --git a/compiler/optimizing/graph_test.cc b/compiler/optimizing/graph_test.cc index 46c93aff84..5b43af3564 100644 --- a/compiler/optimizing/graph_test.cc +++ b/compiler/optimizing/graph_test.cc @@ -38,7 +38,7 @@ HBasicBlock* GraphTest::CreateIfBlock(HGraph* graph) { HBasicBlock* if_block = new (GetAllocator()) HBasicBlock(graph); graph->AddBlock(if_block); HInstruction* instr = graph->GetIntConstant(4); - HInstruction* equal = MakeCondition<HEqual>(if_block, instr, instr); + HInstruction* equal = MakeCondition(if_block, kCondEQ, instr, instr); MakeIf(if_block, equal); return if_block; } diff --git a/compiler/optimizing/gvn_test.cc b/compiler/optimizing/gvn_test.cc index 27121fc55a..fba53ee157 100644 --- a/compiler/optimizing/gvn_test.cc +++ b/compiler/optimizing/gvn_test.cc @@ -28,15 +28,9 @@ namespace art HIDDEN { class GVNTest : public OptimizingUnitTest {}; TEST_F(GVNTest, LocalFieldElimination) { - HGraph* graph = CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(entry); - graph->SetEntryBlock(entry); - HInstruction* parameter = MakeParam(DataType::Type::kReference); + HBasicBlock* block = InitEntryMainExitGraphWithReturnVoid(); - HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(block); - entry->AddSuccessor(block); + HInstruction* parameter = MakeParam(DataType::Type::kReference); MakeIFieldGet(block, parameter, DataType::Type::kReference, MemberOffset(42)); HInstruction* to_remove = @@ -47,16 +41,15 @@ TEST_F(GVNTest, LocalFieldElimination) { MakeIFieldSet(block, parameter, parameter, MemberOffset(42)); HInstruction* use_after_kill = MakeIFieldGet(block, parameter, DataType::Type::kReference, MemberOffset(42)); - MakeExit(block); ASSERT_EQ(to_remove->GetBlock(), block); ASSERT_EQ(different_offset->GetBlock(), block); ASSERT_EQ(use_after_kill->GetBlock(), block); - graph->BuildDominatorTree(); - SideEffectsAnalysis side_effects(graph); + graph_->BuildDominatorTree(); + SideEffectsAnalysis side_effects(graph_); side_effects.Run(); - GVNOptimization(graph, side_effects).Run(); + GVNOptimization(graph_, side_effects).Run(); ASSERT_TRUE(to_remove->GetBlock() == nullptr); ASSERT_EQ(different_offset->GetBlock(), block); @@ -64,77 +57,38 @@ TEST_F(GVNTest, LocalFieldElimination) { } TEST_F(GVNTest, GlobalFieldElimination) { - HGraph* graph = CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(entry); - graph->SetEntryBlock(entry); - HInstruction* parameter = MakeParam(DataType::Type::kReference); + HBasicBlock* join = InitEntryMainExitGraphWithReturnVoid(); + auto [block, then, else_] = CreateDiamondPattern(join); - HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(block); - entry->AddSuccessor(block); + HInstruction* parameter = MakeParam(DataType::Type::kReference); HInstruction* field_get = MakeIFieldGet(block, parameter, DataType::Type::kBool, MemberOffset(42)); MakeIf(block, field_get); - HBasicBlock* then = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* else_ = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* join = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(then); - graph->AddBlock(else_); - graph->AddBlock(join); - - block->AddSuccessor(then); - block->AddSuccessor(else_); - then->AddSuccessor(join); - else_->AddSuccessor(join); - MakeIFieldGet(then, parameter, DataType::Type::kBool, MemberOffset(42)); - MakeGoto(then); - MakeIFieldGet(else_, parameter, DataType::Type::kBool, MemberOffset(42)); - MakeGoto(else_); - MakeIFieldGet(join, parameter, DataType::Type::kBool, MemberOffset(42)); - MakeExit(join); - graph->BuildDominatorTree(); - SideEffectsAnalysis side_effects(graph); + graph_->BuildDominatorTree(); + SideEffectsAnalysis side_effects(graph_); side_effects.Run(); - GVNOptimization(graph, side_effects).Run(); + GVNOptimization(graph_, side_effects).Run(); // Check that all field get instructions have been GVN'ed. ASSERT_TRUE(then->GetFirstInstruction()->IsGoto()); ASSERT_TRUE(else_->GetFirstInstruction()->IsGoto()); - ASSERT_TRUE(join->GetFirstInstruction()->IsExit()); + ASSERT_TRUE(join->GetFirstInstruction()->IsReturnVoid()); } TEST_F(GVNTest, LoopFieldElimination) { - HGraph* graph = CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(entry); - graph->SetEntryBlock(entry); + 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. HInstruction* parameter = MakeParam(DataType::Type::kReference); - HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(block); - entry->AddSuccessor(block); - MakeIFieldGet(block, parameter, DataType::Type::kBool, MemberOffset(42)); - MakeGoto(block); - - HBasicBlock* loop_header = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* loop_body = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* exit = new (GetAllocator()) HBasicBlock(graph); - - graph->AddBlock(loop_header); - graph->AddBlock(loop_body); - graph->AddBlock(exit); - block->AddSuccessor(loop_header); - loop_header->AddSuccessor(loop_body); - loop_header->AddSuccessor(exit); - loop_body->AddSuccessor(loop_header); + MakeIFieldGet(pre_header, parameter, DataType::Type::kBool, MemberOffset(42)); HInstruction* field_get_in_loop_header = MakeIFieldGet(loop_header, parameter, DataType::Type::kBool, MemberOffset(42)); @@ -146,87 +100,58 @@ TEST_F(GVNTest, LoopFieldElimination) { 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)); - MakeGoto(loop_body); - HInstruction* field_get_in_exit = - MakeIFieldGet(exit, parameter, DataType::Type::kBool, MemberOffset(42)); - MakeExit(exit); + HInstruction* field_get_in_return_block = + MakeIFieldGet(return_block, parameter, DataType::Type::kBool, MemberOffset(42)); ASSERT_EQ(field_get_in_loop_header->GetBlock(), loop_header); ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body); - ASSERT_EQ(field_get_in_exit->GetBlock(), exit); + ASSERT_EQ(field_get_in_return_block->GetBlock(), return_block); - graph->BuildDominatorTree(); + graph_->BuildDominatorTree(); { - SideEffectsAnalysis side_effects(graph); + SideEffectsAnalysis side_effects(graph_); side_effects.Run(); - GVNOptimization(graph, side_effects).Run(); + GVNOptimization(graph_, side_effects).Run(); } // 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 exit block is dominated by the loop header, whose field get + // 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_exit->GetBlock() == nullptr); + 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); { - SideEffectsAnalysis side_effects(graph); + SideEffectsAnalysis side_effects(graph_); side_effects.Run(); - GVNOptimization(graph, side_effects).Run(); + GVNOptimization(graph_, side_effects).Run(); } ASSERT_TRUE(field_get_in_loop_header->GetBlock() == nullptr); ASSERT_TRUE(field_get_in_loop_body->GetBlock() == nullptr); - ASSERT_TRUE(field_get_in_exit->GetBlock() == nullptr); + ASSERT_TRUE(field_get_in_return_block->GetBlock() == nullptr); } // Test that inner loops affect the side effects of the outer loop. TEST_F(GVNTest, LoopSideEffects) { static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC(); - HGraph* graph = CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(entry); - graph->SetEntryBlock(entry); - - HBasicBlock* outer_loop_header = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* outer_loop_body = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* outer_loop_exit = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* inner_loop_header = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* inner_loop_body = new (GetAllocator()) HBasicBlock(graph); - HBasicBlock* inner_loop_exit = new (GetAllocator()) HBasicBlock(graph); - - graph->AddBlock(outer_loop_header); - graph->AddBlock(outer_loop_body); - graph->AddBlock(outer_loop_exit); - graph->AddBlock(inner_loop_header); - graph->AddBlock(inner_loop_body); - graph->AddBlock(inner_loop_exit); - - entry->AddSuccessor(outer_loop_header); - outer_loop_header->AddSuccessor(outer_loop_body); - outer_loop_header->AddSuccessor(outer_loop_exit); - outer_loop_body->AddSuccessor(inner_loop_header); - inner_loop_header->AddSuccessor(inner_loop_body); - inner_loop_header->AddSuccessor(inner_loop_exit); - inner_loop_body->AddSuccessor(inner_loop_header); - inner_loop_exit->AddSuccessor(outer_loop_header); + 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. HInstruction* parameter = MakeParam(DataType::Type::kBool); - MakeGoto(entry); MakeSuspendCheck(outer_loop_header); MakeIf(outer_loop_header, parameter); - MakeGoto(outer_loop_body); MakeSuspendCheck(inner_loop_header); MakeIf(inner_loop_header, parameter); - MakeGoto(inner_loop_body); - MakeGoto(inner_loop_exit); - MakeExit(outer_loop_exit); - graph->BuildDominatorTree(); + graph_->BuildDominatorTree(); ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn( *outer_loop_header->GetLoopInformation())); @@ -234,12 +159,12 @@ TEST_F(GVNTest, LoopSideEffects) { // Check that the only side effect of loops is to potentially trigger GC. { // Make one block with a side effect. - MakeIFieldSet(entry, parameter, parameter, DataType::Type::kReference, MemberOffset(42)); + MakeIFieldSet(entry_block_, parameter, parameter, DataType::Type::kReference, MemberOffset(42)); - SideEffectsAnalysis side_effects(graph); + SideEffectsAnalysis side_effects(graph_); side_effects.Run(); - ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite()); + ASSERT_TRUE(side_effects.GetBlockEffects(entry_block_).DoesAnyWrite()); ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite()); ASSERT_FALSE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite()); ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite()); @@ -252,10 +177,10 @@ TEST_F(GVNTest, LoopSideEffects) { MakeIFieldSet( outer_loop_body, parameter, parameter, DataType::Type::kReference, MemberOffset(42)); - SideEffectsAnalysis side_effects(graph); + SideEffectsAnalysis side_effects(graph_); side_effects.Run(); - ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite()); + ASSERT_TRUE(side_effects.GetBlockEffects(entry_block_).DoesAnyWrite()); ASSERT_TRUE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite()); ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite()); ASSERT_FALSE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite()); @@ -268,10 +193,10 @@ TEST_F(GVNTest, LoopSideEffects) { MakeIFieldSet( inner_loop_body, parameter, parameter, DataType::Type::kReference, MemberOffset(42)); - SideEffectsAnalysis side_effects(graph); + SideEffectsAnalysis side_effects(graph_); side_effects.Run(); - ASSERT_TRUE(side_effects.GetBlockEffects(entry).DoesAnyWrite()); + ASSERT_TRUE(side_effects.GetBlockEffects(entry_block_).DoesAnyWrite()); ASSERT_FALSE(side_effects.GetBlockEffects(outer_loop_body).DoesAnyWrite()); ASSERT_TRUE(side_effects.GetLoopEffects(outer_loop_header).DoesAnyWrite()); ASSERT_TRUE(side_effects.GetLoopEffects(inner_loop_header).DoesAnyWrite()); diff --git a/compiler/optimizing/induction_var_analysis_test.cc b/compiler/optimizing/induction_var_analysis_test.cc index 872fa42a76..b8f683774d 100644 --- a/compiler/optimizing/induction_var_analysis_test.cc +++ b/compiler/optimizing/induction_var_analysis_test.cc @@ -74,7 +74,7 @@ class InductionVarAnalysisTest : public OptimizingUnitTest { for (int d = 0; d < n; d++) { std::tie(basic_[d], increment_[d]) = MakeLinearLoopVar(loop_header_[d], loop_body_[d], constant0_, constant1_); - HInstruction* compare = MakeCondition<HLessThan>(loop_header_[d], basic_[d], constant100_); + HInstruction* compare = MakeCondition(loop_header_[d], kCondLT, basic_[d], constant100_); MakeIf(loop_header_[d], compare); } } diff --git a/compiler/optimizing/induction_var_range_test.cc b/compiler/optimizing/induction_var_range_test.cc index 0c0b54eb23..17ee6787ff 100644 --- a/compiler/optimizing/induction_var_range_test.cc +++ b/compiler/optimizing/induction_var_range_test.cc @@ -76,11 +76,8 @@ class InductionVarRangeTest : public OptimizingUnitTest { HInstruction* lower_const = graph_->GetIntConstant(lower); HPhi* phi; std::tie(phi, increment_) = MakeLinearLoopVar(loop_header_, loop_body_, lower, stride); - if (stride > 0) { - condition_ = MakeCondition<HLessThan>(loop_header_, phi, upper); // i < u - } else { - condition_ = MakeCondition<HGreaterThan>(loop_header_, phi, upper); // i > u - } + IfCondition cond = (stride > 0) ? kCondLT : kCondGT; + condition_ = MakeCondition(loop_header_, cond, phi, upper); // i < u or i > u MakeIf(loop_header_, condition_); } diff --git a/compiler/optimizing/licm_test.cc b/compiler/optimizing/licm_test.cc index 58d90c3168..08a2dcc179 100644 --- a/compiler/optimizing/licm_test.cc +++ b/compiler/optimizing/licm_test.cc @@ -31,12 +31,9 @@ namespace art HIDDEN { class LICMTest : public OptimizingUnitTest { public: LICMTest() - : entry_(nullptr), - loop_preheader_(nullptr), + : loop_preheader_(nullptr), loop_header_(nullptr), loop_body_(nullptr), - return_(nullptr), - exit_(nullptr), parameter_(nullptr), int_constant_(nullptr), float_constant_(nullptr) { @@ -48,40 +45,15 @@ class LICMTest : public OptimizingUnitTest { // Builds a singly-nested loop structure in CFG. Tests can further populate // the basic blocks with instructions to set up interesting scenarios. void BuildLoop() { - entry_ = new (GetAllocator()) HBasicBlock(graph_); - loop_preheader_ = new (GetAllocator()) HBasicBlock(graph_); - loop_header_ = new (GetAllocator()) HBasicBlock(graph_); - loop_body_ = new (GetAllocator()) HBasicBlock(graph_); - return_ = new (GetAllocator()) HBasicBlock(graph_); - exit_ = new (GetAllocator()) HBasicBlock(graph_); - - graph_->AddBlock(entry_); - graph_->AddBlock(loop_preheader_); - graph_->AddBlock(loop_header_); - graph_->AddBlock(loop_body_); - graph_->AddBlock(return_); - graph_->AddBlock(exit_); - - graph_->SetEntryBlock(entry_); - graph_->SetExitBlock(exit_); - - // Set up loop flow in CFG. - entry_->AddSuccessor(loop_preheader_); - loop_preheader_->AddSuccessor(loop_header_); - loop_header_->AddSuccessor(loop_body_); - loop_header_->AddSuccessor(return_); - loop_body_->AddSuccessor(loop_header_); - return_->AddSuccessor(exit_); + HBasicBlock* return_block = InitEntryMainExitGraphWithReturnVoid(); + std::tie(loop_preheader_, loop_header_, loop_body_) = CreateWhileLoop(return_block); + loop_header_->SwapSuccessors(); // Move the loop exit to the "else" successor. // Provide boiler-plate instructions. parameter_ = MakeParam(DataType::Type::kReference); int_constant_ = graph_->GetIntConstant(42); float_constant_ = graph_->GetFloatConstant(42.0f); - MakeGoto(loop_preheader_); MakeIf(loop_header_, parameter_); - MakeGoto(loop_body_); - MakeReturnVoid(return_); - MakeExit(exit_); } // Performs LICM optimizations (after proper set up). @@ -92,16 +64,10 @@ class LICMTest : public OptimizingUnitTest { LICM(graph_, side_effects, nullptr).Run(); } - // General building fields. - HGraph* graph_; - // Specific basic blocks. - HBasicBlock* entry_; HBasicBlock* loop_preheader_; HBasicBlock* loop_header_; HBasicBlock* loop_body_; - HBasicBlock* return_; - HBasicBlock* exit_; HInstruction* parameter_; // "this" HInstruction* int_constant_; @@ -164,12 +130,10 @@ TEST_F(LICMTest, NoArrayHoisting) { BuildLoop(); // Populate the loop with instructions: set/get array with same types. - HInstruction* get_array = new (GetAllocator()) HArrayGet( - parameter_, int_constant_, DataType::Type::kFloat32, 0); - loop_body_->InsertInstructionBefore(get_array, loop_body_->GetLastInstruction()); - HInstruction* set_array = new (GetAllocator()) HArraySet( - parameter_, get_array, float_constant_, DataType::Type::kFloat32, 0); - loop_body_->InsertInstructionBefore(set_array, loop_body_->GetLastInstruction()); + HInstruction* get_array = + MakeArrayGet(loop_body_, parameter_, int_constant_, DataType::Type::kFloat32); + HInstruction* set_array = + MakeArraySet(loop_body_, parameter_, get_array, float_constant_, DataType::Type::kFloat32); EXPECT_EQ(get_array->GetBlock(), loop_body_); EXPECT_EQ(set_array->GetBlock(), loop_body_); diff --git a/compiler/optimizing/load_store_analysis_test.cc b/compiler/optimizing/load_store_analysis_test.cc index 09a336323c..b53e224ab5 100644 --- a/compiler/optimizing/load_store_analysis_test.cc +++ b/compiler/optimizing/load_store_analysis_test.cc @@ -42,40 +42,23 @@ class LoadStoreAnalysisTest : public CommonCompilerTest, public OptimizingUnitTe LoadStoreAnalysisTest() { use_boot_image_ = true; // Make the Runtime creation cheaper. } - - 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); - } }; TEST_F(LoadStoreAnalysisTest, ArrayHeapLocations) { - CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_); - graph_->AddBlock(entry); - graph_->SetEntryBlock(entry); - - // entry: - // array ParameterValue - // index ParameterValue - // c1 IntConstant - // c2 IntConstant - // c3 IntConstant - // array_get1 ArrayGet [array, c1] - // array_get2 ArrayGet [array, c2] - // array_set1 ArraySet [array, c1, c3] - // array_set2 ArraySet [array, index, c3] + HBasicBlock* main = InitEntryMainExitGraphWithReturnVoid(); + + // entry HInstruction* array = MakeParam(DataType::Type::kReference); HInstruction* index = MakeParam(DataType::Type::kInt32); HInstruction* c1 = graph_->GetIntConstant(1); HInstruction* c2 = graph_->GetIntConstant(2); HInstruction* c3 = graph_->GetIntConstant(3); - HInstruction* array_get1 = MakeArrayGet(entry, array, c1, DataType::Type::kInt32); - HInstruction* array_get2 = MakeArrayGet(entry, array, c2, DataType::Type::kInt32); - HInstruction* array_set1 = MakeArraySet(entry, array, c1, c3, DataType::Type::kInt32); - HInstruction* array_set2 = MakeArraySet(entry, array, index, c3, DataType::Type::kInt32); + + // main + HInstruction* array_get1 = MakeArrayGet(main, array, c1, DataType::Type::kInt32); + HInstruction* array_get2 = MakeArrayGet(main, array, c2, DataType::Type::kInt32); + HInstruction* array_set1 = MakeArraySet(main, array, c1, c3, DataType::Type::kInt32); + HInstruction* array_set2 = MakeArraySet(main, array, index, c3, DataType::Type::kInt32); // Test HeapLocationCollector initialization. // Should be no heap locations, no operations on the heap. @@ -86,7 +69,7 @@ TEST_F(LoadStoreAnalysisTest, ArrayHeapLocations) { // Test that after visiting the graph_, it must see following heap locations // array[c1], array[c2], array[index]; and it should see heap stores. - heap_location_collector.VisitBasicBlock(entry); + heap_location_collector.VisitBasicBlock(main); ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 3U); ASSERT_TRUE(heap_location_collector.HasHeapStores()); @@ -126,25 +109,18 @@ TEST_F(LoadStoreAnalysisTest, ArrayHeapLocations) { } TEST_F(LoadStoreAnalysisTest, FieldHeapLocations) { - CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_); - graph_->AddBlock(entry); - graph_->SetEntryBlock(entry); - - // entry: - // object ParameterValue - // c1 IntConstant - // set_field10 InstanceFieldSet [object, c1, 10] - // get_field10 InstanceFieldGet [object, 10] - // get_field20 InstanceFieldGet [object, 20] + HBasicBlock* main = InitEntryMainExitGraphWithReturnVoid(); - HInstruction* c1 = graph_->GetIntConstant(1); + // entry HInstruction* object = MakeParam(DataType::Type::kReference); - HInstanceFieldSet* set_field10 = MakeIFieldSet(entry, object, c1, MemberOffset(10)); + HInstruction* c1 = graph_->GetIntConstant(1); + + // main + HInstanceFieldSet* set_field10 = MakeIFieldSet(main, object, c1, MemberOffset(10)); HInstanceFieldGet* get_field10 = - MakeIFieldGet(entry, object, DataType::Type::kInt32, MemberOffset(10)); + MakeIFieldGet(main, object, DataType::Type::kInt32, MemberOffset(10)); HInstanceFieldGet* get_field20 = - MakeIFieldGet(entry, object, DataType::Type::kInt32, MemberOffset(20)); + MakeIFieldGet(main, object, DataType::Type::kInt32, MemberOffset(20)); // Test HeapLocationCollector initialization. // Should be no heap locations, no operations on the heap. @@ -155,7 +131,7 @@ TEST_F(LoadStoreAnalysisTest, FieldHeapLocations) { // Test that after visiting the graph, it must see following heap locations // object.field10, object.field20 and it should see heap stores. - heap_location_collector.VisitBasicBlock(entry); + heap_location_collector.VisitBasicBlock(main); ASSERT_EQ(heap_location_collector.GetNumberOfHeapLocations(), 2U); ASSERT_TRUE(heap_location_collector.HasHeapStores()); @@ -177,10 +153,7 @@ TEST_F(LoadStoreAnalysisTest, FieldHeapLocations) { } TEST_F(LoadStoreAnalysisTest, ArrayIndexAliasingTest) { - CreateGraph(); - AdjacencyListGraph blks( - SetupFromAdjacencyList("entry", "exit", {{"entry", "body"}, {"body", "exit"}})); - HBasicBlock* body = blks.Get("body"); + HBasicBlock* body = InitEntryMainExitGraphWithReturnVoid(); HInstruction* array = MakeParam(DataType::Type::kReference); HInstruction* index = MakeParam(DataType::Type::kInt32); @@ -210,8 +183,7 @@ TEST_F(LoadStoreAnalysisTest, ArrayIndexAliasingTest) { // array[i-(-1)] = c0 HInstruction* arr_set8 = MakeArraySet(body, array, sub_neg1, c0, DataType::Type::kInt32); - MakeReturnVoid(body); - + graph_->ComputeDominanceInformation(); ScopedArenaAllocator allocator(graph_->GetArenaStack()); LoadStoreAnalysis lsa(graph_, nullptr, &allocator); lsa.Run(); @@ -254,11 +226,7 @@ TEST_F(LoadStoreAnalysisTest, ArrayIndexAliasingTest) { } TEST_F(LoadStoreAnalysisTest, ArrayAliasingTest) { - CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_); - graph_->AddBlock(entry); - graph_->SetEntryBlock(entry); - graph_->BuildDominatorTree(); + HBasicBlock* main = InitEntryMainExitGraphWithReturnVoid(); HInstruction* array = MakeParam(DataType::Type::kReference); HInstruction* index = MakeParam(DataType::Type::kInt32); @@ -267,34 +235,35 @@ TEST_F(LoadStoreAnalysisTest, ArrayAliasingTest) { HInstruction* c6 = graph_->GetIntConstant(6); HInstruction* c8 = graph_->GetIntConstant(8); - HInstruction* arr_set_0 = MakeArraySet(entry, array, c0, c0, DataType::Type::kInt32); - HInstruction* arr_set_1 = MakeArraySet(entry, array, c1, c0, DataType::Type::kInt32); - HInstruction* arr_set_i = MakeArraySet(entry, array, index, c0, DataType::Type::kInt32); + HInstruction* arr_set_0 = MakeArraySet(main, array, c0, c0, DataType::Type::kInt32); + HInstruction* arr_set_1 = MakeArraySet(main, array, c1, c0, DataType::Type::kInt32); + HInstruction* arr_set_i = MakeArraySet(main, array, index, c0, DataType::Type::kInt32); HVecOperation* v1 = new (GetAllocator()) HVecReplicateScalar(GetAllocator(), c1, DataType::Type::kInt32, 4, kNoDexPc); - entry->AddInstruction(v1); + AddOrInsertInstruction(main, v1); HVecOperation* v2 = new (GetAllocator()) HVecReplicateScalar(GetAllocator(), c1, DataType::Type::kInt32, 2, kNoDexPc); - entry->AddInstruction(v2); - HInstruction* i_add6 = MakeBinOp<HAdd>(entry, DataType::Type::kInt32, index, c6); - HInstruction* i_add8 = MakeBinOp<HAdd>(entry, DataType::Type::kInt32, index, c8); - - HInstruction* vstore_0 = MakeVecStore(entry, array, c0, v1, DataType::Type::kInt32); - HInstruction* vstore_1 = MakeVecStore(entry, array, c1, v1, DataType::Type::kInt32); - HInstruction* vstore_8 = MakeVecStore(entry, array, c8, v1, DataType::Type::kInt32); - HInstruction* vstore_i = MakeVecStore(entry, array, index, v1, DataType::Type::kInt32); - HInstruction* vstore_i_add6 = MakeVecStore(entry, array, i_add6, v1, DataType::Type::kInt32); - HInstruction* vstore_i_add8 = MakeVecStore(entry, array, i_add8, v1, DataType::Type::kInt32); + AddOrInsertInstruction(main, v2); + HInstruction* i_add6 = MakeBinOp<HAdd>(main, DataType::Type::kInt32, index, c6); + HInstruction* i_add8 = MakeBinOp<HAdd>(main, DataType::Type::kInt32, index, c8); + + HInstruction* vstore_0 = MakeVecStore(main, array, c0, v1, DataType::Type::kInt32); + HInstruction* vstore_1 = MakeVecStore(main, array, c1, v1, DataType::Type::kInt32); + HInstruction* vstore_8 = MakeVecStore(main, array, c8, v1, DataType::Type::kInt32); + HInstruction* vstore_i = MakeVecStore(main, array, index, v1, DataType::Type::kInt32); + HInstruction* vstore_i_add6 = MakeVecStore(main, array, i_add6, v1, DataType::Type::kInt32); + HInstruction* vstore_i_add8 = MakeVecStore(main, array, i_add8, v1, DataType::Type::kInt32); HInstruction* vstore_i_add6_vlen2 = - MakeVecStore(entry, array, i_add6, v2, DataType::Type::kInt32, /*vector_lengt=*/ 2); + MakeVecStore(main, array, i_add6, v2, DataType::Type::kInt32, /*vector_lengt=*/ 2); + graph_->BuildDominatorTree(); ScopedArenaAllocator allocator(graph_->GetArenaStack()); LoadStoreAnalysis lsa(graph_, nullptr, &allocator); lsa.Run(); @@ -381,11 +350,7 @@ TEST_F(LoadStoreAnalysisTest, ArrayAliasingTest) { } TEST_F(LoadStoreAnalysisTest, ArrayIndexCalculationOverflowTest) { - CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_); - graph_->AddBlock(entry); - graph_->SetEntryBlock(entry); - graph_->BuildDominatorTree(); + HBasicBlock* main = InitEntryMainExitGraphWithReturnVoid(); HInstruction* array = MakeParam(DataType::Type::kReference); HInstruction* index = MakeParam(DataType::Type::kInt32); @@ -398,34 +363,30 @@ TEST_F(LoadStoreAnalysisTest, ArrayIndexCalculationOverflowTest) { HInstruction* c_0x80000001 = graph_->GetIntConstant(0x80000001); // `index+0x80000000` and `index-0x80000000` array indices MAY alias. - HInstruction* add_0x80000000 = - MakeBinOp<HAdd>(entry, DataType::Type::kInt32, index, c_0x80000000); - HInstruction* sub_0x80000000 = - MakeBinOp<HSub>(entry, DataType::Type::kInt32, index, c_0x80000000); - HInstruction* arr_set_1 = MakeArraySet(entry, array, add_0x80000000, c0, DataType::Type::kInt32); - HInstruction* arr_set_2 = MakeArraySet(entry, array, sub_0x80000000, c0, DataType::Type::kInt32); + HInstruction* add_0x80000000 = MakeBinOp<HAdd>(main, DataType::Type::kInt32, index, c_0x80000000); + HInstruction* sub_0x80000000 = MakeBinOp<HSub>(main, DataType::Type::kInt32, index, c_0x80000000); + HInstruction* arr_set_1 = MakeArraySet(main, array, add_0x80000000, c0, DataType::Type::kInt32); + HInstruction* arr_set_2 = MakeArraySet(main, array, sub_0x80000000, c0, DataType::Type::kInt32); // `index+0x10` and `index-0xFFFFFFF0` array indices MAY alias. - HInstruction* add_0x10 = MakeBinOp<HAdd>(entry, DataType::Type::kInt32, index, c_0x10); - HInstruction* sub_0xFFFFFFF0 = - MakeBinOp<HSub>(entry, DataType::Type::kInt32, index, c_0xFFFFFFF0); - HInstruction* arr_set_3 = MakeArraySet(entry, array, add_0x10, c0, DataType::Type::kInt32); - HInstruction* arr_set_4 = MakeArraySet(entry, array, sub_0xFFFFFFF0, c0, DataType::Type::kInt32); + HInstruction* add_0x10 = MakeBinOp<HAdd>(main, DataType::Type::kInt32, index, c_0x10); + HInstruction* sub_0xFFFFFFF0 = MakeBinOp<HSub>(main, DataType::Type::kInt32, index, c_0xFFFFFFF0); + HInstruction* arr_set_3 = MakeArraySet(main, array, add_0x10, c0, DataType::Type::kInt32); + HInstruction* arr_set_4 = MakeArraySet(main, array, sub_0xFFFFFFF0, c0, DataType::Type::kInt32); // `index+0x7FFFFFFF` and `index-0x80000001` array indices MAY alias. - HInstruction* add_0x7FFFFFFF = - MakeBinOp<HAdd>(entry, DataType::Type::kInt32, index, c_0x7FFFFFFF); - HInstruction* sub_0x80000001 = - MakeBinOp<HSub>(entry, DataType::Type::kInt32, index, c_0x80000001); - HInstruction* arr_set_5 = MakeArraySet(entry, array, add_0x7FFFFFFF, c0, DataType::Type::kInt32); - HInstruction* arr_set_6 = MakeArraySet(entry, array, sub_0x80000001, c0, DataType::Type::kInt32); + HInstruction* add_0x7FFFFFFF = MakeBinOp<HAdd>(main, DataType::Type::kInt32, index, c_0x7FFFFFFF); + HInstruction* sub_0x80000001 = MakeBinOp<HSub>(main, DataType::Type::kInt32, index, c_0x80000001); + HInstruction* arr_set_5 = MakeArraySet(main, array, add_0x7FFFFFFF, c0, DataType::Type::kInt32); + HInstruction* arr_set_6 = MakeArraySet(main, array, sub_0x80000001, c0, DataType::Type::kInt32); // `index+0` and `index-0` array indices MAY alias. - HInstruction* add_0 = MakeBinOp<HAdd>(entry, DataType::Type::kInt32, index, c0); - HInstruction* sub_0 = MakeBinOp<HSub>(entry, DataType::Type::kInt32, index, c0); - HInstruction* arr_set_7 = MakeArraySet(entry, array, add_0, c0, DataType::Type::kInt32); - HInstruction* arr_set_8 = MakeArraySet(entry, array, sub_0, c0, DataType::Type::kInt32); + HInstruction* add_0 = MakeBinOp<HAdd>(main, DataType::Type::kInt32, index, c0); + HInstruction* sub_0 = MakeBinOp<HSub>(main, DataType::Type::kInt32, index, c0); + HInstruction* arr_set_7 = MakeArraySet(main, array, add_0, c0, DataType::Type::kInt32); + HInstruction* arr_set_8 = MakeArraySet(main, array, sub_0, c0, DataType::Type::kInt32); + graph_->BuildDominatorTree(); ScopedArenaAllocator allocator(graph_->GetArenaStack()); LoadStoreAnalysis lsa(graph_, nullptr, &allocator); lsa.Run(); @@ -471,10 +432,7 @@ TEST_F(LoadStoreAnalysisTest, ArrayIndexCalculationOverflowTest) { } TEST_F(LoadStoreAnalysisTest, TestHuntOriginalRef) { - CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph_); - graph_->AddBlock(entry); - graph_->SetEntryBlock(entry); + HBasicBlock* main = InitEntryMainExitGraphWithReturnVoid(); // Different ways where orignal array reference are transformed & passed to ArrayGet. // ParameterValue --> ArrayGet @@ -483,22 +441,23 @@ TEST_F(LoadStoreAnalysisTest, TestHuntOriginalRef) { // ParameterValue --> BoundType --> NullCheck --> IntermediateAddress --> ArrayGet HInstruction* c1 = graph_->GetIntConstant(1); HInstruction* array = MakeParam(DataType::Type::kReference); - HInstruction* array_get1 = MakeArrayGet(entry, array, c1, DataType::Type::kInt32); + + HInstruction* array_get1 = MakeArrayGet(main, array, c1, DataType::Type::kInt32); HInstruction* bound_type = new (GetAllocator()) HBoundType(array); - entry->AddInstruction(bound_type); - HInstruction* array_get2 = MakeArrayGet(entry, bound_type, c1, DataType::Type::kInt32); + AddOrInsertInstruction(main, bound_type); + HInstruction* array_get2 = MakeArrayGet(main, bound_type, c1, DataType::Type::kInt32); - HInstruction* null_check = MakeNullCheck(entry, bound_type); - HInstruction* array_get3 = MakeArrayGet(entry, null_check, c1, DataType::Type::kInt32); + HInstruction* null_check = MakeNullCheck(main, bound_type); + HInstruction* array_get3 = MakeArrayGet(main, null_check, c1, DataType::Type::kInt32); HInstruction* inter_addr = new (GetAllocator()) HIntermediateAddress(null_check, c1, 0); - entry->AddInstruction(inter_addr); - HInstruction* array_get4 = MakeArrayGet(entry, inter_addr, c1, DataType::Type::kInt32); + AddOrInsertInstruction(main, inter_addr); + HInstruction* array_get4 = MakeArrayGet(main, inter_addr, c1, DataType::Type::kInt32); ScopedArenaAllocator allocator(graph_->GetArenaStack()); HeapLocationCollector heap_location_collector(graph_, &allocator); - heap_location_collector.VisitBasicBlock(entry); + heap_location_collector.VisitBasicBlock(main); // Test that the HeapLocationCollector should be able to tell // that there is only ONE array location, no matter how many @@ -515,7 +474,7 @@ TEST_F(LoadStoreAnalysisTest, TestHuntOriginalRef) { ASSERT_EQ(loc1, loc4); } -// // ENTRY +// // IF_BLOCK // obj = new Obj(); // if (parameter_value) { // // LEFT @@ -525,35 +484,28 @@ TEST_F(LoadStoreAnalysisTest, TestHuntOriginalRef) { // obj.f0 = 0; // call_func2(obj); // } -// // EXIT +// // RETURN_BLOCK // obj.f0; TEST_F(LoadStoreAnalysisTest, TotalEscape) { - CreateGraph(); - AdjacencyListGraph blks(SetupFromAdjacencyList( - "entry", - "exit", - { { "entry", "left" }, { "entry", "right" }, { "left", "exit" }, { "right", "exit" } })); - HBasicBlock* entry = blks.Get("entry"); - HBasicBlock* left = blks.Get("left"); - HBasicBlock* right = blks.Get("right"); - HBasicBlock* exit = blks.Get("exit"); + HBasicBlock* return_block = InitEntryMainExitGraphWithReturnVoid(); + auto [if_block, left, right] = CreateDiamondPattern(return_block); HInstruction* bool_value = MakeParam(DataType::Type::kBool); HInstruction* c0 = graph_->GetIntConstant(0); - HInstruction* cls = MakeLoadClass(entry); - HInstruction* new_inst = MakeNewInstance(entry, cls); - MakeIf(entry, bool_value); + + HInstruction* cls = MakeLoadClass(if_block); + HInstruction* new_inst = MakeNewInstance(if_block, cls); + MakeIf(if_block, bool_value); HInstruction* call_left = MakeInvokeStatic(left, DataType::Type::kVoid, {new_inst}); - MakeGoto(left); HInstruction* call_right = MakeInvokeStatic(right, DataType::Type::kVoid, {new_inst}); HInstruction* write_right = MakeIFieldSet(right, new_inst, c0, MemberOffset(32)); - MakeGoto(right); HInstruction* read_final = - MakeIFieldGet(exit, new_inst, DataType::Type::kInt32, MemberOffset(32)); + MakeIFieldGet(return_block, new_inst, DataType::Type::kInt32, MemberOffset(32)); + graph_->ComputeDominanceInformation(); ScopedArenaAllocator allocator(graph_->GetArenaStack()); LoadStoreAnalysis lsa(graph_, nullptr, &allocator); lsa.Run(); @@ -563,25 +515,21 @@ TEST_F(LoadStoreAnalysisTest, TotalEscape) { ASSERT_FALSE(info->IsSingleton()); } -// // ENTRY +// // MAIN // obj = new Obj(); // obj.foo = 0; -// // EXIT // return obj; TEST_F(LoadStoreAnalysisTest, TotalEscape2) { - CreateGraph(); - AdjacencyListGraph blks(SetupFromAdjacencyList("entry", "exit", { { "entry", "exit" } })); - HBasicBlock* entry = blks.Get("entry"); - HBasicBlock* exit = blks.Get("exit"); + HBasicBlock* main = InitEntryMainExitGraph(); HInstruction* c0 = graph_->GetIntConstant(0); - HInstruction* cls = MakeLoadClass(entry); - HInstruction* new_inst = MakeNewInstance(entry, cls); - HInstruction* write_start = MakeIFieldSet(entry, new_inst, c0, MemberOffset(32)); - MakeGoto(entry); - MakeReturn(exit, new_inst); + HInstruction* cls = MakeLoadClass(main); + HInstruction* new_inst = MakeNewInstance(main, cls); + HInstruction* write_start = MakeIFieldSet(main, new_inst, c0, MemberOffset(32)); + MakeReturn(main, new_inst); + graph_->ComputeDominanceInformation(); ScopedArenaAllocator allocator(graph_->GetArenaStack()); LoadStoreAnalysis lsa(graph_, nullptr, &allocator); lsa.Run(); @@ -591,7 +539,7 @@ TEST_F(LoadStoreAnalysisTest, TotalEscape2) { ASSERT_TRUE(info->IsSingletonAndNonRemovable()); } -// // ENTRY +// // TOP // obj = new Obj(); // if (parameter_value) { // // HIGH_LEFT @@ -609,41 +557,25 @@ TEST_F(LoadStoreAnalysisTest, TotalEscape2) { // // LOW_RIGHT // obj.f0 = 1; // } -// // EXIT +// // BOTTOM // obj.f0 TEST_F(LoadStoreAnalysisTest, DoubleDiamondEscape) { - CreateGraph(); - AdjacencyListGraph blks(SetupFromAdjacencyList("entry", - "exit", - { { "entry", "high_left" }, - { "entry", "high_right" }, - { "low_left", "exit" }, - { "low_right", "exit" }, - { "high_right", "mid" }, - { "high_left", "mid" }, - { "mid", "low_left" }, - { "mid", "low_right" } })); - HBasicBlock* entry = blks.Get("entry"); - HBasicBlock* high_left = blks.Get("high_left"); - HBasicBlock* high_right = blks.Get("high_right"); - HBasicBlock* mid = blks.Get("mid"); - HBasicBlock* low_left = blks.Get("low_left"); - HBasicBlock* low_right = blks.Get("low_right"); - HBasicBlock* exit = blks.Get("exit"); + HBasicBlock* bottom = InitEntryMainExitGraphWithReturnVoid(); + auto [mid, low_left, low_right] = CreateDiamondPattern(bottom); + auto [top, high_left, high_right] = CreateDiamondPattern(mid); HInstruction* bool_value1 = MakeParam(DataType::Type::kBool); HInstruction* bool_value2 = MakeParam(DataType::Type::kBool); HInstruction* c0 = graph_->GetIntConstant(0); HInstruction* c2 = graph_->GetIntConstant(2); - HInstruction* cls = MakeLoadClass(entry); - HInstruction* new_inst = MakeNewInstance(entry, cls); - MakeIf(entry, bool_value1); + + HInstruction* cls = MakeLoadClass(top); + HInstruction* new_inst = MakeNewInstance(top, cls); + MakeIf(top, bool_value1); HInstruction* call_left = MakeInvokeStatic(high_left, DataType::Type::kVoid, {new_inst}); - MakeGoto(high_left); HInstruction* write_right = MakeIFieldSet(high_right, new_inst, c0, MemberOffset(32)); - MakeGoto(high_right); HInstruction* read_mid = MakeIFieldGet(mid, new_inst, DataType::Type::kInt32, MemberOffset(32)); HInstruction* mul_mid = MakeBinOp<HMul>(mid, DataType::Type::kInt32, read_mid, c2); @@ -651,14 +583,13 @@ TEST_F(LoadStoreAnalysisTest, DoubleDiamondEscape) { MakeIf(mid, bool_value2); HInstruction* call_low_left = MakeInvokeStatic(low_left, DataType::Type::kVoid, {new_inst}); - MakeGoto(low_left); HInstruction* write_low_right = MakeIFieldSet(low_right, new_inst, c0, MemberOffset(32)); - MakeGoto(low_right); HInstruction* read_final = - MakeIFieldGet(exit, new_inst, DataType::Type::kInt32, MemberOffset(32)); + MakeIFieldGet(bottom, new_inst, DataType::Type::kInt32, MemberOffset(32)); + graph_->ComputeDominanceInformation(); ScopedArenaAllocator allocator(graph_->GetArenaStack()); LoadStoreAnalysis lsa(graph_, nullptr, &allocator); lsa.Run(); @@ -668,7 +599,7 @@ TEST_F(LoadStoreAnalysisTest, DoubleDiamondEscape) { ASSERT_FALSE(info->IsSingleton()); } -// // ENTRY +// // START // Obj new_inst = new Obj(); // new_inst.foo = 12; // Obj obj; @@ -692,68 +623,42 @@ TEST_F(LoadStoreAnalysisTest, DoubleDiamondEscape) { // // RIGHT // out = obj_param; // } -// // EXIT +// // BRETURN // // Can't do anything with this since we don't have good tracking for the heap-locations // // out = phi[param, phi[new_inst, param]] // return out.foo TEST_F(LoadStoreAnalysisTest, PartialPhiPropagation1) { - CreateGraph(); - AdjacencyListGraph blks(SetupFromAdjacencyList("entry", - "exit", - {{"entry", "left"}, - {"entry", "right"}, - {"left", "left_left"}, - {"left", "left_right"}, - {"left_left", "left_merge"}, - {"left_right", "left_merge"}, - {"left_merge", "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); - GET_BLOCK(left_left); - GET_BLOCK(left_right); - GET_BLOCK(left_merge); -#undef GET_BLOCK + HBasicBlock* breturn = InitEntryMainExitGraph(); + auto [start, left_merge, right] = CreateDiamondPattern(breturn); + auto [left, left_left, left_right] = CreateDiamondPattern(left_merge); EnsurePredecessorOrder(breturn, {left_merge, right}); EnsurePredecessorOrder(left_merge, {left_left, left_right}); HInstruction* param1 = MakeParam(DataType::Type::kBool); HInstruction* param2 = MakeParam(DataType::Type::kBool); HInstruction* obj_param = MakeParam(DataType::Type::kReference); HInstruction* c12 = graph_->GetIntConstant(12); - HInstruction* cls = MakeLoadClass(entry); - HInstruction* new_inst = MakeNewInstance(entry, cls); - HInstruction* store = MakeIFieldSet(entry, new_inst, c12, MemberOffset(32)); - MakeIf(entry, param1); + + HInstruction* cls = MakeLoadClass(start); + HInstruction* new_inst = MakeNewInstance(start, cls); + HInstruction* store = MakeIFieldSet(start, new_inst, c12, MemberOffset(32)); + MakeIf(start, param1); ArenaVector<HInstruction*> current_locals({}, GetAllocator()->Adapter(kArenaAllocInstruction)); ManuallyBuildEnvFor(cls, ¤t_locals); new_inst->CopyEnvironmentFrom(cls->GetEnvironment()); MakeIf(left, param2); - MakeGoto(left_left); - - MakeGoto(left_right); - HPhi* left_phi = MakePhi(left_merge, {obj_param, new_inst}); HInstruction* call_left = MakeInvokeStatic(left_merge, DataType::Type::kVoid, {left_phi}); MakeGoto(left_merge); left_phi->SetCanBeNull(true); call_left->CopyEnvironmentFrom(cls->GetEnvironment()); - MakeGoto(right); - HPhi* return_phi = MakePhi(breturn, {left_phi, obj_param}); HInstruction* read_exit = MakeIFieldGet(breturn, return_phi, DataType::Type::kReference, MemberOffset(32)); MakeReturn(breturn, read_exit); - MakeExit(exit); - graph_->ClearDominanceInformation(); graph_->BuildDominatorTree(); diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc index ae6e1137c9..416e5843ef 100644 --- a/compiler/optimizing/load_store_elimination_test.cc +++ b/compiler/optimizing/load_store_elimination_test.cc @@ -123,7 +123,7 @@ class LoadStoreEliminationTestBase : public SuperTest, public OptimizingUnitTest // phi++; // if (phi >= 128) suspend_check_ = MakeSuspendCheck(loop_); - HInstruction* cmp = MakeCondition<HGreaterThanOrEqual>(loop_, phi_, c128); + HInstruction* cmp = MakeCondition(loop_, kCondGE, phi_, c128); MakeIf(loop_, cmp); CreateEnvForSuspendCheck(); @@ -147,7 +147,7 @@ class LoadStoreEliminationTestBase : public SuperTest, public OptimizingUnitTest auto [upper, left, right] = CreateDiamondPattern(return_block_); - HInstruction* cmp = MakeCondition<HGreaterThanOrEqual>(upper, i_, j_); + HInstruction* cmp = MakeCondition(upper, kCondGE, i_, j_); MakeIf(upper, cmp); return std::make_tuple(upper, left, right, return_block_); @@ -1028,7 +1028,7 @@ TEST_F(LoadStoreEliminationTest, ArrayLoopOverlap) { auto [i_phi, i_add] = MakeLinearLoopVar(loop, body, one_const, one_const); HPhi* t_phi = MakePhi(loop, {zero_const, /* placeholder */ zero_const}); HInstruction* suspend = MakeSuspendCheck(loop); - HInstruction* i_cmp_top = MakeCondition<HGreaterThanOrEqual>(loop, i_phi, eighty_const); + HInstruction* i_cmp_top = MakeCondition(loop, kCondGE, i_phi, eighty_const); HIf* loop_if = MakeIf(loop, i_cmp_top); CHECK(loop_if->IfTrueSuccessor() == ret); @@ -1102,7 +1102,7 @@ TEST_F(LoadStoreEliminationTest, ArrayLoopOverlap2) { auto [i_phi, i_add] = MakeLinearLoopVar(loop, body, one_const, one_const); HPhi* t_phi = MakePhi(loop, {zero_const, /* placeholder */ zero_const}); HInstruction* suspend = MakeSuspendCheck(loop); - HInstruction* i_cmp_top = MakeCondition<HGreaterThanOrEqual>(loop, i_phi, eighty_const); + HInstruction* i_cmp_top = MakeCondition(loop, kCondGE, i_phi, eighty_const); HIf* loop_if = MakeIf(loop, i_cmp_top); CHECK(loop_if->IfTrueSuccessor() == ret); @@ -1284,7 +1284,7 @@ TEST_F(LoadStoreEliminationTest, ArrayLoopAliasing1) { // loop auto [i_phi, i_add] = MakeLinearLoopVar(loop, body, c0, c1); HInstruction* loop_suspend_check = MakeSuspendCheck(loop); - HInstruction* loop_cond = MakeCondition<HLessThan>(loop, i_phi, n); + HInstruction* loop_cond = MakeCondition(loop, kCondLT, i_phi, n); HIf* loop_if = MakeIf(loop, loop_cond); CHECK(loop_if->IfTrueSuccessor() == body); ManuallyBuildEnvFor(loop_suspend_check, {}); @@ -1332,7 +1332,7 @@ TEST_F(LoadStoreEliminationTest, ArrayLoopAliasing2) { // loop auto [i_phi, i_add] = MakeLinearLoopVar(loop, body, c0, c1); HInstruction* loop_suspend_check = MakeSuspendCheck(loop); - HInstruction* loop_cond = MakeCondition<HLessThan>(loop, i_phi, n); + HInstruction* loop_cond = MakeCondition(loop, kCondLT, i_phi, n); HIf* loop_if = MakeIf(loop, loop_cond); CHECK(loop_if->IfTrueSuccessor() == body); ManuallyBuildEnvFor(loop_suspend_check, {}); diff --git a/compiler/optimizing/nodes_test.cc b/compiler/optimizing/nodes_test.cc index ce4ad848dd..01e12a061f 100644 --- a/compiler/optimizing/nodes_test.cc +++ b/compiler/optimizing/nodes_test.cc @@ -143,26 +143,14 @@ TEST_F(NodeTest, ClearDominanceThenLoopInformation) { * and environment lists. */ TEST_F(NodeTest, RemoveInstruction) { - HGraph* graph = CreateGraph(); - HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(entry); - graph->SetEntryBlock(entry); - HInstruction* parameter = MakeParam(DataType::Type::kReference); - MakeGoto(entry); + HBasicBlock* main = InitEntryMainExitGraphWithReturnVoid(); - HBasicBlock* first_block = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(first_block); - entry->AddSuccessor(first_block); - HInstruction* null_check = MakeNullCheck(first_block, parameter); - MakeReturnVoid(first_block); + HInstruction* parameter = MakeParam(DataType::Type::kReference); - HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph); - graph->AddBlock(exit_block); - first_block->AddSuccessor(exit_block); - MakeExit(exit_block); + HInstruction* null_check = MakeNullCheck(main, parameter); HEnvironment* environment = new (GetAllocator()) HEnvironment( - GetAllocator(), 1, graph->GetArtMethod(), 0, null_check); + GetAllocator(), 1, graph_->GetArtMethod(), 0, null_check); null_check->SetRawEnvironment(environment); environment->SetRawEnvAt(0, parameter); parameter->AddEnvUseAt(null_check->GetEnvironment(), 0); @@ -170,7 +158,7 @@ TEST_F(NodeTest, RemoveInstruction) { ASSERT_TRUE(parameter->HasEnvironmentUses()); ASSERT_TRUE(parameter->HasUses()); - first_block->RemoveInstruction(null_check); + main->RemoveInstruction(null_check); ASSERT_FALSE(parameter->HasEnvironmentUses()); ASSERT_FALSE(parameter->HasUses()); diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h index f6267c5867..adf24701a5 100644 --- a/compiler/optimizing/optimizing_unit_test.h +++ b/compiler/optimizing/optimizing_unit_test.h @@ -660,17 +660,26 @@ class OptimizingUnitTestHelper { return insn; } - template <typename Type> - Type* MakeCondition(HBasicBlock* block, - HInstruction* first, - HInstruction* second, - uint32_t dex_pc = kNoDexPc) { - static_assert(std::is_base_of_v<HCondition, Type>); - Type* condition = new (GetAllocator()) Type(first, second, dex_pc); + HCondition* MakeCondition(HBasicBlock* block, + IfCondition cond, + HInstruction* first, + HInstruction* second, + uint32_t dex_pc = kNoDexPc) { + HCondition* condition = graph_->CreateCondition(cond, first, second, dex_pc); AddOrInsertInstruction(block, condition); return condition; } + HSelect* MakeSelect(HBasicBlock* block, + HInstruction* condition, + HInstruction* true_value, + HInstruction* false_value, + uint32_t dex_pc = kNoDexPc) { + HSelect* select = new (GetAllocator()) HSelect(condition, true_value, false_value, dex_pc); + AddOrInsertInstruction(block, select); + return select; + } + HSuspendCheck* MakeSuspendCheck(HBasicBlock* block, uint32_t dex_pc = kNoDexPc) { HSuspendCheck* suspend_check = new (GetAllocator()) HSuspendCheck(dex_pc); AddOrInsertInstruction(block, suspend_check); diff --git a/compiler/optimizing/ssa_liveness_analysis_test.cc b/compiler/optimizing/ssa_liveness_analysis_test.cc index a951796526..a0b03ce0e2 100644 --- a/compiler/optimizing/ssa_liveness_analysis_test.cc +++ b/compiler/optimizing/ssa_liveness_analysis_test.cc @@ -149,7 +149,7 @@ TEST_F(SsaLivenessAnalysisTest, TestDeoptimize) { null_check->SetRawEnvironment(null_check_env); HInstruction* length = MakeArrayLength(block, array); // Use HAboveOrEqual+HDeoptimize as the bounds check. - HInstruction* ae = MakeCondition<HAboveOrEqual>(block, index, length); + HInstruction* ae = MakeCondition(block, kCondAE, index, length); HInstruction* deoptimize = new(GetAllocator()) HDeoptimize( GetAllocator(), ae, DeoptimizationKind::kBlockBCE, /* dex_pc= */ 0u); block->AddInstruction(deoptimize); diff --git a/compiler/optimizing/superblock_cloner_test.cc b/compiler/optimizing/superblock_cloner_test.cc index 11d7db8b7e..4a61e45021 100644 --- a/compiler/optimizing/superblock_cloner_test.cc +++ b/compiler/optimizing/superblock_cloner_test.cc @@ -48,9 +48,9 @@ class SuperblockClonerTest : public OptimizingUnitTest { HIntConstant* const_128 = graph_->GetIntConstant(128); // Header block. - HPhi* phi = MakePhi(loop_header, {const_0, /* placeholder */ const_0}); + auto [phi, induction_inc] = MakeLinearLoopVar(loop_header, loop_body, const_0, const_1); HInstruction* suspend_check = MakeSuspendCheck(loop_header); - HInstruction* loop_check = MakeCondition<HGreaterThanOrEqual>(loop_header, phi, const_128); + HInstruction* loop_check = MakeCondition(loop_header, kCondGE, phi, const_128); MakeIf(loop_header, loop_check); // Loop body block. @@ -62,9 +62,6 @@ class SuperblockClonerTest : public OptimizingUnitTest { HInstruction* add = MakeBinOp<HAdd>(loop_body, DataType::Type::kInt32, array_get, const_1); HInstruction* array_set = MakeArraySet(loop_body, null_check, bounds_check, add, DataType::Type::kInt32, dex_pc); - HInstruction* induction_inc = MakeBinOp<HAdd>(loop_body, DataType::Type::kInt32, phi, const_1); - - phi->ReplaceInput(induction_inc, 1u); // Update back-edge input. graph_->SetHasBoundsChecks(true); |