[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