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
> > >

Reply via email to