On 7/16/2026 5:59 PM, Sebastian Huber wrote:
There are targets which only offer 32-bit atomic operations (for example
32-bit RISC-V).  For these targets, split the 64-bit atomic bitwise-or
operation used to update condition/decision coverage counters into up to
two 32-bit atomic bitwise-or operations, one per 32-bit half of the
counter.  If a half folds to a compile-time constant zero, then the
atomic bitwise-or operation for that half is a no-op and is omitted, the
same optimization already applied to whole-counter updates.

For this test case

int a(int i);
int b(int i);

int f(int i)
{
   if (i) {
     return a(i);
   } else {
     return b(i);
   }
}

with options

-O2 -fprofile-update=atomic -fcondition-coverage

on a 32-bit RISC-V target with the atomic extension but no 64-bit atomic
instructions, each counter update now generates a single inlined

   amoor.w zero,a4,0(a5)

instead of a call into libatomic.  The always-zero high 32-bit half of
the counter is folded away at compile time, so its atomic bitwise-or
operation is omitted.  On a target with 64-bit atomic instructions, such
as 64-bit RISC-V, a single

   amoor.d zero,a4,0(a5)

is generated, unchanged from before this patch.

Tested on x86_64-pc-linux-gnu (gcov.exp, gcc.dg gcov*.c, tree-prof.exp)
with no regressions, and cross-checked code generation on 32-bit and
64-bit RISC-V (rv32ima/ilp32 and rv64ima/lp64).

gcc/ChangeLog:

        * tree-profile.cc (split_update_decision_counter): New.
        (instrument_decisions): Use counter_update to determine which
        atomic operations are available.  Use
        split_update_decision_counter() if 64-bit atomic operations can
        be split up into two 32-bit atomic operations.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/amo/gcov-condition-coverage-split-ior.c: New
        test.

Signed-off-by: Sebastian Huber <[email protected]>
---

v2:

* Properly use a right shift (RSHIFT_EXPR) to get the higher order
   32-bits of the counter.

* Fix style issue.

v3:

* Update to take into account the recent counter optimization changes.

* Add test case.


+static void
+split_update_decision_counter (gimple_seq *seq, tree ref, tree counter,
+                              tree atomic_ior_32, tree relaxed)
+{
+  ref = unshare_expr (ref);
+
+  /* Get the low and high address of the referenced counter */
Make sure your comments are full sentences.  End them with a period, two spaces and the close comment  the same nit is repeated a few times in this function.
@@ -1191,6 +1244,9 @@ instrument_decisions (array_slice<basic_block> expr, 
size_t condno,
                                                    next[k], relaxed);
                  gimple_seq_add_stmt (&seq, flush);
                }
+             else if (use_atomic_split)
+                 split_update_decision_counter (&seq, ref, next[k],
+                                                atomic_ior_32, relaxed);
Another nit.  It's a bit incconsistent, but our coding guidelines would have the call to split_udpate_decision_counter indented 2 positions inside the else-if, not 4 positions like you've done.  4 positions would be right if you had enclosing curly braces, but those would be redundant here (and it does get called out regularly).  So adjust the indention to just two positions inside the else-if.

OK with the nits fixed.  No need for another review round.

jeff

Reply via email to