On Mon, Oct 26, 2026 at 1:58 PM Yongqiang Tian <[email protected]> wrote: > > Thanks for the review. I do not have GCC commit access. Could you > please push it for me?
Done. Richard. > Thanks a lot. > Yongqiang > > On Sat, 24 Oct 2026 at 23:06, Richard Biener <[email protected]> > wrote: > > > > On Thu, Oct 22, 2026 at 2:23 AM Yongqiang Tian <[email protected]> wrote: > > > > > > CRC verification treats every outside-loop use of an in-loop definition as > > > an observable use. This includes debug binds, so adding debug information > > > can prevent an otherwise valid CRC loop from being recognized and > > > replaced. > > > > > > Ignore debug statements when checking for outside-loop uses. Ignoring > > > them > > > alone is not sufficient, however: after the loop is replaced, an > > > outside-loop > > > debug bind may still refer to an SSA value whose original final-iteration > > > value no longer exists. Such a bind can make the debugger display an > > > incorrect value. > > > > > > Before replacing the loop, reset outside-loop debug binds that use values > > > defined inside it. The vectorizer already performs the same reset before > > > peeling a loop, so factor that walk into reset_debug_uses_outside_loop > > > and use > > > the common helper from both transformations. Keep debug binds inside the > > > loop > > > unchanged because the transformed loop body still executes once and those > > > binds may remain valid. > > > > > > Add a regression test that verifies both CRC recognition and that the > > > unrecoverable outside-loop value is marked unavailable. > > > > > > Bootstrapped and regression tested on x86_64-pc-linux-gnu. The GCC, G++ > > > and > > > libstdc++ testsuites showed no patch-induced regressions. The new test > > > and > > > the existing gcc.dg CRC tests pass. > > > > This is OK. > > > > Thanks, > > Richard. > > > > > Assisted-by: OpenAI Codex 5.6 Sol, co-reviewed by Claude and Yongqiang > > > Tian. > > > > > > PR tree-optimization/127716 > > > > > > gcc/ChangeLog: > > > > > > * crc-verification.cc > > > (crc_symbolic_execution::is_used_outside_the_loop): Ignore debug > > > statements when checking for outside-loop uses. > > > * gimple-crc-optimization.cc > > > (crc_optimization::optimize_crc_loop): Reset outside-loop debug > > > binds > > > before replacing the loop. > > > * tree-ssa-loop-manip.cc (reset_debug_uses_outside_loop): New > > > function, > > > factored from vect_do_peeling. > > > * tree-ssa-loop-manip.h (reset_debug_uses_outside_loop): Declare. > > > * tree-vect-loop-manip.cc (vect_do_peeling): Use it. > > > > > > gcc/testsuite/ChangeLog: > > > > > > * gcc.dg/pr127716.c: New test. > > > > > > Suggested-by: Richard Biener <[email protected]> > > > Signed-off-by: Yongqiang Tian <[email protected]> > > > --- > > > Thanks for the suggestion. This version factors the existing vectorizer > > > logic into a common helper and reuses it for the CRC transformation. > > > > > > Changes in v2: > > > > > > - Factor the vectorizer's existing outside-loop debug-bind reset walk into > > > reset_debug_uses_outside_loop in tree-ssa-loop-manip.{cc,h}, as > > > suggested by > > > Richard. > > > - Reuse the helper from both vect_do_peeling and the CRC transformation. > > > - Rerun the focused test, bootstrap, and full regression tests. > > > > > > gcc/crc-verification.cc | 4 +++ > > > gcc/gimple-crc-optimization.cc | 5 ++++ > > > gcc/testsuite/gcc.dg/pr127716.c | 30 ++++++++++++++++++++++ > > > gcc/tree-ssa-loop-manip.cc | 45 +++++++++++++++++++++++++++++++++ > > > gcc/tree-ssa-loop-manip.h | 2 ++ > > > gcc/tree-vect-loop-manip.cc | 37 ++------------------------- > > > 6 files changed, 88 insertions(+), 35 deletions(-) > > > create mode 100644 gcc/testsuite/gcc.dg/pr127716.c > > > > > > diff --git a/gcc/crc-verification.cc b/gcc/crc-verification.cc > > > index ead4b8136..ffc93d0df 100644 > > > --- a/gcc/crc-verification.cc > > > +++ b/gcc/crc-verification.cc > > > @@ -45,6 +45,10 @@ crc_symbolic_execution::is_used_outside_the_loop (tree > > > def) > > > gimple *use_stmt; > > > FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def) > > > { > > > + /* Debug uses must not affect whether the loop is recognized. > > > Stale > > > + outside-loop binds are reset if the loop is transformed. */ > > > + if (is_gimple_debug (use_stmt)) > > > + continue; > > > if (!flow_bb_inside_loop_p (m_crc_loop, use_stmt->bb)) > > > { > > > if (is_a<gphi *> (use_stmt) > > > diff --git a/gcc/gimple-crc-optimization.cc > > > b/gcc/gimple-crc-optimization.cc > > > index 81ea0a381..ec985148e 100644 > > > --- a/gcc/gimple-crc-optimization.cc > > > +++ b/gcc/gimple-crc-optimization.cc > > > @@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see > > > #include "tree-cfg.h" > > > #include "cfgloop.h" > > > #include "tree-scalar-evolution.h" > > > +#include "tree-ssa-loop-manip.h" > > > #include "crc-verification.h" > > > #include "internal-fn.h" > > > #include "predict.h" > > > @@ -1274,6 +1275,10 @@ crc_optimization::optimize_crc_loop (class loop > > > *loop, gphi *output_crc) > > > return false; > > > } > > > > > > + basic_block *bbs = get_loop_body (loop); > > > + reset_debug_uses_outside_loop (loop, bbs, loop->num_nodes); > > > + free (bbs); > > > + > > > /* Add IFN call and write the return value in the phi_result. */ > > > gcall *call = gimple_build_call_internal (ifn, 3, m_crc_arg, > > > m_data_arg, > > > polynomial_arg); > > > diff --git a/gcc/testsuite/gcc.dg/pr127716.c > > > b/gcc/testsuite/gcc.dg/pr127716.c > > > new file mode 100644 > > > index 000000000..c7d3de54c > > > --- /dev/null > > > +++ b/gcc/testsuite/gcc.dg/pr127716.c > > > @@ -0,0 +1,30 @@ > > > +/* PR tree-optimization/127716 */ > > > +/* { dg-do compile } */ > > > +/* { dg-options "-O2 -g -fcompare-debug -fdump-tree-crc-details" } */ > > > + > > > +typedef unsigned short u16; > > > + > > > +#define POLY 0x1021 > > > + > > > +u16 > > > +crc16 (u16 data) > > > +{ > > > + int i = 0; > > > + u16 sh; > > > + > > > + do > > > + { > > > + sh = data << 1; > > > + if (data & 0x8000) > > > + data = sh ^ POLY; > > > + else > > > + data = sh; > > > + } > > > + while (++i < 16); > > > + > > > + u16 last __attribute__ ((unused)) = sh; > > > + return data; > > > +} > > > + > > > +/* { dg-final { scan-tree-dump "calculates CRC!" "crc" } } */ > > > +/* { dg-final { scan-tree-dump "# DEBUG last => NULL" "crc" } } */ > > > diff --git a/gcc/tree-ssa-loop-manip.cc b/gcc/tree-ssa-loop-manip.cc > > > index 7e1a183a1..f1e381e7d 100644 > > > --- a/gcc/tree-ssa-loop-manip.cc > > > +++ b/gcc/tree-ssa-loop-manip.cc > > > @@ -47,6 +47,51 @@ along with GCC; see the file COPYING3. If not see > > > so that we can free them all at once. */ > > > static bitmap_obstack loop_renamer_obstack; > > > > > > +/* Reset debug binds outside LOOP that use values defined in the > > > NUM_NODES > > > + basic blocks in BBS. */ > > > + > > > +void > > > +reset_debug_uses_outside_loop (class loop *loop, basic_block *bbs, > > > + unsigned num_nodes) > > > +{ > > > + for (unsigned i = 0; i < num_nodes; ++i) > > > + { > > > + basic_block bb = bbs[i]; > > > + imm_use_iterator ui; > > > + gimple *use_stmt; > > > + for (gphi_iterator gpi = gsi_start_phis (bb); !gsi_end_p (gpi); > > > + gsi_next (&gpi)) > > > + { > > > + FOR_EACH_IMM_USE_STMT (use_stmt, ui, > > > + gimple_phi_result (gpi.phi ())) > > > + if (gimple_debug_bind_p (use_stmt) > > > + && loop != gimple_bb (use_stmt)->loop_father > > > + && !flow_loop_nested_p (loop, > > > + gimple_bb > > > (use_stmt)->loop_father)) > > > + { > > > + gimple_debug_bind_reset_value (use_stmt); > > > + update_stmt (use_stmt); > > > + } > > > + } > > > + for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p > > > (gsi); > > > + gsi_next (&gsi)) > > > + { > > > + ssa_op_iter op_iter; > > > + def_operand_p def_p; > > > + FOR_EACH_SSA_DEF_OPERAND (def_p, gsi_stmt (gsi), op_iter, > > > SSA_OP_DEF) > > > + FOR_EACH_IMM_USE_STMT (use_stmt, ui, DEF_FROM_PTR (def_p)) > > > + if (gimple_debug_bind_p (use_stmt) > > > + && loop != gimple_bb (use_stmt)->loop_father > > > + && !flow_loop_nested_p (loop, > > > + gimple_bb > > > (use_stmt)->loop_father)) > > > + { > > > + gimple_debug_bind_reset_value (use_stmt); > > > + update_stmt (use_stmt); > > > + } > > > + } > > > + } > > > +} > > > + > > > /* Insert IV increment statements STMTS before or after INCR_POS; > > > AFTER selects which. INCR_POS and AFTER can be computed using > > > standard_iv_increment_position. */ > > > diff --git a/gcc/tree-ssa-loop-manip.h b/gcc/tree-ssa-loop-manip.h > > > index 521aac2db..aaa625e65 100644 > > > --- a/gcc/tree-ssa-loop-manip.h > > > +++ b/gcc/tree-ssa-loop-manip.h > > > @@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see > > > > > > typedef void (*transform_callback)(class loop *, void *); > > > > > > +extern void reset_debug_uses_outside_loop (class loop *, basic_block *, > > > + unsigned); > > > extern void insert_iv_increment (gimple_stmt_iterator *, bool, > > > gimple_seq); > > > extern void create_iv (tree, tree_code, tree, tree, class loop *, > > > gimple_stmt_iterator *, bool, tree *, tree *, > > > diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc > > > index 5e875d88f..a127fe4d1 100644 > > > --- a/gcc/tree-vect-loop-manip.cc > > > +++ b/gcc/tree-vect-loop-manip.cc > > > @@ -3522,41 +3522,8 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree > > > niters, tree nitersm1, > > > /* Before doing any peeling make sure to reset debug binds outside of > > > the loop referring to defs not in LC SSA. */ > > > class loop *loop = LOOP_VINFO_LOOP (loop_vinfo); > > > - for (unsigned i = 0; i < loop->num_nodes; ++i) > > > - { > > > - basic_block bb = LOOP_VINFO_BBS (loop_vinfo)[i]; > > > - imm_use_iterator ui; > > > - gimple *use_stmt; > > > - for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi); > > > - gsi_next (&gsi)) > > > - { > > > - FOR_EACH_IMM_USE_STMT (use_stmt, ui, gimple_phi_result (gsi.phi > > > ())) > > > - if (gimple_debug_bind_p (use_stmt) > > > - && loop != gimple_bb (use_stmt)->loop_father > > > - && !flow_loop_nested_p (loop, > > > - gimple_bb > > > (use_stmt)->loop_father)) > > > - { > > > - gimple_debug_bind_reset_value (use_stmt); > > > - update_stmt (use_stmt); > > > - } > > > - } > > > - for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p > > > (gsi); > > > - gsi_next (&gsi)) > > > - { > > > - ssa_op_iter op_iter; > > > - def_operand_p def_p; > > > - FOR_EACH_SSA_DEF_OPERAND (def_p, gsi_stmt (gsi), op_iter, > > > SSA_OP_DEF) > > > - FOR_EACH_IMM_USE_STMT (use_stmt, ui, DEF_FROM_PTR (def_p)) > > > - if (gimple_debug_bind_p (use_stmt) > > > - && loop != gimple_bb (use_stmt)->loop_father > > > - && !flow_loop_nested_p (loop, > > > - gimple_bb > > > (use_stmt)->loop_father)) > > > - { > > > - gimple_debug_bind_reset_value (use_stmt); > > > - update_stmt (use_stmt); > > > - } > > > - } > > > - } > > > + reset_debug_uses_outside_loop (loop, LOOP_VINFO_BBS (loop_vinfo), > > > + loop->num_nodes); > > > > > > prob_vector = profile_probability::guessed_always ().apply_scale (9, > > > 10); > > > estimated_vf = vect_vf_for_cost (loop_vinfo); > > > -- > > > 2.34.1 > > >
