MachineBasicBlock *selectBestCandidateBlock(
BlockChain &Chain, SmallVectorImpl<MachineBasicBlock *> &WorkList,
const BlockFilterSet *BlockFilter);
- MachineBasicBlock *getFirstUnplacedBlock(const BlockChain &PlacedChain,
- ArrayRef<MachineBasicBlock *> Blocks,
- unsigned &PrevUnplacedBlockIdx);
+ MachineBasicBlock *getFirstUnplacedBlock(
+ MachineFunction &F,
+ const BlockChain &PlacedChain,
+ MachineFunction::iterator &PrevUnplacedBlockIt,
+ const BlockFilterSet *BlockFilter);
void buildChain(MachineBasicBlock *BB, BlockChain &Chain,
- ArrayRef<MachineBasicBlock *> Blocks,
SmallVectorImpl<MachineBasicBlock *> &BlockWorkList,
const BlockFilterSet *BlockFilter = 0);
void buildLoopChains(MachineFunction &F, MachineLoop &L);
///
/// This routine is called when we are unable to use the CFG to walk through
/// all of the basic blocks and form a chain due to unnatural loops in the CFG.
-/// We walk through the sequence of blocks, starting from the
-/// LastUnplacedBlockIdx. We update this index to avoid re-scanning the entire
-/// sequence on repeated calls to this routine.
+/// We walk through the function's blocks in order, starting from the
+/// LastUnplacedBlockIt. We update this iterator on each call to avoid
+/// re-scanning the entire sequence on repeated calls to this routine.
MachineBasicBlock *MachineBlockPlacement::getFirstUnplacedBlock(
- const BlockChain &PlacedChain,
- ArrayRef<MachineBasicBlock *> Blocks,
- unsigned &PrevUnplacedBlockIdx) {
- for (unsigned i = PrevUnplacedBlockIdx, e = Blocks.size(); i != e; ++i) {
- MachineBasicBlock *BB = Blocks[i];
- if (BlockToChain[BB] != &PlacedChain) {
- PrevUnplacedBlockIdx = i;
- return BB;
+ MachineFunction &F, const BlockChain &PlacedChain,
+ MachineFunction::iterator &PrevUnplacedBlockIt,
+ const BlockFilterSet *BlockFilter) {
+ for (MachineFunction::iterator I = PrevUnplacedBlockIt, E = F.end(); I != E;
+ ++I) {
+ if (BlockFilter && !BlockFilter->count(I))
+ continue;
+ if (BlockToChain[I] != &PlacedChain) {
+ PrevUnplacedBlockIt = I;
+ return I;
}
}
return 0;
void MachineBlockPlacement::buildChain(
MachineBasicBlock *BB,
BlockChain &Chain,
- ArrayRef<MachineBasicBlock *> Blocks,
SmallVectorImpl<MachineBasicBlock *> &BlockWorkList,
const BlockFilterSet *BlockFilter) {
assert(BB);
assert(BlockToChain[BB] == &Chain);
assert(*Chain.begin() == BB);
SmallVector<MachineOperand, 4> Cond; // For AnalyzeBranch.
- unsigned PrevUnplacedBlockIdx = 0;
+ MachineFunction &F = *BB->getParent();
+ MachineFunction::iterator PrevUnplacedBlockIt = F.begin();
MachineBasicBlock *LoopHeaderBB = BB;
markChainSuccessors(Chain, LoopHeaderBB, BlockWorkList, BlockFilter);
BestSucc = selectBestCandidateBlock(Chain, BlockWorkList, BlockFilter);
if (!BestSucc) {
- BestSucc = getFirstUnplacedBlock(Chain, Blocks, PrevUnplacedBlockIdx);
+ BestSucc = getFirstUnplacedBlock(F, Chain, PrevUnplacedBlockIt,
+ BlockFilter);
if (!BestSucc)
break;
BlockWorkList.push_back(*BI);
}
- buildChain(*L.block_begin(), LoopChain, L.getBlocks(), BlockWorkList,
- &LoopBlockSet);
+ buildChain(*L.block_begin(), LoopChain, BlockWorkList, &LoopBlockSet);
DEBUG({
// Crash at the end so we get all of the debugging output first.
++LI)
buildLoopChains(F, **LI);
- // We need a vector of blocks so that buildChain can handle unnatural CFG
- // constructs by searching for unplaced blocks and just concatenating them.
- SmallVector<MachineBasicBlock *, 16> Blocks;
- Blocks.reserve(F.size());
-
SmallVector<MachineBasicBlock *, 16> BlockWorkList;
SmallPtrSet<BlockChain *, 4> UpdatedPreds;
for (MachineFunction::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
MachineBasicBlock *BB = &*FI;
- Blocks.push_back(BB);
BlockChain &Chain = *BlockToChain[BB];
if (!UpdatedPreds.insert(&Chain))
continue;
}
BlockChain &FunctionChain = *BlockToChain[&F.front()];
- buildChain(&F.front(), FunctionChain, Blocks, BlockWorkList);
+ buildChain(&F.front(), FunctionChain, BlockWorkList);
typedef SmallPtrSet<MachineBasicBlock *, 16> FunctionBlockSetType;
DEBUG({
; CHECK: unnatural_cfg1
; CHECK: %entry
; CHECK: %loop.body1
-; CHECK: %loop.body3
; CHECK: %loop.body2
+; CHECK: %loop.body3
entry:
br label %loop.header
br label %loop.body3
}
+define void @unnatural_cfg2() {
+; Test that we can handle a loop with a nested natural loop *and* an unnatural
+; loop. This was reduced from a crash on block placement when run over
+; single-source GCC.
+; CHECK: unnatural_cfg2
+; CHECK: %entry
+; CHECK: %loop.header
+; CHECK: %loop.body1
+; CHECK: %loop.body2
+; CHECK: %loop.body3
+; CHECK: %loop.inner1.begin
+; The end block is folded with %loop.body3...
+; CHECK-NOT: %loop.inner1.end
+; CHECK: %loop.body4
+; CHECK: %loop.inner2.begin
+; The loop.inner2.end block is folded
+; CHECK: %bail
+
+entry:
+ br label %loop.header
+
+loop.header:
+ %comp0 = icmp eq i32* undef, null
+ br i1 %comp0, label %bail, label %loop.body1
+
+loop.body1:
+ %val0 = load i32** undef, align 4
+ br i1 undef, label %loop.body2, label %loop.inner1.begin
+
+loop.body2:
+ br i1 undef, label %loop.body4, label %loop.body3
+
+loop.body3:
+ %ptr1 = getelementptr inbounds i32* %val0, i32 0
+ %castptr1 = bitcast i32* %ptr1 to i32**
+ %val1 = load i32** %castptr1, align 4
+ br label %loop.inner1.begin
+
+loop.inner1.begin:
+ %valphi = phi i32* [ %val2, %loop.inner1.end ], [ %val1, %loop.body3 ], [ %val0, %loop.body1 ]
+ %castval = bitcast i32* %valphi to i32*
+ %comp1 = icmp eq i32 undef, 48
+ br i1 %comp1, label %loop.inner1.end, label %loop.body4
+
+loop.inner1.end:
+ %ptr2 = getelementptr inbounds i32* %valphi, i32 0
+ %castptr2 = bitcast i32* %ptr2 to i32**
+ %val2 = load i32** %castptr2, align 4
+ br label %loop.inner1.begin
+
+loop.body4.dead:
+ br label %loop.body4
+
+loop.body4:
+ %comp2 = icmp ult i32 undef, 3
+ br i1 %comp2, label %loop.inner2.begin, label %loop.end
+
+loop.inner2.begin:
+ br i1 false, label %loop.end, label %loop.inner2.end
+
+loop.inner2.end:
+ %comp3 = icmp eq i32 undef, 1769472
+ br i1 %comp3, label %loop.end, label %loop.inner2.begin
+
+loop.end:
+ br label %loop.header
+
+bail:
+ unreachable
+}
+
define i32 @problematic_switch() {
; This function's CFG caused overlow in the machine branch probability
; calculation, triggering asserts. Make sure we don't crash on it.