Flutter Engine
The Flutter Engine
Static Public Member Functions | List of all members
dart::IfConverter Class Reference

#include <branch_optimizer.h>

Inheritance diagram for dart::IfConverter:
dart::AllStatic

Static Public Member Functions

static void Simplify (FlowGraph *flow_graph)
 

Detailed Description

Definition at line 58 of file branch_optimizer.h.

Member Function Documentation

◆ Simplify()

void dart::IfConverter::Simplify ( FlowGraph flow_graph)
static

Definition at line 242 of file branch_optimizer.cc.

242 {
243 Zone* zone = flow_graph->zone();
244 bool changed = false;
245
246 const GrowableArray<BlockEntryInstr*>& postorder = flow_graph->postorder();
247 for (BlockIterator it(postorder); !it.Done(); it.Advance()) {
248 BlockEntryInstr* block = it.Current();
249 JoinEntryInstr* join = block->AsJoinEntry();
250
251 // Detect diamond control flow pattern which materializes a value depending
252 // on the result of the comparison:
253 //
254 // B_pred:
255 // ...
256 // Branch if COMP goto (B_pred1, B_pred2)
257 // B_pred1: -- trivial block that contains at most one definition
258 // v1 = Constant(...)
259 // goto B_block
260 // B_pred2: -- trivial block that contains at most one definition
261 // v2 = Constant(...)
262 // goto B_block
263 // B_block:
264 // v3 = phi(v1, v2) -- single phi
265 //
266 // and replace it with
267 //
268 // Ba:
269 // v3 = IfThenElse(COMP ? v1 : v2)
270 //
271 if ((join != nullptr) && (join->phis() != nullptr) &&
272 (join->phis()->length() == 1) && (block->PredecessorCount() == 2)) {
273 BlockEntryInstr* pred1 = block->PredecessorAt(0);
274 BlockEntryInstr* pred2 = block->PredecessorAt(1);
275
276 PhiInstr* phi = (*join->phis())[0];
277 Value* v1 = phi->InputAt(0);
278 Value* v2 = phi->InputAt(1);
279
280 if (IsTrivialBlock(pred1, v1->definition()) &&
281 IsTrivialBlock(pred2, v2->definition()) &&
282 (pred1->PredecessorAt(0) == pred2->PredecessorAt(0))) {
283 BlockEntryInstr* pred = pred1->PredecessorAt(0);
284 BranchInstr* branch = pred->last_instruction()->AsBranch();
285
286 if (branch == nullptr) {
287 // There is no "B_pred" block, or the block is the IndirectGoto
288 // of a switch that uses it as a jump table.
289 ASSERT(pred->last_instruction()->IsGraphEntry() ||
290 pred->last_instruction()->IsIndirectGoto());
291 continue;
292 }
293
294 ComparisonInstr* comparison = branch->comparison();
295
296 // Check if the platform supports efficient branchless IfThenElseInstr
297 // for the given combination of comparison and values flowing from
298 // false and true paths.
299 if (IfThenElseInstr::Supports(comparison, v1, v2)) {
300 Value* if_true = (pred1 == branch->true_successor()) ? v1 : v2;
301 Value* if_false = (pred2 == branch->true_successor()) ? v1 : v2;
302
303 ComparisonInstr* new_comparison = comparison->CopyWithNewOperands(
304 comparison->left()->Copy(zone), comparison->right()->Copy(zone));
305 IfThenElseInstr* if_then_else =
306 new (zone) IfThenElseInstr(new_comparison, if_true->Copy(zone),
307 if_false->Copy(zone), DeoptId::kNone);
308 flow_graph->InsertBefore(branch, if_then_else, nullptr,
310
311 phi->ReplaceUsesWith(if_then_else);
312
313 // Connect IfThenElseInstr to the first instruction in the merge block
314 // effectively eliminating diamond control flow.
315 // Current block as well as pred1 and pred2 blocks are no longer in
316 // the graph at this point.
317 if_then_else->LinkTo(join->next());
318 pred->set_last_instruction(join->last_instruction());
319
320 // Resulting block must inherit block id from the eliminated current
321 // block to guarantee that ordering of phi operands in its successor
322 // stays consistent.
323 pred->set_block_id(block->block_id());
324
325 // If v1 and v2 were defined inside eliminated blocks pred1/pred2
326 // move them out to the place before inserted IfThenElse instruction.
327 EliminateTrivialBlock(pred1, v1->definition(), if_then_else);
328 EliminateTrivialBlock(pred2, v2->definition(), if_then_else);
329
330 // Update use lists to reflect changes in the graph.
331 phi->UnuseAllInputs();
332 branch->UnuseAllInputs();
333 block->UnuseAllInputs();
334
335 // The graph has changed. Recompute dominators and block orders after
336 // this pass is finished.
337 changed = true;
338 }
339 }
340 }
341 }
342
343 if (changed) {
344 // We may have changed the block order and the dominator tree.
345 flow_graph->DiscoverBlocks();
346 GrowableArray<BitVector*> dominance_frontier;
347 flow_graph->ComputeDominators(&dominance_frontier);
348 }
349}
SI T if_then_else(C cond, T t, T e)
Vec2Value v2
static constexpr intptr_t kNone
Definition: deopt_id.h:27
static bool Supports(ComparisonInstr *comparison, Value *v1, Value *v2)
Definition: il.cc:6613
#define ASSERT(E)
static bool IsTrivialBlock(BlockEntryInstr *block, Definition *defn)
static void EliminateTrivialBlock(BlockEntryInstr *block, Definition *instr, IfThenElseInstr *before)
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741

The documentation for this class was generated from the following files: