Skip to content

Commit 085b048

Browse files
fixup! use get/set Sucessor
1 parent be55920 commit 085b048

File tree

2 files changed

+45
-41
lines changed

2 files changed

+45
-41
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7437,31 +7437,34 @@ static bool simplifySwitchOfCmpIntrinsic(SwitchInst *SI, IRBuilderBase &Builder,
74377437
return true;
74387438
}
74397439

7440-
/// Checking whether two CaseHandle.getCaseSuccessor() are equal depends on
7441-
/// the BasicBlock and the incoming values of their successor PHINodes.
7440+
/// Checking whether two cases of SI are equal depends on the contents of the
7441+
/// BasicBlock and the incoming values of their successor PHINodes.
74427442
/// PHINode::getIncomingValueForBlock is O(|Preds|), so we'd like to avoid
74437443
/// calling this function on each BasicBlock every time isEqual is called,
74447444
/// especially since the same BasicBlock may be passed as an argument multiple
74457445
/// times. To do this, we can precompute a map of PHINode -> Pred BasicBlock ->
74467446
/// IncomingValue and add it in the Wrapper so isEqual can do O(1) checking
74477447
/// of the incoming values.
7448-
struct CaseHandleWrapper {
7449-
const SwitchInst::CaseHandle Case;
7448+
struct SwitchSuccWrapper {
7449+
// Keep so we can use SwitchInst::setSuccessor to do the replacement. It won't
7450+
// be important to equality though.
7451+
unsigned SuccNum;
7452+
BasicBlock *Dest;
74507453
DenseMap<PHINode *, DenseMap<BasicBlock *, Value *>> *PhiPredIVs;
74517454
};
74527455

74537456
namespace llvm {
7454-
template <> struct DenseMapInfo<const CaseHandleWrapper *> {
7455-
static const CaseHandleWrapper *getEmptyKey() {
7456-
return static_cast<CaseHandleWrapper *>(
7457+
template <> struct DenseMapInfo<const SwitchSuccWrapper *> {
7458+
static const SwitchSuccWrapper *getEmptyKey() {
7459+
return static_cast<SwitchSuccWrapper *>(
74577460
DenseMapInfo<void *>::getEmptyKey());
74587461
}
7459-
static const CaseHandleWrapper *getTombstoneKey() {
7460-
return static_cast<CaseHandleWrapper *>(
7462+
static const SwitchSuccWrapper *getTombstoneKey() {
7463+
return static_cast<SwitchSuccWrapper *>(
74617464
DenseMapInfo<void *>::getTombstoneKey());
74627465
}
7463-
static unsigned getHashValue(const CaseHandleWrapper *CHW) {
7464-
BasicBlock *Succ = CHW->Case.getCaseSuccessor();
7466+
static unsigned getHashValue(const SwitchSuccWrapper *SSW) {
7467+
BasicBlock *Succ = SSW->Dest;
74657468
BranchInst *BI = cast<BranchInst>(Succ->getTerminator());
74667469
assert(BI->isUnconditional() &&
74677470
"Only supporting unconditional branches for now");
@@ -7475,26 +7478,26 @@ template <> struct DenseMapInfo<const CaseHandleWrapper *> {
74757478
// this had poor performance. We find that the extra computation of getting
74767479
// the incoming PHI values here leads to better performance on overall Set
74777480
// performance. We also tried to build a map from BB -> Succs.IncomingValues
7478-
// ahead of time and passing it in CaseHandleWrapper, but this slowed down
7481+
// ahead of time and passing it in SwitchSuccWrapper, but this slowed down
74797482
// the average compile time without having any impact on the worst case
74807483
// compile time.
74817484
BasicBlock *BB = BI->getSuccessor(0);
74827485
SmallVector<Value *> PhiValsForBB;
74837486
for (PHINode &Phi : BB->phis())
7484-
PhiValsForBB.emplace_back((*CHW->PhiPredIVs)[&Phi][BB]);
7487+
PhiValsForBB.emplace_back((*SSW->PhiPredIVs)[&Phi][BB]);
74857488

74867489
return hash_combine(
74877490
BB, hash_combine_range(PhiValsForBB.begin(), PhiValsForBB.end()));
74887491
}
7489-
static bool isEqual(const CaseHandleWrapper *LHS,
7490-
const CaseHandleWrapper *RHS) {
7491-
auto EKey = DenseMapInfo<CaseHandleWrapper *>::getEmptyKey();
7492-
auto TKey = DenseMapInfo<CaseHandleWrapper *>::getTombstoneKey();
7492+
static bool isEqual(const SwitchSuccWrapper *LHS,
7493+
const SwitchSuccWrapper *RHS) {
7494+
auto EKey = DenseMapInfo<SwitchSuccWrapper *>::getEmptyKey();
7495+
auto TKey = DenseMapInfo<SwitchSuccWrapper *>::getTombstoneKey();
74937496
if (LHS == EKey || RHS == EKey || LHS == TKey || RHS == TKey)
74947497
return LHS == RHS;
74957498

7496-
BasicBlock *A = LHS->Case.getCaseSuccessor();
7497-
BasicBlock *B = RHS->Case.getCaseSuccessor();
7499+
BasicBlock *A = LHS->Dest;
7500+
BasicBlock *B = RHS->Dest;
74987501

74997502
// FIXME: we checked that the size of A and B are both 1 in
75007503
// simplifyDuplicateSwitchArms to make the Case list smaller to
@@ -7535,10 +7538,11 @@ bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
75357538
SmallPtrSet<PHINode *, 8> Phis;
75367539
SmallPtrSet<BasicBlock *, 8> Seen;
75377540
DenseMap<PHINode *, DenseMap<BasicBlock *, Value *>> PhiPredIVs;
7538-
SmallVector<CaseHandleWrapper> Cases;
7541+
SmallVector<SwitchSuccWrapper> Cases;
75397542
Cases.reserve(SI->getNumCases());
7540-
for (auto &Case : SI->cases()) {
7541-
BasicBlock *BB = Case.getCaseSuccessor();
7543+
7544+
for (unsigned I = 0; I < SI->getNumSuccessors(); ++I) {
7545+
BasicBlock *BB = SI->getSuccessor(I);
75427546

75437547
// FIXME: Support more than just a single BranchInst. One way we could do
75447548
// this is by taking a hashing approach of all insts in BB.
@@ -7567,11 +7571,11 @@ bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
75677571
for (PHINode &Phi : Succ->phis())
75687572
Phis.insert(&Phi);
75697573
}
7570-
Cases.emplace_back(CaseHandleWrapper{Case, &PhiPredIVs});
7574+
Cases.emplace_back(SwitchSuccWrapper{I, BB, &PhiPredIVs});
75717575
}
75727576

75737577
// Precompute a data structure to improve performance of isEqual for
7574-
// CaseHandleWrapper.
7578+
// SwitchSuccWrapper.
75757579
PhiPredIVs.reserve(Phis.size());
75767580
for (PHINode *Phi : Phis) {
75777581
PhiPredIVs[Phi] =
@@ -7580,36 +7584,36 @@ bool SimplifyCFGOpt::simplifyDuplicateSwitchArms(SwitchInst *SI,
75807584
PhiPredIVs[Phi].insert({Phi->getIncomingBlock(IV), IV.get()});
75817585
}
75827586

7583-
// Build a set such that if the CaseHandleWrapper exists in the set and
7584-
// another CaseHandleWrapper isEqual, then the equivalent CaseHandleWrapper
7587+
// Build a set such that if the SwitchSuccWrapper exists in the set and
7588+
// another SwitchSuccWrapper isEqual, then the equivalent SwitchSuccWrapper
75857589
// which is not in the set should be replaced with the one in the set. If the
7586-
// CaseHandleWrapper is not in the set, then it should be added to the set so
7587-
// other CaseHandleWrappers can check against it in the same manner. We chose
7588-
// to use CaseHandleWrapper instead of BasicBlock since we'd need an extra
7589-
// nested loop since there is no O(1) lookup of BasicBlock -> Cases in
7590-
// SwichInst.
7591-
DenseSet<const CaseHandleWrapper *, DenseMapInfo<const CaseHandleWrapper *>>
7590+
// SwitchSuccWrapper is not in the set, then it should be added to the set so
7591+
// other SwitchSuccWrappers can check against it in the same manner. We use
7592+
// SwitchSuccWrapper instead of just BasicBlock because we'd like to pass
7593+
// around information to isEquality, getHashValue, and when doing the
7594+
// replacement with better performance.
7595+
DenseSet<const SwitchSuccWrapper *, DenseMapInfo<const SwitchSuccWrapper *>>
75927596
ReplaceWith;
75937597
ReplaceWith.reserve(Cases.size());
75947598

7595-
bool MadeChange = false;
75967599
SmallVector<DominatorTree::UpdateType> Updates;
75977600
Updates.reserve(ReplaceWith.size());
7598-
for (auto &CHW : Cases) {
7599-
// CHW is a candidate for simplification. If we find a duplicate BB,
7601+
bool MadeChange = false;
7602+
for (auto &SSW : Cases) {
7603+
// SSW is a candidate for simplification. If we find a duplicate BB,
76007604
// replace it.
7601-
const auto [It, Inserted] = ReplaceWith.insert(&CHW);
7605+
const auto [It, Inserted] = ReplaceWith.insert(&SSW);
76027606
if (!Inserted) {
76037607
// We know that SI's parent BB no longer dominates the old case successor
76047608
// since we are making it dead.
7605-
Updates.push_back({DominatorTree::Delete, SI->getParent(),
7606-
CHW.Case.getCaseSuccessor()});
7607-
CHW.Case.setSuccessor((*It)->Case.getCaseSuccessor());
7609+
Updates.push_back({DominatorTree::Delete, SI->getParent(), SSW.Dest});
7610+
SI->setSuccessor(SSW.SuccNum, (*It)->Dest);
76087611
MadeChange = true;
76097612
} else {
7610-
ReplaceWith.insert(&CHW);
7613+
ReplaceWith.insert(&SSW);
76117614
}
76127615
}
7616+
76137617
if (DTU)
76147618
DTU->applyUpdates(Updates);
76157619

llvm/test/Transforms/PhaseOrdering/switch-sext.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ define i8 @test_switch_with_sext_phi(i8 %code) {
66
; CHECK-SAME: i8 [[CODE:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
77
; CHECK-NEXT: entry:
88
; CHECK-NEXT: switch i8 [[CODE]], label [[SW_EPILOG:%.*]] [
9-
; CHECK-NEXT: i8 76, label [[SW_BB3:%.*]]
109
; CHECK-NEXT: i8 108, label [[SW_BB2:%.*]]
10+
; CHECK-NEXT: i8 76, label [[SW_BB3:%.*]]
1111
; CHECK-NEXT: ]
1212
; CHECK: sw.bb2:
1313
; CHECK-NEXT: br label [[SW_EPILOG]]

0 commit comments

Comments
 (0)