[clang] [llvm] [LV] Support generating masks for switch terminators. (PR #99808)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 24 09:14:11 PDT 2024


================
@@ -7763,6 +7763,41 @@ VPValue *VPRecipeBuilder::createEdgeMask(BasicBlock *Src, BasicBlock *Dst) {
 
   VPValue *SrcMask = getBlockInMask(Src);
 
+  if (auto *SI = dyn_cast<SwitchInst>(Src->getTerminator())) {
+    // Create mask where the terminator in Src is a switch. We need to handle 2
+    // separate cases:
+    // 1. Dst is not the default desintation. Dst is reached if any of the cases
+    // with destination == Dst are taken. Join the conditions for each case
+    // where destination == Dst using a logical OR.
+    // 2. Dst is the default destination. Dst is reached if none of the cases
+    // with destination != Dst are taken. Join the conditions for each case
+    // where the destination is != Dst using a logical OR and negate it.
+    VPValue *Mask = nullptr;
+    VPValue *Cond = getVPValueOrAddLiveIn(SI->getCondition(), Plan);
+    bool IsDefault = SI->getDefaultDest() == Dst;
----------------
ayalz wrote:

This is fine. Worth considering the alternative of computing the default case by recursively computing (and recording, or retrieving) the masks of all other edges from Src to its successors, excluding default. Note that there may be no such other edges, in which case the desired edge mask is that of Src (worth a test).
When computing the non-default case, all relevant edges need to be computed - the cache was checked at the beginning.

```suggestion
    if (SI->getDefaultDest() == Dst) {
      VPValue *AllOtherEdgesMask = nullptr;
      SmallPtrSet<BasicBlock *, 4> UniqueSuccessors(succ_begin(Src), succ_end(Src));
      for (auto *Successor : UniqueSuccessors) {
        if (Succssor == Dst)
          continue;
        VPValue *OtherEdgeMask = createEdgeMask(Src, Successor);
        if (AllOtherEdgesMask)
          AllOtherEdgesMask = Builder.createLogicalOr(AllOtherEdgesMask, OtherEdgeMask);
        else
          AllOtherEdgesMask = OtherEdgeMask;
      }
      if (!AllOtherEdgesMask) {
        assert(UniqueSuccessors.size() == 1 && "Src expected to have only default successor");
        return EdgeMaskCache[Edge] = SrcMask;
      }
      return EdgeMaskCache[Edge] = Builder.createNot(AllOtherEdgesMask);
    }
    VPValue *EdgeMask = nullptr;
    VPValue *Cond = getVPValueOrAddLiveIn(SI->getCondition(), Plan);
    for (auto &C : SI->cases()) {
      if (C.getCaseSuccessor() != Dst)
        continue;
      // Edge for case C is not in EdgeMaskCache, create it.
      VPValue *V = getVPValueOrAddLiveIn(C.getCaseValue(), Plan);
      VPValue *CMask = Builder.createICmp(CmpInst::ICMP_EQ, Cond, V);
      if (EdgeMask)
        EdgeMask = Builder.createLogicalOr(EdgeMask, CMask);
      else
        EdgeMask = CMask;
    }
    assert(EdgeMask && "mask must be created");
    return EdgeMaskCache[Edge] = EdgeMask;
  }
```

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


More information about the llvm-commits mailing list