On Mon, 8 Apr 2024, Jørgen Kvalsvik wrote:

> 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.

OK.

Thanks,
Richard.

>       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);
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to