[llvm] [SimplifyCFG] Improve reduceSwitchRange to avoid unnecessary subtractions (PR #198374)

Alexis Engelke via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 5 09:54:43 PDT 2026


================
@@ -7637,34 +7672,24 @@ static bool reduceSwitchRange(SwitchInst *SI, IRBuilder<> &Builder,
   llvm::sort(Values);
 
   // If the switch is already dense, there's nothing useful to do here.
-  if (isSwitchDense(Values, SI->getFunction()->hasOptSize()))
+  bool OptSize = SI->getFunction()->hasOptSize();
+  if (isSwitchDense(Values, OptSize))
     return false;
 
-  // First, transform the values such that they start at zero and ascend.
+  // Find a Base and corresponding Shift that results in a dense switch range.
+  // Values[0] is the local minimum.
   int64_t Base = Values[0];
-  for (auto &V : Values)
-    V -= (uint64_t)(Base);
-
-  // Now we have signed numbers that have been shifted so that, given enough
-  // precision, there are no negative values. Since the rest of the transform
-  // is bitwise only, we switch now to an unsigned representation.
-
-  // This transform can be done speculatively because it is so cheap - it
-  // results in a single rotate operation being inserted.
-
-  // countTrailingZeros(0) returns 64. As Values is guaranteed to have more than
-  // one element and LLVM disallows duplicate cases, Shift is guaranteed to be
-  // less than 64.
-  unsigned Shift = 64;
-  for (auto &V : Values)
-    Shift = std::min(Shift, (unsigned)llvm::countr_zero((uint64_t)V));
-  assert(Shift < 64);
-  if (Shift > 0)
-    for (auto &V : Values)
-      V = (int64_t)((uint64_t)V >> Shift);
-
-  if (!isSwitchDense(Values, SI->getFunction()->hasOptSize()))
-    // Transform didn't create a dense switch.
+  std::optional<unsigned> Shift;
+  // Prefer Base=0 when the case values are still dense after shifting out their
+  // common low zero bits without subtracting a base. This avoids creating an
+  // unnecessary `(condition - local_min)` expression.
+  if ((Shift = getDenseSwitchRangeReductionShift(Values, /*Base=*/0,
+                                                 /*OptSize=*/true)))
+    Base = 0;
+  else if (Base != 0)
+    Shift = getDenseSwitchRangeReductionShift(Values, Base, OptSize);
----------------
aengelke wrote:

Sounds good, but please add these considerations as a comment into the code.

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


More information about the llvm-commits mailing list