diff options
author | 2025-01-22 14:23:27 +0000 | |
---|---|---|
committer | 2025-01-23 00:28:41 -0800 | |
commit | d661c115a57277e64e8225d2d69629635f7d4e3a (patch) | |
tree | e5b6b3900ffc030600183e3b0c15f431cbfcade1 | |
parent | 74d140050d566f40ecc021c3c80393931fff2d7f (diff) |
Optimizing: Remove `CreateDoWhileLoop()`.
And do some other gtest cleanup.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: I9d2c3241e5cd9f96722284c4654b8b2fd446b104
-rw-r--r-- | compiler/optimizing/code_flow_simplifier_test.cc | 14 | ||||
-rw-r--r-- | compiler/optimizing/load_store_elimination_test.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/optimizing_unit_test.h | 57 |
3 files changed, 37 insertions, 36 deletions
diff --git a/compiler/optimizing/code_flow_simplifier_test.cc b/compiler/optimizing/code_flow_simplifier_test.cc index a382f0f6f6..1abd9f8fa6 100644 --- a/compiler/optimizing/code_flow_simplifier_test.cc +++ b/compiler/optimizing/code_flow_simplifier_test.cc @@ -58,7 +58,7 @@ TEST_F(CodeFlowSimplifierTest, testZeroCheckPreventsSelect) { ManuallyBuildEnvFor(instr, {param, graph_->GetIntConstant(1)}); EXPECT_FALSE(CheckGraphAndTryCodeFlowSimplifier()); - EXPECT_FALSE(phi->GetBlock() == nullptr); + EXPECT_INS_RETAINED(phi); } // Test that CodeFlowSimplifier succeeds with HAdd. @@ -68,7 +68,7 @@ TEST_F(CodeFlowSimplifierTest, testSelectWithAdd) { HAdd* instr = new (GetAllocator()) HAdd(DataType::Type::kInt32, param, param, /*dex_pc=*/ 0); HPhi* phi = ConstructBasicGraphForSelect(return_block, instr); EXPECT_TRUE(CheckGraphAndTryCodeFlowSimplifier()); - EXPECT_TRUE(phi->GetBlock() == nullptr); + EXPECT_INS_REMOVED(phi); } // Test `HSelect` optimization in an irreducible loop. @@ -84,10 +84,8 @@ TEST_F(CodeFlowSimplifierTest, testSelectInIrreducibleLoop) { HInstruction* const0 = graph_->GetIntConstant(0); HInstruction* const1 = graph_->GetIntConstant(1); - HPhi* right_phi = MakePhi(right_header, {const0, /* placeholder */ const0}); - HPhi* left_phi = MakePhi(left_header, {const1, right_phi}); - HAdd* add = MakeBinOp<HAdd>(body, DataType::Type::kInt32, left_phi, const1); - right_phi->ReplaceInput(add, 1u); // Update back-edge input. + auto [left_phi, right_phi, add] = + MakeLinearIrreducibleLoopVar(left_header, right_header, body, const1, const0, const1); HCondition* condition = MakeCondition(left_header, kCondGE, left_phi, n_param); MakeIf(left_header, condition); @@ -99,14 +97,14 @@ TEST_F(CodeFlowSimplifierTest, testSelectInIrreducibleLoop) { ASSERT_TRUE(loop_info != nullptr); ASSERT_TRUE(loop_info->IsIrreducible()); - EXPECT_TRUE(phi->GetBlock() == nullptr); + EXPECT_INS_REMOVED(phi); ASSERT_TRUE(if_block->GetFirstInstruction()->IsSelect()); ASSERT_EQ(if_block, add->GetBlock()); // Moved when merging blocks. for (HBasicBlock* removed_block : {then_block, else_block, body}) { + ASSERT_BLOCK_REMOVED(removed_block); uint32_t removed_block_id = removed_block->GetBlockId(); - ASSERT_TRUE(removed_block->GetGraph() == nullptr) << removed_block_id; ASSERT_FALSE(loop_info->GetBlocks().IsBitSet(removed_block_id)) << removed_block_id; } } diff --git a/compiler/optimizing/load_store_elimination_test.cc b/compiler/optimizing/load_store_elimination_test.cc index 1e5c7082a4..347a050a3b 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 // Return the pre-header and loop block. std::tuple<HBasicBlock*, HBasicBlock*> CreateDoWhileLoopWithInstructions( HBasicBlock* loop_exit, std::initializer_list<HInstruction*> suspend_check_env = {}) { - auto [pre_header, loop] = CreateDoWhileLoop(loop_exit); + auto [pre_header, loop, back_edge] = CreateWhileLoop(loop_exit); MakeSimpleLoopInstructions(loop, loop, suspend_check_env); return {pre_header, loop}; } diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h index 8115ea035d..21998b19da 100644 --- a/compiler/optimizing/optimizing_unit_test.h +++ b/compiler/optimizing/optimizing_unit_test.h @@ -90,6 +90,11 @@ inline std::ostream& operator<<(std::ostream& os, const InstructionDumper& id) { #define ASSERT_INS_REMOVED(a) ASSERT_TRUE(IsRemoved(a)) << "Not removed: " << (InstructionDumper{a}) #define ASSERT_INS_RETAINED(a) ASSERT_FALSE(IsRemoved(a)) << "Removed: " << (InstructionDumper{a}) +#define EXPECT_BLOCK_REMOVED(b) EXPECT_TRUE(IsRemoved(b)) << "Not removed: B" << b->GetBlockId() +#define EXPECT_BLOCK_RETAINED(b) EXPECT_FALSE(IsRemoved(b)) << "Removed: B" << b->GetBlockId() +#define ASSERT_BLOCK_REMOVED(b) ASSERT_TRUE(IsRemoved(b)) << "Not removed: B" << b->GetBlockId() +#define ASSERT_BLOCK_RETAINED(b) ASSERT_FALSE(IsRemoved(b)) << "Removed: B" << b->GetBlockId() + inline LiveInterval* BuildInterval(const size_t ranges[][2], size_t number_of_ranges, ScopedArenaAllocator* allocator, @@ -348,6 +353,8 @@ class OptimizingUnitTestHelper { // empty, leaving the construction of an appropriate condition and `HIf` to the caller. // Note: The `loop_exit` shall be the "then" successor of the "loop-header". If the `loop_exit` // is needed as the "else" successor, use `HBlock::SwapSuccessors()` to adjust the order. + // Note: A `do { ... } while (...);` loop pattern has the same block structure, except that + // the `loop_body` is a single-goto block that exists purely to avoid a critical edge. std::tuple<HBasicBlock*, HBasicBlock*, HBasicBlock*> CreateWhileLoop(HBasicBlock* loop_exit) { HBasicBlock* pre_header = AddNewBlock(); HBasicBlock* loop_header = AddNewBlock(); @@ -367,28 +374,6 @@ class OptimizingUnitTestHelper { return {pre_header, loop_header, loop_body}; } - // Insert "pre-header" and "loop" blocks before a given `loop_exit` block and connect them in a - // `do { ... } while (...);` loop pattern. Return the new blocks. Adds `HGoto` to the "pre-header" - // block but leaves the "loop" block empty, leaving the construction of an appropriate condition - // and `HIf` to the caller. - // Note: The `loop_exit` shall be the "then" successor of the "loop". If the `loop_exit` - // is needed as the "else" successor, use `HBlock::SwapSuccessors()` to adjust the order. - std::tuple<HBasicBlock*, HBasicBlock*> CreateDoWhileLoop(HBasicBlock* loop_exit) { - HBasicBlock* pre_header = AddNewBlock(); - HBasicBlock* loop = AddNewBlock(); - - HBasicBlock* predecessor = loop_exit->GetSinglePredecessor(); - predecessor->ReplaceSuccessor(loop_exit, pre_header); - - pre_header->AddSuccessor(loop); - loop->AddSuccessor(loop_exit); // true successor - loop->AddSuccessor(loop); // false successor - - MakeGoto(pre_header); - - return {pre_header, loop}; - } - // Insert blocks for an irreducible loop before the `loop_exit`: // // <loop_exit's old predecessor> @@ -923,6 +908,19 @@ class OptimizingUnitTestHelper { return {phi, add}; } + std::tuple<HPhi*, HPhi*, HAdd*> MakeLinearIrreducibleLoopVar(HBasicBlock* left_header, + HBasicBlock* right_header, + HBasicBlock* body, + HInstruction* left_initial, + HInstruction* right_initial, + HInstruction* increment) { + HPhi* left_phi = MakePhi(left_header, {left_initial, /* placeholder */ left_initial}); + HAdd* add = MakeBinOp<HAdd>(body, left_phi->GetType(), left_phi, increment); + HPhi* right_phi = MakePhi(right_header, {right_initial, add}); + left_phi->ReplaceInput(right_phi, 1u); // Update back-edge input. + return {left_phi, right_phi, add}; + } + dex::TypeIndex DefaultTypeIndexForType(DataType::Type type) { switch (type) { case DataType::Type::kBool: @@ -959,6 +957,16 @@ class OptimizingUnitTestHelper { return val; } + // Returns if the `instruction` is removed from the graph. + static inline bool IsRemoved(HInstruction* instruction) { + return instruction->GetBlock() == nullptr; + } + + // Returns if the `block` is removed from the graph. + static inline bool IsRemoved(HBasicBlock* block) { + return block->GetGraph() == nullptr; + } + protected: bool CheckGraph(HGraph* graph, std::ostream& oss) { GraphChecker checker(graph); @@ -1006,11 +1014,6 @@ inline std::string Patch(const std::string& original, const diff_t& diff) { return result; } -// Returns if the instruction is removed from the graph. -inline bool IsRemoved(HInstruction* instruction) { - return instruction->GetBlock() == nullptr; -} - inline std::ostream& operator<<(std::ostream& oss, const AdjacencyListGraph& alg) { return alg.Dump(oss); } |