summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyCFG.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp24
1 files changed, 13 insertions, 11 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index ec574eaa81d..90b552035af 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -5559,23 +5559,25 @@ static bool ReduceSwitchRange(SwitchInst *SI, IRBuilder<> &Builder,
// 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.
+ uint64_t GCD = 0;
+ for (auto &V : Values)
+ GCD = GreatestCommonDivisor64(GCD, (uint64_t)V);
- // This transform can be done speculatively because it is so cheap - it
- // results in a single rotate operation being inserted.
+ // This transform can be done speculatively because it is so cheap - it results
+ // in a single rotate operation being inserted. This can only happen if the
+ // factor extracted is a power of 2.
+ // FIXME: If the GCD is an odd number we can multiply by the multiplicative
+ // inverse of GCD and then perform this transform.
// FIXME: It's possible that optimizing a switch on powers of two might also
// be beneficial - flag values are often powers of two and we could use a CLZ
// as the key function.
+ if (GCD <= 1 || !isPowerOf2_64(GCD))
+ // No common divisor found or too expensive to compute key function.
+ return false;
- // 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;
+ unsigned Shift = Log2_64(GCD);
for (auto &V : Values)
- Shift = std::min(Shift, countTrailingZeros((uint64_t)V));
- assert(Shift < 64);
- if (Shift > 0)
- for (auto &V : Values)
- V = (int64_t)((uint64_t)V >> Shift);
+ V = (int64_t)((uint64_t)V >> Shift);
if (!isSwitchDense(Values))
// Transform didn't create a dense switch.
OpenPOWER on IntegriCloud