diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/SwitchLoweringUtils.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/SwitchLoweringUtils.cpp | 81 | 
1 files changed, 81 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/SwitchLoweringUtils.cpp b/contrib/llvm-project/llvm/lib/CodeGen/SwitchLoweringUtils.cpp index 7982d80353bd..8922fa589813 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/SwitchLoweringUtils.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/SwitchLoweringUtils.cpp @@ -494,3 +494,84 @@ void SwitchCG::sortAndRangeify(CaseClusterVector &Clusters) {    }    Clusters.resize(DstIndex);  } + +unsigned SwitchCG::SwitchLowering::caseClusterRank(const CaseCluster &CC, +                                                   CaseClusterIt First, +                                                   CaseClusterIt Last) { +  return std::count_if(First, Last + 1, [&](const CaseCluster &X) { +    if (X.Prob != CC.Prob) +      return X.Prob > CC.Prob; + +    // Ties are broken by comparing the case value. +    return X.Low->getValue().slt(CC.Low->getValue()); +  }); +} + +llvm::SwitchCG::SwitchLowering::SplitWorkItemInfo +SwitchCG::SwitchLowering::computeSplitWorkItemInfo( +    const SwitchWorkListItem &W) { +  CaseClusterIt LastLeft = W.FirstCluster; +  CaseClusterIt FirstRight = W.LastCluster; +  auto LeftProb = LastLeft->Prob + W.DefaultProb / 2; +  auto RightProb = FirstRight->Prob + W.DefaultProb / 2; + +  // Move LastLeft and FirstRight towards each other from opposite directions to +  // find a partitioning of the clusters which balances the probability on both +  // sides. If LeftProb and RightProb are equal, alternate which side is +  // taken to ensure 0-probability nodes are distributed evenly. +  unsigned I = 0; +  while (LastLeft + 1 < FirstRight) { +    if (LeftProb < RightProb || (LeftProb == RightProb && (I & 1))) +      LeftProb += (++LastLeft)->Prob; +    else +      RightProb += (--FirstRight)->Prob; +    I++; +  } + +  while (true) { +    // Our binary search tree differs from a typical BST in that ours can have +    // up to three values in each leaf. The pivot selection above doesn't take +    // that into account, which means the tree might require more nodes and be +    // less efficient. We compensate for this here. + +    unsigned NumLeft = LastLeft - W.FirstCluster + 1; +    unsigned NumRight = W.LastCluster - FirstRight + 1; + +    if (std::min(NumLeft, NumRight) < 3 && std::max(NumLeft, NumRight) > 3) { +      // If one side has less than 3 clusters, and the other has more than 3, +      // consider taking a cluster from the other side. + +      if (NumLeft < NumRight) { +        // Consider moving the first cluster on the right to the left side. +        CaseCluster &CC = *FirstRight; +        unsigned RightSideRank = caseClusterRank(CC, FirstRight, W.LastCluster); +        unsigned LeftSideRank = caseClusterRank(CC, W.FirstCluster, LastLeft); +        if (LeftSideRank <= RightSideRank) { +          // Moving the cluster to the left does not demote it. +          ++LastLeft; +          ++FirstRight; +          continue; +        } +      } else { +        assert(NumRight < NumLeft); +        // Consider moving the last element on the left to the right side. +        CaseCluster &CC = *LastLeft; +        unsigned LeftSideRank = caseClusterRank(CC, W.FirstCluster, LastLeft); +        unsigned RightSideRank = caseClusterRank(CC, FirstRight, W.LastCluster); +        if (RightSideRank <= LeftSideRank) { +          // Moving the cluster to the right does not demot it. +          --LastLeft; +          --FirstRight; +          continue; +        } +      } +    } +    break; +  } + +  assert(LastLeft + 1 == FirstRight); +  assert(LastLeft >= W.FirstCluster); +  assert(FirstRight <= W.LastCluster); + +  return SplitWorkItemInfo{LastLeft, FirstRight, LeftProb, RightProb}; +}
\ No newline at end of file  | 
