diff mbox series

[18/22] Don't contract into random edge in multi-succ node

Message ID 20231004123921.634024-19-j@lambda.is
State New
Headers show
Series [01/22] Add condition coverage profiling | expand

Commit Message

Jørgen Kvalsvik Oct. 4, 2023, 12:39 p.m. UTC
A check was missing for is-single when contracting, so if a
multi-successor node that was not a condition node (e.g. a switch) a
random edge would be picked and contracted into.
---
 gcc/testsuite/gcc.misc-tests/gcov-23.c | 48 ++++++++++++++++++++++++++
 gcc/tree-profile.cc                    |  4 +++
 2 files changed, 52 insertions(+)

Comments

Jørgen Kvalsvik Oct. 4, 2023, 3:29 p.m. UTC | #1
On 04/10/2023 21:39, Jørgen Kvalsvik wrote:
> A check was missing for is-single when contracting, so if a
> multi-successor node that was not a condition node (e.g. a switch) a
> random edge would be picked and contracted into.
> ---
>   gcc/testsuite/gcc.misc-tests/gcov-23.c | 48 ++++++++++++++++++++++++++
>   gcc/tree-profile.cc                    |  4 +++
>   2 files changed, 52 insertions(+)
> 
> diff --git a/gcc/testsuite/gcc.misc-tests/gcov-23.c b/gcc/testsuite/gcc.misc-tests/gcov-23.c
> index c4afc5e700d..856e97f5088 100644
> --- a/gcc/testsuite/gcc.misc-tests/gcov-23.c
> +++ b/gcc/testsuite/gcc.misc-tests/gcov-23.c
> @@ -3,6 +3,7 @@
>   int id (int);
>   int idp (int *);
>   int err;
> +char c;
>   
>   /* This becomes problematic only under optimization for the case when the
>      compiler cannot inline the function but have to generate a call.  It is not
> @@ -72,4 +73,51 @@ exit:
>       return a;
>   }
>   
> +/* Adapted from icu4c-73.1 common/ucase.cpp ucase_getLocaleCase ().  */
> +int
> +mcdc003 (const char *locale)
> +{
> +    /* extern, so its effect won't be optimized out.  */
> +    c = *locale++;
> +    if (c == 'z') /* conditions(0/2) true(0) false(0) */
> +		  /* conditions(end) */
> +    {
> +	return 1;
> +    }
> +    else if (c >= 'a') /* conditions(0/2) true(0) false(0) */
> +		      /* conditions(end) */
> +    {
> +	if (id (c)) /* conditions(0/2) true(0) false(0) */
> +		    /* conditions(end) */
> +	    c = *locale++;
> +    }
> +    else
> +    {
> +	if (c == 'T')
> +	{
> +	    if (id (c)) /* conditions(0/2) true(0) false(0) */
> +			/* conditions(end) */
> +		c = *locale++;
> +	    if (id (c)) /* conditions(0/2) true(0) false(0) */
> +			/* conditions(end) */
> +		c = *locale++;
> +	}
> +	else if (c == 'L')
> +	    c = *locale++;
> +	else if (c == 'E')
> +	    c = *locale++;
> +	else if (c == 'N')
> +	    c = *locale++;
> +	else if (c == 'H')
> +	{
> +	    c = *locale++;
> +	    if (id (c)) /* conditions(0/2) true(0) false(0) */
> +			/* conditions(end) */
> +		c = *locale++;
> +	}
> +    }
> +
> +    return 1;
> +}
> +
>   /* { dg-final { run-gcov conditions { --conditions gcov-23.c } } } */
> diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
> index 26e1924d444..ce679130ca0 100644
> --- a/gcc/tree-profile.cc
> +++ b/gcc/tree-profile.cc
> @@ -297,6 +297,10 @@ contract_edge (edge e, sbitmap G = nullptr)
>   	    return source;
>   	if (block_conditional_p (dest))
>   	    return e;
> +	/* This happens for switches, and must be checked after the is-conditional
> +	   (which is also not single).  */
> +	if (!single (dest->succs))
> +	    return source;
>   
>   	if (G)
>   	    bitmap_set_bit (G, dest->index);

This test seems to fail on aarch64 (thanks, linaro bot)


FAIL: 24 regressions

regressions.sum:
		=== gcc tests ===

Running gcc:gcc.misc-tests/gcov.exp ...
FAIL: gcc.misc-tests/gcov-23.c gcov: 0 failures in line counts, 0 in 
branch percentages, 13 in condition/decision, 0 in return percentages, 0 
in intermediate format
FAIL: gcc.misc-tests/gcov-23.c line 108: unexpected summary 0/2
FAIL: gcc.misc-tests/gcov-23.c line 108: unexpected uncovered term 0 (false)
FAIL: gcc.misc-tests/gcov-23.c line 108: unexpected uncovered term 0 (true)
FAIL: gcc.misc-tests/gcov-23.c line 110: unexpected summary 0/2
FAIL: gcc.misc-tests/gcov-23.c line 110: unexpected uncovered term 0 (false)
FAIL: gcc.misc-tests/gcov-23.c line 110: unexpected uncovered term 0 (true)
... and 19 more entries

Apparently the if-else do not get turned into a switch here. I have a 
look and see if I can reproduce the problem with an explicit switch 
rather than the implied one from if-else, as it is broken in its current 
state.
diff mbox series

Patch

diff --git a/gcc/testsuite/gcc.misc-tests/gcov-23.c b/gcc/testsuite/gcc.misc-tests/gcov-23.c
index c4afc5e700d..856e97f5088 100644
--- a/gcc/testsuite/gcc.misc-tests/gcov-23.c
+++ b/gcc/testsuite/gcc.misc-tests/gcov-23.c
@@ -3,6 +3,7 @@ 
 int id (int);
 int idp (int *);
 int err;
+char c;
 
 /* This becomes problematic only under optimization for the case when the
    compiler cannot inline the function but have to generate a call.  It is not
@@ -72,4 +73,51 @@  exit:
     return a;
 }
 
+/* Adapted from icu4c-73.1 common/ucase.cpp ucase_getLocaleCase ().  */
+int
+mcdc003 (const char *locale)
+{
+    /* extern, so its effect won't be optimized out.  */
+    c = *locale++;
+    if (c == 'z') /* conditions(0/2) true(0) false(0) */
+		  /* conditions(end) */
+    {
+	return 1;
+    }
+    else if (c >= 'a') /* conditions(0/2) true(0) false(0) */
+		      /* conditions(end) */
+    {
+	if (id (c)) /* conditions(0/2) true(0) false(0) */
+		    /* conditions(end) */
+	    c = *locale++;
+    }
+    else
+    {
+	if (c == 'T')
+	{
+	    if (id (c)) /* conditions(0/2) true(0) false(0) */
+			/* conditions(end) */
+		c = *locale++;
+	    if (id (c)) /* conditions(0/2) true(0) false(0) */
+			/* conditions(end) */
+		c = *locale++;
+	}
+	else if (c == 'L')
+	    c = *locale++;
+	else if (c == 'E')
+	    c = *locale++;
+	else if (c == 'N')
+	    c = *locale++;
+	else if (c == 'H')
+	{
+	    c = *locale++;
+	    if (id (c)) /* conditions(0/2) true(0) false(0) */
+			/* conditions(end) */
+		c = *locale++;
+	}
+    }
+
+    return 1;
+}
+
 /* { dg-final { run-gcov conditions { --conditions gcov-23.c } } } */
diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
index 26e1924d444..ce679130ca0 100644
--- a/gcc/tree-profile.cc
+++ b/gcc/tree-profile.cc
@@ -297,6 +297,10 @@  contract_edge (edge e, sbitmap G = nullptr)
 	    return source;
 	if (block_conditional_p (dest))
 	    return e;
+	/* This happens for switches, and must be checked after the is-conditional
+	   (which is also not single).  */
+	if (!single (dest->succs))
+	    return source;
 
 	if (G)
 	    bitmap_set_bit (G, dest->index);