diff options
-rw-r--r-- | lib/CodeGen/MachineBlockPlacement.cpp | 32 | ||||
-rw-r--r-- | test/CodeGen/X86/block-placement.ll | 36 |
2 files changed, 65 insertions, 3 deletions
diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp index e83ae93..4cbc94e 100644 --- a/lib/CodeGen/MachineBlockPlacement.cpp +++ b/lib/CodeGen/MachineBlockPlacement.cpp @@ -365,9 +365,35 @@ MachineBasicBlock *MachineBlockPlacement::selectBestSuccessor( // Only consider successors which are either "hot", or wouldn't violate // any CFG constraints. - if (SuccChain.LoopPredecessors != 0 && SuccProb < HotProb) { - DEBUG(dbgs() << " " << getBlockName(*SI) << " -> CFG conflict\n"); - continue; + if (SuccChain.LoopPredecessors != 0) { + if (SuccProb < HotProb) { + DEBUG(dbgs() << " " << getBlockName(*SI) << " -> CFG conflict\n"); + continue; + } + + // Make sure that a hot successor doesn't have a globally more important + // predecessor. + BlockFrequency CandidateEdgeFreq + = MBFI->getBlockFreq(BB) * SuccProb * HotProb.getCompl(); + bool BadCFGConflict = false; + for (MachineBasicBlock::pred_iterator PI = (*SI)->pred_begin(), + PE = (*SI)->pred_end(); + PI != PE; ++PI) { + if (*PI == *SI || (BlockFilter && !BlockFilter->count(*PI)) || + BlockToChain[*PI] == &Chain) + continue; + BlockFrequency PredEdgeFreq + = MBFI->getBlockFreq(*PI) * MBPI->getEdgeProbability(*PI, *SI); + if (PredEdgeFreq >= CandidateEdgeFreq) { + BadCFGConflict = true; + break; + } + } + if (BadCFGConflict) { + DEBUG(dbgs() << " " << getBlockName(*SI) + << " -> non-cold CFG conflict\n"); + continue; + } } DEBUG(dbgs() << " " << getBlockName(*SI) << " -> " << SuccProb diff --git a/test/CodeGen/X86/block-placement.ll b/test/CodeGen/X86/block-placement.ll index 16e98ed..b488cdd 100644 --- a/test/CodeGen/X86/block-placement.ll +++ b/test/CodeGen/X86/block-placement.ll @@ -439,3 +439,39 @@ if.end: } !1 = metadata !{metadata !"branch_weights", i32 1000, i32 1} + +declare i32 @f() +declare i32 @g() +declare i32 @h(i32 %x) + +define i32 @test_global_cfg_break_profitability() { +; Check that our metrics for the profitability of a CFG break are global rather +; than local. A successor may be very hot, but if the current block isn't, it +; doesn't matter. Within this test the 'then' block is slightly warmer than the +; 'else' block, but not nearly enough to merit merging it with the exit block +; even though the probability of 'then' branching to the 'exit' block is very +; high. +; CHECK: test_global_cfg_break_profitability +; CHECK: calll f +; CHECK: calll g +; CHECK: calll h +; CHECK: ret + +entry: + br i1 undef, label %then, label %else, !prof !2 + +then: + %then.result = call i32 @f() + br label %exit + +else: + %else.result = call i32 @g() + br label %exit + +exit: + %result = phi i32 [ %then.result, %then ], [ %else.result, %else ] + %result2 = call i32 @h(i32 %result) + ret i32 %result +} + +!2 = metadata !{metadata !"branch_weights", i32 3, i32 1} |