Generating the constants used for recording the edges taken for
condition coverage would trigger undefined behavior when an expression
had exactly 64 (== sizeof (1ULL)) conditions, as it would generate the
constant for the next iteration at the end of the loop body, even if there
was never a next iteration. By moving the check and constant generation
to the top of the loop and hoisting the increment flag there is no
opportunity for UB.

        PR 114627

gcc/ChangeLog:

        * tree-profile.cc (instrument_decisions): Generate constant
        at the start of loop.
---
 gcc/tree-profile.cc | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
index 33ff550a7bc..e58f5c83472 100644
--- a/gcc/tree-profile.cc
+++ b/gcc/tree-profile.cc
@@ -1049,6 +1049,7 @@ instrument_decisions (array_slice<basic_block> expr, 
size_t condno,
     zerocounter[2] = zero;
 
     unsigned xi = 0;
+    bool increment = false;
     tree rhs = build_int_cst (gcov_type_node, 1ULL << xi);
     for (basic_block current : expr)
     {
@@ -1057,7 +1058,14 @@ instrument_decisions (array_slice<basic_block> expr, 
size_t condno,
            candidates.safe_push (zerocounter);
        counters prev = resolve_counters (candidates);
 
-       int increment = 0;
+       if (increment)
+       {
+           xi += 1;
+           gcc_checking_assert (xi < sizeof (uint64_t) * BITS_PER_UNIT);
+           rhs = build_int_cst (gcov_type_node, 1ULL << xi);
+           increment = false;
+       }
+
        for (edge e : current->succs)
        {
            counters next = prev;
@@ -1072,7 +1080,7 @@ instrument_decisions (array_slice<basic_block> expr, 
size_t condno,
                    tree m = build_int_cst (gcov_type_node, masks[2*xi + k]);
                    next[2] = emit_bitwise_op (e, prev[2], BIT_IOR_EXPR, m);
                }
-               increment = 1;
+               increment = true;
            }
            else if (e->flags & EDGE_COMPLEX)
            {
@@ -1085,11 +1093,13 @@ instrument_decisions (array_slice<basic_block> expr, 
size_t condno,
            }
            table.get_or_insert (e->dest).safe_push (next);
        }
-       xi += increment;
-       if (increment)
-           rhs = build_int_cst (gcov_type_node, 1ULL << xi);
     }
 
+    /* Since this is also the return value, the number of conditions, make sure
+       to include the increment of the last basic block.  */
+    if (increment)
+       xi += 1;
+
     gcc_assert (xi == bitmap_count_bits (core));
 
     const tree relaxed = build_int_cst (integer_type_node, MEMMODEL_RELAXED);
-- 
2.30.2

Reply via email to