)]}'
{
  "commit": "58bf8a355a73b7fbc6d7bfebcc7281b3cdadd4da",
  "tree": "53ab46a9c6ba1ac1f1b621d4b5a51459d8b68ac2",
  "parents": [
    "531ee609ca37faa59dd11df4658902d2202c0b66"
  ],
  "author": {
    "name": "Dominic P",
    "email": "gcc@gcc.dp11.uk",
    "time": "Sat Aug 22 20:05:35 2026 -0600"
  },
  "committer": {
    "name": "Jeff Law",
    "email": "jeffrey.law@oss.qualcomm.com",
    "time": "Sat Aug 22 20:05:35 2026 -0600"
  },
  "message": "[PATCH 1/3] tree-optimization: hoist shifts by an in-range constant count\n\nmovement_possibility_1 restricts shifts and rotates to\nMOVE_PRESERVE_EXECUTION so that a count which is out of range is never\nspeculatively executed.  The test was inverted: wi::ltu_p (count,\nprecision) is true exactly when the count is in range and the shift is\nperfectly well defined, so it was the well-defined shifts that were\npinned, while a constant count \u003e\u003d precision - the undefined case the\ncomment describes - fell through as MOVE_POSSIBLE.\n\nThe restriction was added by r14-4786-gd118738e71cf46 (PR111000), whose\nconcern is a count that cannot be proven in range - there, hoisting can\nintroduce an undefined shift on a path that never executed it.  That\ncase is unaffected here: a non-INTEGER_CST count still takes the\nMOVE_PRESERVE_EXECUTION path through the first half of the disjunct, and\ngcc.dg/torture/pr111000.c still passes, and compiles to identical code\nbefore and after.\n\ncompute_invariantness skips a MOVE_PRESERVE_EXECUTION statement whenever\nthe block may not execute, and outermost_invariant_loop then returns\nNULL for its result, so the entire invariant chain rooted at such a\nshift was pinned with it.  In the new testcase the multiply and the\ndivide then stay in the loop as well.\n\nHow much of this reaches the emitted code varies.  It is clearest where\nthe division survives as a libcall by a constant divisor: on\narm-none-eabi at -Os -mcpu\u003darm1176jzf-s the bl __aeabi_idiv sits inside\nthe loop body before this change and above the loop after it, and the\nregister save list shrinks from eight registers to six.  Where the\ndivision is expanded inline the RTL loop-invariant pass can recover the\nmotion on its own - at -O2 that same function is byte for byte identical\nbefore and after - and a non-constant divisor stays pinned either way as\npossibly trapping.  Hoisting earlier can also cost a little code size\nwhere it raises register pressure: a loop body with several such chains\nunder one guard grows on Thumb at -Os, because the hoisted values are\nlive across the loop.  The GIMPLE-level change is what the testcase\nchecks.\n\nThe series was bootstrapped on x86_64-pc-linux-gnu at trunk 7f549ea2b47\nwith the stage2/stage3 comparison successful, and a full make check shows\nno regressions: 227924 gcc and 278399 g++ expected passes, and every one\nof the 112 unexpected results also occurs with the series reverted.  With the\npatch reverted and the test kept, the lim2 dump moves\nno statements instead of three.\n\nAssisted-by: Claude Opus 5 (Anthropic)\n\n\tPR tree-optimization/111000\ngcc/ChangeLog:\n\n\t* tree-ssa-loop-im.cc (movement_possibility_1): Require\n\tMOVE_PRESERVE_EXECUTION for an out-of-range constant shift\n\tcount, not an in-range one.\n\ngcc/testsuite/ChangeLog:\n\n\t* gcc.dg/tree-ssa/loop-im-shift-1.c: New test.\n\nSigned-off-by: Dominic P \u003cgcc@gcc.dp11.uk\u003e\n",
  "tree_diff": [
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "129fa13bf0e66a4bcd65912c2c9fc06c2c8cc6c0",
      "new_mode": 33188,
      "new_path": "gcc/testsuite/gcc.dg/tree-ssa/loop-im-shift-1.c"
    },
    {
      "type": "modify",
      "old_id": "412645600093522036df2db2b472aea6ad75d1a8",
      "old_mode": 33188,
      "old_path": "gcc/tree-ssa-loop-im.cc",
      "new_id": "0dcf5982ec2d82c82d83fcce85cb5d15f36a5992",
      "new_mode": 33188,
      "new_path": "gcc/tree-ssa-loop-im.cc"
    }
  ]
}
