98 {
99
100
101
102
103
104
105
106
107
108
109
110 Zone* zone = flow_graph->zone();
111 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder();
112 GrowableArray<BlockEntryInstr*>
worklist(postorder.length());
113 for (BlockIterator it(postorder); !it.Done(); it.Advance()) {
114 BlockEntryInstr* block = it.Current();
115 if (block->IsJoinEntry() && block->last_instruction()->IsBranch()) {
117 }
118 }
119
120
121 bool changed = false;
123
124 JoinEntryInstr* block =
worklist.RemoveLast()->AsJoinEntry();
126
127 if (Match(block)) {
128 changed = true;
129
130
131
132
133
134
135
136
137
138 BranchInstr* branch = block->last_instruction()->AsBranch();
139 ASSERT(branch !=
nullptr);
140 JoinEntryInstr* join_true =
ToJoinEntry(zone, branch->true_successor());
141 JoinEntryInstr* join_false =
ToJoinEntry(zone, branch->false_successor());
142
143 ComparisonInstr* comparison = branch->comparison();
144 PhiInstr* phi = comparison->left()->definition()->AsPhi();
145 ConstantInstr* constant = comparison->right()->definition()->AsConstant();
146 ASSERT(constant !=
nullptr);
147
148 for (intptr_t
i = 0,
count = block->PredecessorCount();
i <
count; ++
i) {
149 GotoInstr* old_goto =
150 block->PredecessorAt(
i)->last_instruction()->AsGoto();
151 ASSERT(old_goto !=
nullptr);
152
153
154
155 Value* new_left = phi->InputAt(
i)->Copy(zone);
156 Value* new_right =
new (zone)
Value(constant);
157 BranchInstr* new_branch =
158 CloneBranch(zone, branch, new_left, new_right);
159 if (branch->env() == nullptr) {
160 new_branch->InheritDeoptTarget(zone, old_goto);
161 } else {
162
163 new_branch->InheritDeoptTarget(zone, branch);
164
165
166
167 new_branch->comparison()->SetDeoptId(*comparison);
168
169
170 Definition* replacement = phi->InputAt(
i)->definition();
171 new_branch->ReplaceInEnvironment(phi, replacement);
172 }
173
174 new_branch->InsertBefore(old_goto);
175 new_branch->set_next(nullptr);
176 old_goto->UnuseAllInputs();
177
178
179
180 BlockEntryInstr* branch_block = new_branch->GetBlock();
181 branch_block->set_last_instruction(new_branch);
182 if (branch_block->IsJoinEntry())
worklist.Add(branch_block);
183
184
185
186 TargetEntryInstr* true_target = new (zone) TargetEntryInstr(
187 flow_graph->max_block_id() + 1, block->try_index(),
DeoptId::kNone);
188 true_target->InheritDeoptTarget(zone, join_true);
189 TargetEntryInstr* false_target = new (zone) TargetEntryInstr(
190 flow_graph->max_block_id() + 2, block->try_index(),
DeoptId::kNone);
191 false_target->InheritDeoptTarget(zone, join_false);
192 flow_graph->set_max_block_id(flow_graph->max_block_id() + 2);
193 *new_branch->true_successor_address() = true_target;
194 *new_branch->false_successor_address() = false_target;
195 GotoInstr* goto_true =
new (zone) GotoInstr(join_true,
DeoptId::kNone);
196 goto_true->InheritDeoptTarget(zone, join_true);
197 true_target->LinkTo(goto_true);
198 true_target->set_last_instruction(goto_true);
199 GotoInstr* goto_false =
201 goto_false->InheritDeoptTarget(zone, join_false);
202 false_target->LinkTo(goto_false);
203 false_target->set_last_instruction(goto_false);
204 }
205
206
207 phi->UnuseAllInputs();
208 branch->UnuseAllInputs();
209 block->UnuseAllInputs();
211 }
212 }
213
214 if (changed) {
215
216 flow_graph->DiscoverBlocks();
217 GrowableArray<BitVector*> dominance_frontier;
218 flow_graph->ComputeDominators(&dominance_frontier);
219 }
220}
static JoinEntryInstr * ToJoinEntry(Zone *zone, BlockEntryInstr *target)
static constexpr intptr_t kNone