[llvm] [SimplifyCFG] Lay switch lookup tables out over the narrower of the signed and unsigned case range (PR #221489)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 12 08:07:00 PDT 2026
================
@@ -7570,6 +7577,38 @@ static bool simplifySwitchLookup(SwitchInst *SI, IRBuilder<> &Builder,
DefaultResults[PHI] = Result;
}
+ // A switch only compares its condition for equality, so the case values have
+ // no inherent signedness and the table can be laid out over whichever of the
+ // two ranges is narrower. The unsigned one wins whenever the condition has
+ // been narrowed to the smallest type holding all case values (InstCombine
+ // does this), because that wraps a contiguous unsigned range such as
+ // [0, 150) around into the sign-wrapped i8 range [-128, 127]. Note that a
+ // strictly narrower unsigned range implies a non-negative unsigned minimum:
+ // if every case value had the sign bit set, both orderings would agree.
+ APInt SignedRange = MaxCaseVal->getValue() - MinCaseVal->getValue();
+ APInt UnsignedRange =
+ UnsignedMaxCaseVal->getValue() - UnsignedMinCaseVal->getValue();
+ bool UseUnsignedRange = UnsignedRange.ult(SignedRange);
+ // The one thing the wider signed range can buy is a table spanning every
+ // value the condition can take, which then needs no range check. That only
+ // pays off if the default is reachable in the first place, and if its
+ // results can fill the table's holes: without them the holes are poison and
+ // the table needs a mask check anyway, which is no cheaper than the range
+ // check we would be avoiding.
+ if (UseUnsignedRange && SignedRange.isAllOnes() && HasDefaultResults &&
+ !SI->defaultDestUnreachable()) {
+ // Keep the signed range only if such a table would actually be built. The
+ // size below saturates for wide types, where it never is.
+ uint64_t CoveringTableSize =
+ SignedRange.getLimitedValue(UINT64_MAX - 1) + 1;
----------------
dtcxzyw wrote:
The existing transformation seems don't work for `[INT64_MIN, INT64_MAX]`. The table size is incorrectly calculated as 0. Is there a guard to bail out on this case?
https://github.com/llvm/llvm-project/pull/221489
More information about the llvm-commits
mailing list