"post dominator, out of line."),
cl::init(false), cl::Hidden);
+static cl::opt<unsigned> OutlineOptionalThreshold(
+ "outline-optional-threshold",
+ cl::desc("Don't outline optional branches that are a single block with an "
+ "instruction count below this threshold"),
+ cl::init(4), cl::Hidden);
+
namespace {
class BlockChain;
/// \brief Type for our function-wide basic block -> block chain mapping.
// dominates all terminators of the MachineFunction. If it does, other
// successors must be optional. Don't do this for cold branches.
if (OutlineOptionalBranches && SuccProb > HotProb.getCompl() &&
- UnavoidableBlocks.count(Succ) > 0)
- return Succ;
+ UnavoidableBlocks.count(Succ) > 0) {
+ auto HasShortOptionalBranch = [&]() {
+ for (MachineBasicBlock *Pred : Succ->predecessors()) {
+ // Check whether there is an unplaced optional branch.
+ if (Pred == Succ || (BlockFilter && !BlockFilter->count(Pred)) ||
+ BlockToChain[Pred] == &Chain)
+ continue;
+ // Check whether the optional branch has exactly one BB.
+ if (Pred->pred_size() > 1 || *Pred->pred_begin() != BB)
+ continue;
+ // Check whether the optional branch is small.
+ if (Pred->size() < OutlineOptionalThreshold)
+ return true;
+ }
+ return false;
+ };
+ if (!HasShortOptionalBranch())
+ return Succ;
+ }
// Only consider successors which are either "hot", or wouldn't violate
// any CFG constraints.
; RUN: llc -mcpu=corei7 -mtriple=x86_64-linux < %s | FileCheck %s -check-prefix=CHECK
; RUN: llc -mcpu=corei7 -mtriple=x86_64-linux -outline-optional-branches < %s | FileCheck %s -check-prefix=CHECK-OUTLINE
-define void @foo(i32 %t1, i32 %t2) {
+define void @foo(i32 %t1, i32 %t2, i32 %t3) {
; Test that we lift the call to 'c' up to immediately follow the call to 'b'
; when we disable the cfg conflict check.
;
; CHECK-LABEL: foo:
; CHECK: callq a
+; CHECK: callq a
+; CHECK: callq a
+; CHECK: callq a
; CHECK: callq b
; CHECK: callq c
; CHECK: callq d
+; CHECK: callq e
+; CHECK: callq f
;
; CHECK-OUTLINE-LABEL: foo:
; CHECK-OUTLINE: callq b
; CHECK-OUTLINE: callq c
; CHECK-OUTLINE: callq d
+; CHECK-OUTLINE: callq e
+; CHECK-OUTLINE: callq f
+; CHECK-OUTLINE: callq a
+; CHECK-OUTLINE: callq a
+; CHECK-OUTLINE: callq a
; CHECK-OUTLINE: callq a
entry:
if.then:
call void @a()
+ call void @a()
+ call void @a()
+ call void @a()
br label %if.end
if.end:
if.end2:
call void @d()
+ br label %shortbranch
+
+shortbranch:
+ %cmp3 = icmp eq i32 %t3, 0
+ br i1 %cmp3, label %if.then3, label %if.end3
+
+if.then3:
+ call void @e()
+ br label %if.end3
+
+if.end3:
+ call void @f()
ret void
}
declare void @b()
declare void @c()
declare void @d()
+declare void @e()
+declare void @f()
!1 = !{!"branch_weights", i32 64, i32 4}