]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Generate constant at start of loop, without UB
authorJørgen Kvalsvik <j@lambda.is>
Mon, 8 Apr 2024 13:19:55 +0000 (15:19 +0200)
committerJørgen Kvalsvik <j@lambda.is>
Tue, 9 Apr 2024 07:57:42 +0000 (09:57 +0200)
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 middle-end/114627

gcc/ChangeLog:

* tree-profile.cc (instrument_decisions): Generate constant
at the start of loop.

gcc/tree-profile.cc

index f9d727b31118007d5fe6d92d0b85f4c159ae4210..b85111624fedd07864eff8ae3bb36e369ff5af13 100644 (file)
@@ -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);