summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-08-15 07:40:38 +0000
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-08-21 09:12:50 +0000
commitc08fb725b561ead05dc120f2e92ea5228d14eec0 (patch)
treec306cd68d8f26a33b3c45e2f07db695dccc00e6e
parent1ea8807afeea6cd48127449cbd10458cc32cf4ce (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.cc56
-rw-r--r--compiler/optimizing/codegen_test.cc48
-rw-r--r--compiler/optimizing/constant_folding_test.cc145
-rw-r--r--compiler/optimizing/graph_test.cc2
-rw-r--r--compiler/optimizing/gvn_test.cc155
-rw-r--r--compiler/optimizing/induction_var_analysis_test.cc2
-rw-r--r--compiler/optimizing/induction_var_range_test.cc7
-rw-r--r--compiler/optimizing/licm_test.cc52
-rw-r--r--compiler/optimizing/load_store_analysis_test.cc303
-rw-r--r--compiler/optimizing/load_store_elimination_test.cc12
-rw-r--r--compiler/optimizing/nodes_test.cc22
-rw-r--r--compiler/optimizing/optimizing_unit_test.h23
-rw-r--r--compiler/optimizing/ssa_liveness_analysis_test.cc2
-rw-r--r--compiler/optimizing/superblock_cloner_test.cc7
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, &current_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);