forked from OSchip/llvm-project
[SimplifyCFG] Avoid quadratic on a predecessors number behavior in instruction sinking.
If a block has N predecessors, then the current algorithm will try to sink common code to this block N times (whenever we visit a predecessor). Every attempt to sink the common code includes going through all predecessors, so the complexity of the algorithm becomes O(N^2). With this patch we try to sink common code only when we visit the block itself. With this, the complexity goes down to O(N). As a side effect, the moment the code is sunk is slightly different than before (the order of simplifications has been changed), that's why I had to adjust two tests (note that neither of the tests is supposed to test SimplifyCFG): * test/CodeGen/AArch64/arm64-jumptable.ll - changes in this test mimic the changes that previous implementation of SimplifyCFG would do. * test/CodeGen/ARM/avoid-cpsr-rmw.ll - in this test I disabled common code sinking by a command line flag. llvm-svn: 321236
This commit is contained in:
parent
5c73c49c9f
commit
ad371e0caa
|
@ -1654,14 +1654,11 @@ namespace {
|
||||||
|
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
/// Given an unconditional branch that goes to BBEnd,
|
/// Check whether BB's predecessors end with unconditional branches. If it is
|
||||||
/// check whether BBEnd has only two predecessors and the other predecessor
|
/// true, sink any common code from the predecessors to BB.
|
||||||
/// ends with an unconditional branch. If it is true, sink any common code
|
/// We also allow one predecessor to end with conditional branch (but no more
|
||||||
/// in the two predecessors to BBEnd.
|
/// than one).
|
||||||
static bool SinkThenElseCodeToEnd(BranchInst *BI1) {
|
static bool SinkCommonCodeFromPredecessors(BasicBlock *BB) {
|
||||||
assert(BI1->isUnconditional());
|
|
||||||
BasicBlock *BBEnd = BI1->getSuccessor(0);
|
|
||||||
|
|
||||||
// We support two situations:
|
// We support two situations:
|
||||||
// (1) all incoming arcs are unconditional
|
// (1) all incoming arcs are unconditional
|
||||||
// (2) one incoming arc is conditional
|
// (2) one incoming arc is conditional
|
||||||
|
@ -1705,7 +1702,7 @@ static bool SinkThenElseCodeToEnd(BranchInst *BI1) {
|
||||||
//
|
//
|
||||||
SmallVector<BasicBlock*,4> UnconditionalPreds;
|
SmallVector<BasicBlock*,4> UnconditionalPreds;
|
||||||
Instruction *Cond = nullptr;
|
Instruction *Cond = nullptr;
|
||||||
for (auto *B : predecessors(BBEnd)) {
|
for (auto *B : predecessors(BB)) {
|
||||||
auto *T = B->getTerminator();
|
auto *T = B->getTerminator();
|
||||||
if (isa<BranchInst>(T) && cast<BranchInst>(T)->isUnconditional())
|
if (isa<BranchInst>(T) && cast<BranchInst>(T)->isUnconditional())
|
||||||
UnconditionalPreds.push_back(B);
|
UnconditionalPreds.push_back(B);
|
||||||
|
@ -1773,8 +1770,7 @@ static bool SinkThenElseCodeToEnd(BranchInst *BI1) {
|
||||||
DEBUG(dbgs() << "SINK: Splitting edge\n");
|
DEBUG(dbgs() << "SINK: Splitting edge\n");
|
||||||
// We have a conditional edge and we're going to sink some instructions.
|
// We have a conditional edge and we're going to sink some instructions.
|
||||||
// Insert a new block postdominating all blocks we're going to sink from.
|
// Insert a new block postdominating all blocks we're going to sink from.
|
||||||
if (!SplitBlockPredecessors(BI1->getSuccessor(0), UnconditionalPreds,
|
if (!SplitBlockPredecessors(BB, UnconditionalPreds, ".sink.split"))
|
||||||
".sink.split"))
|
|
||||||
// Edges couldn't be split.
|
// Edges couldn't be split.
|
||||||
return false;
|
return false;
|
||||||
Changed = true;
|
Changed = true;
|
||||||
|
@ -5728,9 +5724,6 @@ bool SimplifyCFGOpt::SimplifyUncondBranch(BranchInst *BI,
|
||||||
BasicBlock *BB = BI->getParent();
|
BasicBlock *BB = BI->getParent();
|
||||||
BasicBlock *Succ = BI->getSuccessor(0);
|
BasicBlock *Succ = BI->getSuccessor(0);
|
||||||
|
|
||||||
if (SinkCommon && Options.SinkCommonInsts && SinkThenElseCodeToEnd(BI))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// If the Terminator is the only non-phi instruction, simplify the block.
|
// If the Terminator is the only non-phi instruction, simplify the block.
|
||||||
// If LoopHeader is provided, check if the block or its successor is a loop
|
// If LoopHeader is provided, check if the block or its successor is a loop
|
||||||
// header. (This is for early invocations before loop simplify and
|
// header. (This is for early invocations before loop simplify and
|
||||||
|
@ -6008,6 +6001,9 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) {
|
||||||
if (MergeBlockIntoPredecessor(BB))
|
if (MergeBlockIntoPredecessor(BB))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (SinkCommon && Options.SinkCommonInsts)
|
||||||
|
Changed |= SinkCommonCodeFromPredecessors(BB);
|
||||||
|
|
||||||
IRBuilder<> Builder(BB);
|
IRBuilder<> Builder(BB);
|
||||||
|
|
||||||
// If there is a trivial two-entry PHI node in this basic block, and we can
|
// If there is a trivial two-entry PHI node in this basic block, and we can
|
||||||
|
|
|
@ -6,22 +6,20 @@ define void @sum(i32 %a, i32* %to, i32 %c) {
|
||||||
entry:
|
entry:
|
||||||
switch i32 %a, label %exit [
|
switch i32 %a, label %exit [
|
||||||
i32 1, label %bb1
|
i32 1, label %bb1
|
||||||
i32 2, label %bb2
|
i32 2, label %exit.sink.split
|
||||||
i32 3, label %bb3
|
i32 3, label %bb3
|
||||||
i32 4, label %bb4
|
i32 4, label %bb4
|
||||||
]
|
]
|
||||||
bb1:
|
bb1:
|
||||||
%b = add i32 %c, 1
|
%b = add i32 %c, 1
|
||||||
store i32 %b, i32* %to
|
br label %exit.sink.split
|
||||||
br label %exit
|
|
||||||
bb2:
|
|
||||||
store i32 2, i32* %to
|
|
||||||
br label %exit
|
|
||||||
bb3:
|
bb3:
|
||||||
store i32 3, i32* %to
|
br label %exit.sink.split
|
||||||
br label %exit
|
|
||||||
bb4:
|
bb4:
|
||||||
store i32 5, i32* %to
|
br label %exit.sink.split
|
||||||
|
exit.sink.split:
|
||||||
|
%.sink = phi i32 [ 5, %bb4 ], [ %b, %bb1 ], [ 3, %bb3 ], [ %a, %entry ]
|
||||||
|
store i32 %.sink, i32* %to
|
||||||
br label %exit
|
br label %exit
|
||||||
exit:
|
exit:
|
||||||
ret void
|
ret void
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a9 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CORTEX
|
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a9 -simplifycfg-sink-common=false | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-CORTEX
|
||||||
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=swift | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SWIFT
|
; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=swift -simplifycfg-sink-common=false | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SWIFT
|
||||||
; Avoid some 's' 16-bit instruction which partially update CPSR (and add false
|
; Avoid some 's' 16-bit instruction which partially update CPSR (and add false
|
||||||
; dependency) when it isn't dependent on last CPSR defining instruction.
|
; dependency) when it isn't dependent on last CPSR defining instruction.
|
||||||
; rdar://8928208
|
; rdar://8928208
|
||||||
|
|
Loading…
Reference in New Issue