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\]+" } } */

Reply via email to