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

Michael Maitland via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 14 09:56:05 PST 2024


================
@@ -7436,6 +7437,185 @@ static bool simplifySwitchOfCmpIntrinsic(SwitchInst *SI, IRBuilderBase &Builder,
   return true;
 }
 
+/// Checking whether two cases of SI are equal depends on the contents of the
+/// BasicBlock and the incoming values of their successor PHINodes.
+/// PHINode::getIncomingValueForBlock is O(|Preds|), so we'd like to avoid
+/// calling this function on each BasicBlock every time isEqual is called,
+/// especially since the same BasicBlock may be passed as an argument multiple
+/// times. To do this, we can precompute a map of PHINode -> Pred BasicBlock ->
+/// IncomingValue and add it in the Wrapper so isEqual can do O(1) checking
+/// of the incoming values.
+struct SwitchSuccWrapper {
+  // Keep so we can use SwitchInst::setSuccessor to do the replacement. It won't
+  // be important to equality though.
+  unsigned SuccNum;
+  BasicBlock *Dest;
+  DenseMap<PHINode *, DenseMap<BasicBlock *, Value *>> *PhiPredIVs;
----------------
michaelmaitland wrote:

I've updated to use a SmallDenseMap on the inner map. I think the inner map is important. In `isEqual`, we need to check that for two BasicBlock A and B, that the incoming values for each Phi are the same for the two BasicBlocks. That requires us to call `PHINode::getIncomingValueForBlock`, which is `O(|Preds|)`. If we do not precompute this inner map, then we call `PHINode::getIncomingValueForBlock` redundantly, since a single BasicBlock may be passed as argument to isEqual multiple times. I've noted this in the docstring of the data structure.

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


More information about the llvm-commits mailing list