[llvm] [NFC] SimplifyCFG: Detect switch replacement earlier in `switchToLookup` (PR #155602)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 28 06:02:17 PDT 2025
================
@@ -7022,9 +7031,76 @@ static bool switchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
return false;
}
+ // Compute the table index value.
+ Value *TableIndex;
+ if (UseSwitchConditionAsTableIndex) {
+ TableIndex = SI->getCondition();
+ if (HasDefaultResults) {
+ // Grow the table to cover all possible index values to avoid the range
+ // check. It will use the default result to fill in the table hole later,
+ // so make sure it exist.
+ ConstantRange CR =
+ computeConstantRange(TableIndex, /* ForSigned */ false);
+ // Grow the table shouldn't have any size impact by checking
+ // wouldFitInRegister.
+ // TODO: Consider growing the table also when it doesn't fit in a register
+ // if no optsize is specified.
+ const uint64_t UpperBound = CR.getUpper().getLimitedValue();
+ if (!CR.isUpperWrapped() && all_of(ResultTypes, [&](const auto &KV) {
+ return SwitchReplacement::wouldFitInRegister(
+ DL, UpperBound, KV.second /* ResultType */);
+ })) {
+ // There may be some case index larger than the UpperBound (unreachable
+ // case), so make sure the table size does not get smaller.
+ TableSize = std::max(UpperBound, TableSize);
+ // The default branch is unreachable after we enlarge the lookup table.
+ // Adjust DefaultIsReachable to reuse code path.
+ DefaultIsReachable = false;
+ }
+ }
+ }
+
if (!shouldBuildLookupTable(SI, TableSize, TTI, DL, ResultTypes))
return false;
+ Builder.SetInsertPoint(SI);
+ // TableIndex is the switch condition - TableIndexOffset if we don't
+ // use the condition directly
+ if (!UseSwitchConditionAsTableIndex) {
+ // If the default is unreachable, all case values are s>= MinCaseVal. Then
+ // we can try to attach nsw.
+ bool MayWrap = true;
+ if (!DefaultIsReachable) {
+ APInt Res =
+ MaxCaseVal->getValue().ssub_ov(MinCaseVal->getValue(), MayWrap);
+ (void)Res;
+ }
+ TableIndex = Builder.CreateSub(SI->getCondition(), TableIndexOffset,
+ "switch.tableidx", /*HasNUW =*/false,
+ /*HasNSW =*/!MayWrap);
+ }
+
+ // Keep track of the tables we create for each phi node
+ struct ReplacementParams {
+ SwitchReplacement Replacer;
+ Constant *DefaultVal;
+ };
+ // Keep track of the switch replacement for each phi
+ SmallDenseMap<PHINode *, ReplacementParams> PhiToReplacementMap;
+ for (PHINode *PHI : PHIs) {
+ const auto &ResultList = ResultLists[PHI];
+
+ Type *ResultType = ResultList.begin()->second->getType();
+ // Use any value to fill the lookup table holes.
+ Constant *DefaultVal =
+ AllHolesArePoison ? PoisonValue::get(ResultType) : DefaultResults[PHI];
+ StringRef FuncName = Fn->getName();
+ SwitchReplacement Replacement(*Fn->getParent(), TableSize, TableIndexOffset,
+ ResultList, DefaultVal, DL, FuncName);
----------------
nikic wrote:
Can we store DefaultVal in SwitchReplacement so we don't need this extra ReplacementParams struct?
https://github.com/llvm/llvm-project/pull/155602
More information about the llvm-commits
mailing list