blob: 345ff721487313f7895698a3bfcddfcbf05b86a7 [file] [log] [blame]
Roland Levillain72bceff2014-09-15 18:29:00 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "dead_code_elimination.h"
18
19#include "base/bit_vector-inl.h"
David Brazdil84daae52015-05-18 12:06:52 +010020#include "ssa_phi_elimination.h"
Roland Levillain72bceff2014-09-15 18:29:00 +010021
22namespace art {
23
David Brazdil2d7352b2015-04-20 14:52:42 +010024static void MarkReachableBlocks(HBasicBlock* block, ArenaBitVector* visited) {
25 int block_id = block->GetBlockId();
26 if (visited->IsBitSet(block_id)) {
27 return;
28 }
29 visited->SetBit(block_id);
30
31 HInstruction* last_instruction = block->GetLastInstruction();
32 if (last_instruction->IsIf()) {
33 HIf* if_instruction = last_instruction->AsIf();
34 HInstruction* condition = if_instruction->InputAt(0);
35 if (!condition->IsIntConstant()) {
36 MarkReachableBlocks(if_instruction->IfTrueSuccessor(), visited);
37 MarkReachableBlocks(if_instruction->IfFalseSuccessor(), visited);
38 } else if (condition->AsIntConstant()->IsOne()) {
39 MarkReachableBlocks(if_instruction->IfTrueSuccessor(), visited);
40 } else {
41 DCHECK(condition->AsIntConstant()->IsZero());
42 MarkReachableBlocks(if_instruction->IfFalseSuccessor(), visited);
43 }
Mark Mendellfe57faa2015-09-18 09:26:15 -040044 } else if (last_instruction->IsPackedSwitch() &&
45 last_instruction->AsPackedSwitch()->InputAt(0)->IsIntConstant()) {
46 HPackedSwitch* switch_instruction = last_instruction->AsPackedSwitch();
47 int32_t switch_value = switch_instruction->InputAt(0)->AsIntConstant()->GetValue();
48 int32_t start_value = switch_instruction->GetStartValue();
49 int32_t last_value = start_value + switch_instruction->GetNumEntries();
50 for (int32_t case_value = start_value; case_value <= last_value; case_value++) {
51 if (case_value == last_value) {
52 MarkReachableBlocks(switch_instruction->GetDefaultBlock(), visited);
53 }
54 if (case_value == switch_value) {
55 MarkReachableBlocks(block->GetSuccessor(case_value - start_value), visited);
56 break;
57 }
58 }
David Brazdil2d7352b2015-04-20 14:52:42 +010059 } else {
Vladimir Marko60584552015-09-03 13:35:12 +000060 for (HBasicBlock* successor : block->GetSuccessors()) {
61 MarkReachableBlocks(successor, visited);
David Brazdil2d7352b2015-04-20 14:52:42 +010062 }
63 }
64}
65
David Brazdila4b8c212015-05-07 09:59:30 +010066static void MarkLoopHeadersContaining(const HBasicBlock& block, ArenaBitVector* set) {
67 for (HLoopInformationOutwardIterator it(block); !it.Done(); it.Advance()) {
68 set->SetBit(it.Current()->GetHeader()->GetBlockId());
69 }
70}
71
David Brazdil2d7352b2015-04-20 14:52:42 +010072void HDeadCodeElimination::MaybeRecordDeadBlock(HBasicBlock* block) {
73 if (stats_ != nullptr) {
74 stats_->RecordStat(MethodCompilationStat::kRemovedDeadInstruction,
75 block->GetPhis().CountSize() + block->GetInstructions().CountSize());
76 }
77}
78
79void HDeadCodeElimination::RemoveDeadBlocks() {
80 // Classify blocks as reachable/unreachable.
81 ArenaAllocator* allocator = graph_->GetArena();
Vladimir Markofa6b93c2015-09-15 10:15:55 +010082 ArenaBitVector live_blocks(allocator, graph_->GetBlocks().size(), false);
83 ArenaBitVector affected_loops(allocator, graph_->GetBlocks().size(), false);
David Brazdila4b8c212015-05-07 09:59:30 +010084
David Brazdil2d7352b2015-04-20 14:52:42 +010085 MarkReachableBlocks(graph_->GetEntryBlock(), &live_blocks);
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +010086 bool removed_one_or_more_blocks = false;
David Brazdil2d7352b2015-04-20 14:52:42 +010087
David Brazdila4b8c212015-05-07 09:59:30 +010088 // Remove all dead blocks. Iterate in post order because removal needs the
89 // block's chain of dominators and nested loops need to be updated from the
90 // inside out.
David Brazdil2d7352b2015-04-20 14:52:42 +010091 for (HPostOrderIterator it(*graph_); !it.Done(); it.Advance()) {
92 HBasicBlock* block = it.Current();
David Brazdila4b8c212015-05-07 09:59:30 +010093 int id = block->GetBlockId();
94 if (live_blocks.IsBitSet(id)) {
95 if (affected_loops.IsBitSet(id)) {
96 DCHECK(block->IsLoopHeader());
97 block->GetLoopInformation()->Update();
98 }
David Brazdil69a28042015-04-29 17:16:07 +010099 } else {
100 MaybeRecordDeadBlock(block);
David Brazdila4b8c212015-05-07 09:59:30 +0100101 MarkLoopHeadersContaining(*block, &affected_loops);
David Brazdil69a28042015-04-29 17:16:07 +0100102 block->DisconnectAndDelete();
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100103 removed_one_or_more_blocks = true;
David Brazdil2d7352b2015-04-20 14:52:42 +0100104 }
David Brazdil2d7352b2015-04-20 14:52:42 +0100105 }
106
Nicolas Geoffray1f82ecc2015-06-24 12:20:24 +0100107 // If we removed at least one block, we need to recompute the full
108 // dominator tree.
109 if (removed_one_or_more_blocks) {
110 graph_->ClearDominanceInformation();
111 graph_->ComputeDominanceInformation();
112 }
113
David Brazdil2d7352b2015-04-20 14:52:42 +0100114 // Connect successive blocks created by dead branches. Order does not matter.
115 for (HReversePostOrderIterator it(*graph_); !it.Done();) {
116 HBasicBlock* block = it.Current();
Vladimir Marko60584552015-09-03 13:35:12 +0000117 if (block->IsEntryBlock() || block->GetSuccessors().size() != 1u) {
David Brazdil2d7352b2015-04-20 14:52:42 +0100118 it.Advance();
119 continue;
120 }
Vladimir Marko60584552015-09-03 13:35:12 +0000121 HBasicBlock* successor = block->GetSuccessor(0);
122 if (successor->IsExitBlock() || successor->GetPredecessors().size() != 1u) {
David Brazdil2d7352b2015-04-20 14:52:42 +0100123 it.Advance();
124 continue;
125 }
126 block->MergeWith(successor);
127
128 // Reiterate on this block in case it can be merged with its new successor.
129 }
130}
131
132void HDeadCodeElimination::RemoveDeadInstructions() {
Roland Levillain72bceff2014-09-15 18:29:00 +0100133 // Process basic blocks in post-order in the dominator tree, so that
David Brazdil2d7352b2015-04-20 14:52:42 +0100134 // a dead instruction depending on another dead instruction is removed.
Roland Levillain72bceff2014-09-15 18:29:00 +0100135 for (HPostOrderIterator b(*graph_); !b.Done(); b.Advance()) {
136 HBasicBlock* block = b.Current();
137 // Traverse this block's instructions in backward order and remove
138 // the unused ones.
139 HBackwardInstructionIterator i(block->GetInstructions());
140 // Skip the first iteration, as the last instruction of a block is
141 // a branching instruction.
142 DCHECK(i.Current()->IsControlFlow());
143 for (i.Advance(); !i.Done(); i.Advance()) {
144 HInstruction* inst = i.Current();
145 DCHECK(!inst->IsControlFlow());
Alexandre Rames78e3ef62015-08-12 13:43:29 +0100146 if (!inst->HasSideEffects()
Roland Levillaine161a2a2014-10-03 12:45:18 +0100147 && !inst->CanThrow()
148 && !inst->IsSuspendCheck()
Nicolas Geoffray839188b2015-06-02 10:38:12 +0100149 // If we added an explicit barrier then we should keep it.
150 && !inst->IsMemoryBarrier()
Nicolas Geoffraye418dda2015-08-11 20:03:09 -0700151 && !inst->IsParameterValue()
Roland Levillaine161a2a2014-10-03 12:45:18 +0100152 && !inst->HasUses()) {
Roland Levillain72bceff2014-09-15 18:29:00 +0100153 block->RemoveInstruction(inst);
Calin Juravle8f20bdb2015-04-21 14:07:50 +0100154 MaybeRecordStat(MethodCompilationStat::kRemovedDeadInstruction);
Roland Levillain72bceff2014-09-15 18:29:00 +0100155 }
156 }
157 }
158}
159
David Brazdil2d7352b2015-04-20 14:52:42 +0100160void HDeadCodeElimination::Run() {
David Brazdilbbd733e2015-08-18 17:48:17 +0100161 if (!graph_->HasTryCatch()) {
162 // TODO: Update dead block elimination and enable for try/catch.
163 RemoveDeadBlocks();
164 }
David Brazdil84daae52015-05-18 12:06:52 +0100165 SsaRedundantPhiElimination(graph_).Run();
David Brazdil2d7352b2015-04-20 14:52:42 +0100166 RemoveDeadInstructions();
167}
168
Roland Levillain72bceff2014-09-15 18:29:00 +0100169} // namespace art