[llvm] [SimplifyCFG] Simplify switch instruction that has duplicate arms (PR #114262)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 31 20:14:17 PDT 2024
================
@@ -7436,6 +7437,140 @@ static bool simplifySwitchOfCmpIntrinsic(SwitchInst *SI, IRBuilderBase &Builder,
return true;
}
+namespace llvm {
+template <> struct DenseMapInfo<const SwitchInst::CaseHandle *> {
+ static const SwitchInst::CaseHandle *getEmptyKey() {
+ return reinterpret_cast<const SwitchInst::CaseHandle *>(
+ DenseMapInfo<void *>::getEmptyKey());
+ }
+ static const SwitchInst::CaseHandle *getTombstoneKey() {
+ return reinterpret_cast<const SwitchInst::CaseHandle *>(
+ DenseMapInfo<void *>::getTombstoneKey());
+ }
+ static unsigned getHashValue(const SwitchInst::CaseHandle *Case) {
+ BasicBlock *Succ = Case->getCaseSuccessor();
+ BranchInst *BI = cast<BranchInst>(Succ->getTerminator());
+
+ auto It = BI->successors();
+ return hash_combine(Succ->size(), hash_combine_range(It.begin(), It.end()));
+ }
+ static bool isEqual(const SwitchInst::CaseHandle *LHS,
+ const SwitchInst::CaseHandle *RHS) {
+
+ auto EKey = DenseMapInfo<const SwitchInst::CaseHandle *>::getEmptyKey();
+ auto TKey = DenseMapInfo<const SwitchInst::CaseHandle *>::getTombstoneKey();
+ if (LHS == EKey || RHS == EKey || LHS == TKey || RHS == TKey)
+ return LHS == RHS;
+
+ auto IsBranchEq = [](BranchInst *A, BranchInst *B) {
+ if (A->isConditional() != B->isConditional())
+ return false;
+
+ if (A->isConditional()) {
+ // If the conditions are instructions, check equality up to
+ // commutativity. Otherwise, check that the two Values are the same.
+ Value *AC = A->getCondition();
+ Value *BC = B->getCondition();
+ auto *ACI = dyn_cast<Instruction>(AC);
+ auto *BCI = dyn_cast<Instruction>(BC);
+
+ if (ACI && BCI && !areIdenticalUpToCommutativity(ACI, BCI))
+ return false;
+ if ((!ACI || !BCI) && AC != BC)
+ return false;
+ }
+
+ if (A->getNumSuccessors() != B->getNumSuccessors())
+ return false;
+
+ for (unsigned I = 0; I < A->getNumSuccessors(); ++I)
+ if (A->getSuccessor(I) != B->getSuccessor(I))
+ return false;
+
+ return true;
+ };
+
+ auto IsBBEq = [&IsBranchEq](BasicBlock *A, BasicBlock *B) {
+ // FIXME: we checked that the size of A and B are both 1 in
+ // simplifyDuplicateSwitchArms to make the Case list smaller to improve
+ // performance. If we decide to support BasicBlocks with more than just a
+ // single instruction, we need to check that A.size() == B.size() here.
+
+ if (!IsBranchEq(cast<BranchInst>(A->getTerminator()),
+ cast<BranchInst>(B->getTerminator())))
+ return false;
+
+ // Need to check that PHIs in sucessors have matching values
+ for (auto *Succ : cast<BranchInst>(A->getTerminator())->successors())
+ for (PHINode &Phi : Succ->phis())
+ if (Phi.getIncomingValueForBlock(A) !=
----------------
dtcxzyw wrote:
FYI `Phi.getIncomingValueForBlock` is `O(|Pred|)`.
https://github.com/llvm/llvm-project/pull/114262
More information about the llvm-commits
mailing list