[llvm] [SimplifyCFG] Simplify switch instruction that has duplicate arms (PR #114262)

Michael Maitland via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 31 21:39:29 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) !=
----------------
michaelmaitland wrote:

It would probably be best to calculate this once for a given basic block. I’ll update the patch to calculate this ahead of time. Thanks for noting this. 

https://github.com/llvm/llvm-project/pull/114262


More information about the llvm-commits mailing list