https://gcc.gnu.org/g:7bb5f632a124d27f91fb2f2986e7e041dcb44080
commit r16-6792-g7bb5f632a124d27f91fb2f2986e7e041dcb44080 Author: Kugan Vivekanandarajah <[email protected]> Date: Thu Jan 15 14:39:33 2026 +1100 [AutoFDO] Add hierarchical discriminator for loop versioning Add hierarchical discriminator support for loop versioning pass. Assigns copyid discriminators to distinguish different loop versions. gcc/ChangeLog: * gimple-loop-versioning.cc (loop_versioning::version_loop): Assign copyid discriminators to distinguish different loop versions. gcc/testsuite/ChangeLog: * gcc.dg/hierarchical-discriminator-loop-version.c: New test. Signed-off-by: Kugan Vivekanandarajah <[email protected]> Diff: --- gcc/gimple-loop-versioning.cc | 20 ++++++++++++++++ .../hierarchical-discriminator-loop-version.c | 28 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/gcc/gimple-loop-versioning.cc b/gcc/gimple-loop-versioning.cc index d913c217ee63..71bf1b2f256a 100644 --- a/gcc/gimple-loop-versioning.cc +++ b/gcc/gimple-loop-versioning.cc @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-into-ssa.h" #include "gimple-range.h" #include "tree-cfg.h" +#include "hierarchical_discriminator.h" namespace { @@ -1699,6 +1700,25 @@ loop_versioning::version_loop (class loop *loop) return false; } + /* Assign hierarchical discriminators to distinguish loop versions. + This allows AutoFDO to distinguish profile data from different + versions. No multiplicity for non-vectorized loop versioning. */ + gimple *optimized_last = last_nondebug_stmt (li.optimized_loop->header); + location_t optimized_loc + = optimized_last ? gimple_location (optimized_last) : UNKNOWN_LOCATION; + if (optimized_loc != UNKNOWN_LOCATION) + { + unsigned int optimized_copyid = allocate_copyid_base (optimized_loc, 1); + assign_discriminators_to_loop (li.optimized_loop, 0, optimized_copyid); + } + gimple *loop_last = last_nondebug_stmt (loop->header); + location_t loop_loc + = loop_last ? gimple_location (loop_last) : UNKNOWN_LOCATION; + if (loop_loc != UNKNOWN_LOCATION) + { + unsigned int loop_copyid = allocate_copyid_base (loop_loc, 1); + assign_discriminators_to_loop (loop, 0, loop_copyid); + } if (dump_enabled_p ()) dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, find_loop_location (loop), "versioned this loop for when certain strides are 1\n"); diff --git a/gcc/testsuite/gcc.dg/hierarchical-discriminator-loop-version.c b/gcc/testsuite/gcc.dg/hierarchical-discriminator-loop-version.c new file mode 100644 index 000000000000..af9dddf554f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/hierarchical-discriminator-loop-version.c @@ -0,0 +1,28 @@ +/* Test hierarchical discriminators for loop versioning pass. + { dg-do compile } + { dg-options "-O3 -g -fdump-tree-lversion-details" } + { dg-require-effective-target size32plus } */ + +void +test_loop_versioning (double *x, int stepx, int n) +{ + for (int i = 0; i < n; ++i) + x[stepx * i] = 100; +} + +/* Expected discriminators from the assembly (hierarchical format: [Base:8][Multiplicity:7][CopyID:11][Unused:6]): + + Loop versioning creates two versions: + 1. Optimized loop (for stride == 1): + - copyid = allocate_copyid_base(loc, 1) = 1 (first allocation) + - multiplicity = 0 (no vectorization in this pass) + - Discriminator = base:0 | (0<<8) | (1<<15) = 0 | 0 | 32768 = 32768 + + 2. Unoptimized loop (for stride != 1): + - copyid = allocate_copyid_base(loc, 1) = 2 (second allocation at same location) + - multiplicity = 0 + - Discriminator = base:0 | (0<<8) | (2<<15) = 0 | 0 | 65536 = 65536 +*/ + +/* { dg-final { scan-tree-dump "versioned this loop for when certain strides are 1" "lversion" } } */ +/* { dg-final { scan-assembler "\\.loc 1 14 \[0-9\]+ is_stmt 0 discriminator \[0-9\]+" } } */
