Skip to content

Commit cdcb8d4

Browse files
committed
[Uniformity] Fixed control-div early stop
Control-divergence finds joins by propagating labels from the divergent control branch. The code that checks the early stop for propagation is not correct when a sequence of blocks that can be merged into a single block stay unmerged. This change fixes this issue by handling this sequence of blocks as they would be merged. Note that the existing early stop checking is not optimal. Idealy, the IPD should be the stop point, but this algorithm can go beyond IPD.
1 parent 03d3e6d commit cdcb8d4

File tree

1 file changed

+55
-4
lines changed

1 file changed

+55
-4
lines changed

llvm/include/llvm/ADT/GenericUniformityImpl.h

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,55 @@ template <typename ContextT> class DivergencePropagator {
604604
return true;
605605
}
606606

607+
// getRealSucc() gets all successors of \p SuccBlock that can be merged with it
608+
// and returns the last one of them (called it real succ of SuccBlock).
609+
// For example,
610+
//
611+
// div-b0
612+
// / \
613+
// b1 b2
614+
// | |
615+
// b3 b4
616+
// | /
617+
// b5 /
618+
// \ /
619+
// \ /
620+
// b6
621+
//
622+
// For \p SuccBlock = b1, {b1, b3, b5} can be merged together and this
623+
// function returns the last one b5; for \p SuccBlock = b2, {b2, b4} can
624+
// be merged and this function returns b4.
625+
//
626+
// This is necessary as the algorithm of propagating control-divergence
627+
// assumes that CFG has been optimized so that (b1,b3,b5) and (b2, b4)
628+
// are merged into a single block, respectively.
629+
const BlockT* getRealSucc(const BlockT& SuccBlock, const BlockT& Label) {
630+
const BlockT *LastBlock = &SuccBlock;
631+
if (pred_size(LastBlock) != 1)
632+
return LastBlock;
633+
634+
while (succ_size(LastBlock) == 1) {
635+
const BlockT* NextBlock = *succ_begin(LastBlock);
636+
637+
if (pred_size(NextBlock) != 1)
638+
break;
639+
640+
// NextBlock can be merged into LastBlock
641+
const auto *OldLabel = BlockLabels[LastBlock];
642+
assert(OldLabel == nullptr);
643+
644+
LLVM_DEBUG(dbgs() << "labeling (for non real succ) "
645+
<< Context.print(LastBlock) << ":\n"
646+
<< "\tpushed label: " << Context.print(&Label) << "\n"
647+
<< "\told label: " << Context.print(OldLabel) << "\n");
648+
649+
BlockLabels[LastBlock] = &Label;
650+
LastBlock = NextBlock;
651+
}
652+
653+
return LastBlock;
654+
}
655+
607656
std::unique_ptr<DivergenceDescriptorT> computeJoinPoints() {
608657
assert(DivDesc);
609658

@@ -626,8 +675,9 @@ template <typename ContextT> class DivergencePropagator {
626675
LLVM_DEBUG(dbgs() << "\tImmediate divergent cycle exit: "
627676
<< Context.print(SuccBlock) << "\n");
628677
}
629-
auto SuccIdx = CyclePOT.getIndex(SuccBlock);
630-
visitEdge(*SuccBlock, *SuccBlock);
678+
const auto* SuccBB = getRealSucc(*SuccBlock, *SuccBlock);
679+
auto SuccIdx = CyclePOT.getIndex(SuccBB);
680+
visitEdge(*SuccBB, *SuccBlock);
631681
FloorIdx = std::min<int>(FloorIdx, SuccIdx);
632682
}
633683

@@ -688,9 +738,10 @@ template <typename ContextT> class DivergencePropagator {
688738
}
689739
} else {
690740
for (const auto *SuccBlock : successors(Block)) {
691-
CausedJoin |= visitEdge(*SuccBlock, *Label);
741+
const auto* SuccBB = getRealSucc(*SuccBlock, *Label);
742+
CausedJoin |= visitEdge(*SuccBB, *Label);
692743
LoweredFloorIdx =
693-
std::min<int>(LoweredFloorIdx, CyclePOT.getIndex(SuccBlock));
744+
std::min<int>(LoweredFloorIdx, CyclePOT.getIndex(SuccBB));
694745
}
695746
}
696747

0 commit comments

Comments
 (0)