On Sat, 22 Aug 2026, Jeffrey Law wrote:

> 
> 
> On 8/15/2026 2:17 PM, Dominic P wrote:
> > movement_possibility_1 restricts shifts and rotates to
> > MOVE_PRESERVE_EXECUTION so that a count which is out of range is never
> > speculatively executed.  The test was inverted: wi::ltu_p (count,
> > precision) is true exactly when the count is in range and the shift is
> > perfectly well defined, so it was the well-defined shifts that were
> > pinned, while a constant count >= precision - the undefined case the
> > comment describes - fell through as MOVE_POSSIBLE.
> >
> > The restriction was added by r14-4786-gd118738e71cf46 (PR111000), whose
> > concern is a count that cannot be proven in range - there, hoisting can
> > introduce an undefined shift on a path that never executed it.  That
> > case is unaffected here: a non-INTEGER_CST count still takes the
> > MOVE_PRESERVE_EXECUTION path through the first half of the disjunct, and
> > gcc.dg/torture/pr111000.c still passes, and compiles to identical code
> > before and after.
> >
> > compute_invariantness skips a MOVE_PRESERVE_EXECUTION statement whenever
> > the block may not execute, and outermost_invariant_loop then returns
> > NULL for its result, so the entire invariant chain rooted at such a
> > shift was pinned with it.  In the new testcase the multiply and the
> > divide then stay in the loop as well.
> >
> > How much of this reaches the emitted code varies.  It is clearest where
> > the division survives as a libcall by a constant divisor: on
> > arm-none-eabi at -Os -mcpu=arm1176jzf-s the bl __aeabi_idiv sits inside
> > the loop body before this change and above the loop after it, and the
> > register save list shrinks from eight registers to six.  Where the
> > division is expanded inline the RTL loop-invariant pass can recover the
> > motion on its own - at -O2 that same function is byte for byte identical
> > before and after - and a non-constant divisor stays pinned either way as
> > possibly trapping.  Hoisting earlier can also cost a little code size
> > where it raises register pressure: a loop body with several such chains
> > under one guard grows on Thumb at -Os, because the hoisted values are
> > live across the loop.  The GIMPLE-level change is what the testcase
> > checks.
> >
> > The series was bootstrapped on x86_64-pc-linux-gnu at trunk 7f549ea2b47
> > with the stage2/stage3 comparison successful, and a full make check shows
> > no regressions: 227924 gcc and 278399 g++ expected passes, and every one
> > of the 112 unexpected results also occurs with the series reverted.  With
> > the patch reverted and the test kept, the lim2 dump moves
> > no statements instead of three.
> >
> > Assisted-by: Claude Opus 5 (Anthropic)
> >
> > gcc/ChangeLog:
> >
> >  PR tree-optimization/111000
> >  * tree-ssa-loop-im.cc (movement_possibility_1): Require
> >  MOVE_PRESERVE_EXECUTION for an out-of-range constant shift
> >  count, not an in-range one.
> >
> > gcc/testsuite/ChangeLog:
> >
> >  * gcc.dg/tree-ssa/loop-im-shift-1.c: New test.
> >
> > Signed-off-by: Dominic P <[email protected]>
> OK.   While I might normally feel the need to ask about precisely what the LLM
> was used for, in this case the patch is so trivial that I don't think it's
> necessary.  I'll push it to the trunk momentarily.

Oops.  This also means we mis-handle out-of-range constants, meaning
it qualifies for backporting.

> Note this could be refined further by querying ranger for the range when the
> shift count is variable.  I would expect ranger to be able to determine a
> useful range reasonably often.  Obviously that would be an independent
> followup.
> 
> Jeff
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to