]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[AutoFDO] Walk function body to to find existing max copyids per location
authorKugan Vivekanandarajah <kvivekananda@nvidia.com>
Fri, 16 Jan 2026 20:59:57 +0000 (07:59 +1100)
committerKugan Vivekanandarajah <kvivekananda@nvidia.com>
Fri, 16 Jan 2026 20:59:57 +0000 (07:59 +1100)
This patch addresses the review comment and walks the function body to
find existing max copyids per location in init_copyid_allocator.

gcc/ChangeLog:

2026-01-15  Kugan Vivekanandarajah  <kvivekananda@nvidia.com>

* hierarchical_discriminator.cc (init_copyid_allocator): Walks the function
body to find existing max copyids per location.
(record_existing_copyid): New.

gcc/testsuite/ChangeLog:

2026-01-15  Kugan Vivekanandarajah  <kvivekananda@nvidia.com>

* gcc.dg/hierarchical-discriminator-loop-version.c: Simplify.
* gcc.dg/hierarchical-discriminator-unroll.c: Likewise
* gcc.dg/hierarchical-discriminator-vect-version.c: Likewise.

Signed-off-by: Kugan Vivekanandarajah <kvivekananda@nvidia.com>
gcc/hierarchical_discriminator.cc
gcc/testsuite/gcc.dg/hierarchical-discriminator-loop-version.c
gcc/testsuite/gcc.dg/hierarchical-discriminator-unroll.c
gcc/testsuite/gcc.dg/hierarchical-discriminator-vect-version.c

index 734da65c29d37169c5568c93c0f7ca8d8def1c8a..009b1a83f1e84dd3ee81ddd1d34c8c1b01fc5940 100644 (file)
@@ -184,7 +184,38 @@ assign_discriminators_to_loop (class loop *loop,
 }
 
 
-/* Initialize the per-function copyid allocator.  */
+/* Helper to update the copyid allocator map with a location's existing copyid.
+   If the location has a non-zero copyid, record that we need to start
+   allocating from copyid+1 for this location.  */
+
+static void
+record_existing_copyid (location_t loc, struct function *fn)
+{
+  if (loc == UNKNOWN_LOCATION)
+    return;
+
+  location_t pure_loc = get_pure_location (loc);
+  unsigned int discr = get_discriminator_from_loc (loc);
+  if (discr == 0)
+    return;
+
+  /* Extract copyid from discriminator.  */
+  unsigned int copyid = (discr >> DISCR_COPYID_SHIFT) & DISCR_COPYID_MASK;
+  if (copyid == 0)
+    return;
+
+  /* Update max copyid for this location.  */
+  unsigned int next_copyid = copyid + 1;
+  if (next_copyid > DISCR_COPYID_MAX)
+    next_copyid = DISCR_COPYID_MAX;
+
+  unsigned int *existing = fn->copyid_alloc->location_map->get (pure_loc);
+  if (!existing || *existing <= copyid)
+    fn->copyid_alloc->location_map->put (pure_loc, next_copyid);
+}
+
+/* Initialize the per-function copyid allocator.  Walks the function
+   body to find existing max copyids per location.  */
 
 static void
 init_copyid_allocator (struct function *fn)
@@ -192,13 +223,59 @@ init_copyid_allocator (struct function *fn)
   if (!fn)
     return;
 
-  if (fn->copyid_alloc)
+  if (fn->copyid_alloc && fn->copyid_alloc->initialized)
     return;  /* Already initialized.  */
 
-  fn->copyid_alloc = XNEW (struct copyid_allocator);
-  fn->copyid_alloc->location_map
-    = new hash_map<int_hash<location_t, UNKNOWN_LOCATION, UNKNOWN_LOCATION>,
-                  unsigned int>;
+  if (!fn->copyid_alloc)
+    {
+      fn->copyid_alloc = XNEW (struct copyid_allocator);
+      fn->copyid_alloc->location_map
+       = new hash_map<int_hash<location_t, UNKNOWN_LOCATION,
+                              UNKNOWN_LOCATION>, unsigned int>;
+      fn->copyid_alloc->initialized = false;
+    }
+
+  /* Only walk the body if not yet initialized.  */
+  if (fn->copyid_alloc->initialized)
+    return;
+
+  /* Walk the function body to find existing max copyids per location.
+     This ensures we don't reuse copyids that were allocated in previous
+     passes, during LTO, or brought in by inlining.  */
+  basic_block bb;
+  FOR_EACH_BB_FN (bb, fn)
+    {
+      if (current_ir_type () == IR_GIMPLE)
+       {
+         /* Process PHI nodes.  */
+         gphi_iterator phi_gsi;
+         for (phi_gsi = gsi_start_phis (bb); !gsi_end_p (phi_gsi);
+              gsi_next (&phi_gsi))
+           record_existing_copyid (gimple_location (phi_gsi.phi ()), fn);
+
+         /* Process regular statements.  */
+         gimple_stmt_iterator gsi;
+         for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+           record_existing_copyid (gimple_location (gsi_stmt (gsi)), fn);
+
+         /* Process edge goto_locus locations.  */
+         edge e;
+         edge_iterator ei;
+         FOR_EACH_EDGE (e, ei, bb->succs)
+           record_existing_copyid (e->goto_locus, fn);
+       }
+      else
+       {
+         /* For RTL mode.  */
+         rtx_insn *insn;
+         FOR_BB_INSNS (bb, insn)
+           {
+             if (INSN_P (insn))
+               record_existing_copyid (INSN_LOCATION (insn), fn);
+           }
+       }
+    }
+
   fn->copyid_alloc->initialized = true;
 }
 
index af9dddf554f01bc02ee53d53f0be7534042a662e..dbe7953e3e306cad6093bae1cc4d016f95067725 100644 (file)
@@ -10,19 +10,11 @@ test_loop_versioning (double *x, int stepx, int n)
     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
-*/
+/* Loop versioning creates two versions of the loop, each should get a distinct
+   copyid in the hierarchical discriminator format: [Base:8][Multiplicity:7][CopyID:11][Unused:6].
+   The exact copyid values depend on what other passes have run before, but both
+   loop versions should have non-zero discriminators to distinguish them for AutoFDO. */
 
+/* Check that loop versioning occurred and discriminators are present on the loop body. */
 /* { 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\]+" } } */
+/* { dg-final { scan-assembler "\\.loc 1 (9|10) \[0-9\]+ is_stmt 0 discriminator \[0-9\]+" } } */
index c22baaeee38f9ec034c3916c50a5bd1631820af7..f137c1c6b1416fba75856486c6da48eddefd9e18 100644 (file)
@@ -21,17 +21,10 @@ test_unroll (void)
   return sum;
 }
 
-/* Expected discriminators from the assembly (hierarchical format: [Base:8][Multiplicity:7][CopyID:11][Unused:6]):
-   Loop unrolling with ndupl=4:
-   - allocate_copyid_base(loc, 4) returns base=1 (first time)
-   - Iteration 0: copyid = 1+0 = 1, multiplicity=0 → 0|(0<<8)|(1<<15) = 32768
-   - Iteration 1: copyid = 1+1 = 2, multiplicity=0 → 0|(0<<8)|(2<<15) = 65536
-   - Iteration 2: copyid = 1+2 = 3, multiplicity=0 → 0|(0<<8)|(3<<15) = 98304
-   - Iteration 3: copyid = 1+3 = 4, multiplicity=0 → 0|(0<<8)|(4<<15) = 131072
-*/
+/* Loop unrolling with #pragma GCC unroll 4 should create 4 copies with distinct
+   copyids in the hierarchical discriminator format: [Base:8][Multiplicity:7][CopyID:11][Unused:6].
+   Each unrolled iteration should get a different copyid, resulting in different discriminators.
+   The exact values depend on what other passes have run, but all should be non-zero. */
 
-/* Each unrolled iteration should have a different discriminator */
-/* { dg-final { scan-assembler "\\.loc 1 17 7 is_stmt 0 discriminator 32768" } } */
-/* { dg-final { scan-assembler "\\.loc 1 17 7 is_stmt 0 discriminator 65536" } } */
-/* { dg-final { scan-assembler "\\.loc 1 17 7 is_stmt 0 discriminator 98304" } } */
-/* { dg-final { scan-assembler "\\.loc 1 17 7 is_stmt 0 discriminator 131072" } } */
+/* Check that unrolled iterations have non-zero discriminators on the asm statement line. */
+/* { dg-final { scan-assembler "\\.loc 1 17 7 is_stmt 0 discriminator (\[1-9\]\[0-9\]*|0x\[1-9a-fA-F\]\[0-9a-fA-F\]*)" } } */
index 5dc945f1274d68c990b43cd14c6dcc62e10483c4..95f1fe0b9334b64095c017540d2d5ab6b2e8a4c9 100644 (file)
@@ -14,4 +14,6 @@ test_vectorize (int *a, int *b, int *c, int n)
     }
 }
 
-/* { dg-final { scan-assembler "\\.loc 1 13 \[0-9\]+ is_stmt 0 discriminator \[0-9\]+" } } */
+/* Check that vectorized code has discriminators on the main loop body line.
+   The discriminator should be non-zero to distinguish vector vs scalar versions. */
+/* { dg-final { scan-assembler "\\.loc 1 13 \[0-9\]+ is_stmt 0 discriminator (\[1-9\]\[0-9\]*|0x\[1-9a-fA-F\]\[0-9a-fA-F\]*)" } } */