Hoist shifts by in-range constants out of loops
Improves loop optimization by hoisting shifts with constant counts that are provably in range.
This commit corrects a bug in loop optimization where shifts with constant counts were incorrectly restricted from being hoisted out of loops. The movement_possibility_1 logic mistakenly pinned shifts with in-range counts, while shifts with out-of-range counts were incorrectly marked as movable. The fix inverts this logic, allowing shifts with constant counts that are proven to be in range to be hoisted. This can lead to performance improvements by reducing redundant computations within loop bodies, as demonstrated by reductions in loop-invariant code and register pressure on ARM targets.
In Details
The movement_possibility_1 logic in GCC's loop invariant code motion pass was inverted regarding shifts and rotates. It used wi::ltu_p(count, precision) to check if the shift count was within the valid range. The original code restricted shifts when count < precision (i.e., in-range) to MOVE_PRESERVE_EXECUTION, while out-of-range shifts (count >= precision) were incorrectly marked MOVE_POSSIBLE. This was due to a misunderstanding of the PR111000 fix which aimed to prevent hoisting of *undefined* shifts (out-of-range counts). This commit corrects the condition: shifts with in-ran…
- loop optimization
- Compiler techniques to improve the performance of code within loops, such as reducing redundant computations or reordering operations.
- hoisting
- Moving a computation from inside a loop to outside the loop, if the result of the computation is the same on every iteration.
- shift operation
- A bitwise operation that shifts the bits of a number to the left or right.
- constant count
- In a shift operation, the number of positions to shift is a fixed value known at compile time.
- loop invariant code motion
- An optimization that moves computations that produce the same result in every loop iteration from inside the loop to outside.
- libcall
- A call to a function in a shared or static library, often used when the compiler cannot generate inline code for an operation.
- register pressure
- A measure of how many registers are needed by the program at a given point; high register pressure can lead to performance degradation as the compiler must spill values to memory.