public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] tree-optimization: [PR102622]: wrong code due to signed one bit integer and "a?-1:0"
@ 2021-10-10  5:42 apinski
  2021-10-10  8:03 ` Richard Biener
  2021-10-11 13:07 ` Michael Matz
  0 siblings, 2 replies; 3+ messages in thread
From: apinski @ 2021-10-10  5:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: Andrew Pinski

From: Andrew Pinski <apinski@marvell.com>

So it turns out this is kinda of a latent bug but not really latent.
In GCC 9 and 10, phi-opt would transform a?-1:0 (even for signed 1-bit integer)
to -(type)a but the type is an one bit integer which means the negation is
undefined. GCC 11 fixed the problem by checking for a?pow2cst:0 transformation
before a?-1:0 transformation.

When I added the transformations to match.pd, I had swapped the order not paying
attention and I didn't expect anything of it. Because there was no testcase failing
due to this.
Anyways this fixes the problem on the trunk by swapping the order in match.pd and
adding a comment of why the order is this way.

I will try to come up with a patch for GCC 9 and 10 series later on which fixes
the problem there too.

Note I didn't include the original testcase which requires the vectorizer and AVX-512f
as I can't figure out the right dg options to restrict it to avx-512f but I did come up
with a testcase which shows the problem and even more shows the problem with the 9/10
series as mentioned.

OK? Bootstrapped and tested on x86_64-linux-gnu.

	PR tree-optimization/102622

gcc/ChangeLog:

	* match.pd: Swap the order of a?pow2cst:0 and a?-1:0 transformations.
	Swap the order of a?0:pow2cst and a?0:-1 transformations.

gcc/testsuite/ChangeLog:

	* gcc.c-torture/execute/bitfld-10.c: New test.
---
 gcc/match.pd                                  | 26 ++++++++++++-------
 .../gcc.c-torture/execute/bitfld-10.c         | 24 +++++++++++++++++
 2 files changed, 41 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.c-torture/execute/bitfld-10.c

diff --git a/gcc/match.pd b/gcc/match.pd
index 9d7c1ac637f..c153e9a6e98 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3949,15 +3949,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     /* a ? 1 : 0 -> a if 0 and 1 are integral types. */
     (if (integer_onep (@1))
      (convert (convert:boolean_type_node @0)))
-    /* a ? -1 : 0 -> -a. */
-    (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1))
-     (negate (convert (convert:boolean_type_node @0))))
     /* a ? powerof2cst : 0 -> a << (log2(powerof2cst)) */
     (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@1))
      (with {
        tree shift = build_int_cst (integer_type_node, tree_log2 (@1));
       }
-      (lshift (convert (convert:boolean_type_node @0)) { shift; })))))
+      (lshift (convert (convert:boolean_type_node @0)) { shift; })))
+    /* a ? -1 : 0 -> -a.  No need to check the TYPE_PRECISION not being 1
+       here as the powerof2cst case above will handle that case correctly.  */
+    (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1))
+     (negate (convert (convert:boolean_type_node @0))))))
   (if (integer_zerop (@1))
    (with {
       tree booltrue = constant_boolean_node (true, boolean_type_node);
@@ -3966,16 +3967,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
      /* a ? 0 : 1 -> !a. */
      (if (integer_onep (@2))
       (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )))
-     /* a ? -1 : 0 -> -(!a). */
-     (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2))
-      (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))))
      /* a ? powerof2cst : 0 -> (!a) << (log2(powerof2cst)) */
-     (if (INTEGRAL_TYPE_P (type) &&  integer_pow2p (@2))
+     (if (INTEGRAL_TYPE_P (type) &&  integer_pow2p (@2)
+         && TYPE_PRECISION (type) != 1)
       (with {
 	tree shift = build_int_cst (integer_type_node, tree_log2 (@2));
        }
        (lshift (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))
-        { shift; }))))))))
+        { shift; })))
+     /* a ? -1 : 0 -> -(!a).  No need to check the TYPE_PRECISION not being 1
+       here as the powerof2cst case above will handle that case correctly.  */
+     (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2))
+      (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))))
+    )
+   )
+  )
+ )
+)
 #endif
 
 /* Simplification moved from fold_cond_expr_with_comparison.  It may also
diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c b/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c
new file mode 100644
index 00000000000..bdbf5733ce7
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c
@@ -0,0 +1,24 @@
+/* PR tree-optimization/102622 */
+/* Wrong code introduced due to phi-opt
+   introducing undefined signed interger overflow
+   with one bit signed integer negation. */
+
+struct f{signed t:1;};
+int g(struct f *a, int t) __attribute__((noipa));
+int g(struct f *a, int t)
+{
+    if (t)
+      a->t = -1;
+    else
+      a->t = 0;
+    int t1 = a->t;
+    if (t1) return 1;
+    return t1;
+}
+
+int main(void)
+{
+    struct f a;
+    if (!g(&a, 1))  __builtin_abort();
+    return 0;
+}
-- 
2.17.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] tree-optimization: [PR102622]: wrong code due to signed one bit integer and "a?-1:0"
  2021-10-10  5:42 [PATCH] tree-optimization: [PR102622]: wrong code due to signed one bit integer and "a?-1:0" apinski
@ 2021-10-10  8:03 ` Richard Biener
  2021-10-11 13:07 ` Michael Matz
  1 sibling, 0 replies; 3+ messages in thread
From: Richard Biener @ 2021-10-10  8:03 UTC (permalink / raw)
  To: apinski, apinski--- via Gcc-patches, gcc-patches; +Cc: Andrew Pinski

On October 10, 2021 7:42:19 AM GMT+02:00, apinski--- via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>From: Andrew Pinski <apinski@marvell.com>
>
>So it turns out this is kinda of a latent bug but not really latent.
>In GCC 9 and 10, phi-opt would transform a?-1:0 (even for signed 1-bit integer)
>to -(type)a but the type is an one bit integer which means the negation is
>undefined. GCC 11 fixed the problem by checking for a?pow2cst:0 transformation
>before a?-1:0 transformation.
>
>When I added the transformations to match.pd, I had swapped the order not paying
>attention and I didn't expect anything of it. Because there was no testcase failing
>due to this.
>Anyways this fixes the problem on the trunk by swapping the order in match.pd and
>adding a comment of why the order is this way.
>
>I will try to come up with a patch for GCC 9 and 10 series later on which fixes
>the problem there too.
>
>Note I didn't include the original testcase which requires the vectorizer and AVX-512f
>as I can't figure out the right dg options to restrict it to avx-512f but I did come up
>with a testcase which shows the problem and even more shows the problem with the 9/10
>series as mentioned.
>
>OK? Bootstrapped and tested on x86_64-linux-gnu.

OK. 

Richard. 


>	PR tree-optimization/102622
>
>gcc/ChangeLog:
>
>	* match.pd: Swap the order of a?pow2cst:0 and a?-1:0 transformations.
>	Swap the order of a?0:pow2cst and a?0:-1 transformations.
>
>gcc/testsuite/ChangeLog:
>
>	* gcc.c-torture/execute/bitfld-10.c: New test.
>---
> gcc/match.pd                                  | 26 ++++++++++++-------
> .../gcc.c-torture/execute/bitfld-10.c         | 24 +++++++++++++++++
> 2 files changed, 41 insertions(+), 9 deletions(-)
> create mode 100644 gcc/testsuite/gcc.c-torture/execute/bitfld-10.c
>
>diff --git a/gcc/match.pd b/gcc/match.pd
>index 9d7c1ac637f..c153e9a6e98 100644
>--- a/gcc/match.pd
>+++ b/gcc/match.pd
>@@ -3949,15 +3949,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>     /* a ? 1 : 0 -> a if 0 and 1 are integral types. */
>     (if (integer_onep (@1))
>      (convert (convert:boolean_type_node @0)))
>-    /* a ? -1 : 0 -> -a. */
>-    (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1))
>-     (negate (convert (convert:boolean_type_node @0))))
>     /* a ? powerof2cst : 0 -> a << (log2(powerof2cst)) */
>     (if (INTEGRAL_TYPE_P (type) && integer_pow2p (@1))
>      (with {
>        tree shift = build_int_cst (integer_type_node, tree_log2 (@1));
>       }
>-      (lshift (convert (convert:boolean_type_node @0)) { shift; })))))
>+      (lshift (convert (convert:boolean_type_node @0)) { shift; })))
>+    /* a ? -1 : 0 -> -a.  No need to check the TYPE_PRECISION not being 1
>+       here as the powerof2cst case above will handle that case correctly.  */
>+    (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@1))
>+     (negate (convert (convert:boolean_type_node @0))))))
>   (if (integer_zerop (@1))
>    (with {
>       tree booltrue = constant_boolean_node (true, boolean_type_node);
>@@ -3966,16 +3967,23 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>      /* a ? 0 : 1 -> !a. */
>      (if (integer_onep (@2))
>       (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } )))
>-     /* a ? -1 : 0 -> -(!a). */
>-     (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2))
>-      (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))))
>      /* a ? powerof2cst : 0 -> (!a) << (log2(powerof2cst)) */
>-     (if (INTEGRAL_TYPE_P (type) &&  integer_pow2p (@2))
>+     (if (INTEGRAL_TYPE_P (type) &&  integer_pow2p (@2)
>+         && TYPE_PRECISION (type) != 1)
>       (with {
> 	tree shift = build_int_cst (integer_type_node, tree_log2 (@2));
>        }
>        (lshift (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))
>-        { shift; }))))))))
>+        { shift; })))
>+     /* a ? -1 : 0 -> -(!a).  No need to check the TYPE_PRECISION not being 1
>+       here as the powerof2cst case above will handle that case correctly.  */
>+     (if (INTEGRAL_TYPE_P (type) && integer_all_onesp (@2))
>+      (negate (convert (bit_xor (convert:boolean_type_node @0) { booltrue; } ))))
>+    )
>+   )
>+  )
>+ )
>+)
> #endif
> 
> /* Simplification moved from fold_cond_expr_with_comparison.  It may also
>diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c b/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c
>new file mode 100644
>index 00000000000..bdbf5733ce7
>--- /dev/null
>+++ b/gcc/testsuite/gcc.c-torture/execute/bitfld-10.c
>@@ -0,0 +1,24 @@
>+/* PR tree-optimization/102622 */
>+/* Wrong code introduced due to phi-opt
>+   introducing undefined signed interger overflow
>+   with one bit signed integer negation. */
>+
>+struct f{signed t:1;};
>+int g(struct f *a, int t) __attribute__((noipa));
>+int g(struct f *a, int t)
>+{
>+    if (t)
>+      a->t = -1;
>+    else
>+      a->t = 0;
>+    int t1 = a->t;
>+    if (t1) return 1;
>+    return t1;
>+}
>+
>+int main(void)
>+{
>+    struct f a;
>+    if (!g(&a, 1))  __builtin_abort();
>+    return 0;
>+}


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] tree-optimization: [PR102622]: wrong code due to signed one bit integer and "a?-1:0"
  2021-10-10  5:42 [PATCH] tree-optimization: [PR102622]: wrong code due to signed one bit integer and "a?-1:0" apinski
  2021-10-10  8:03 ` Richard Biener
@ 2021-10-11 13:07 ` Michael Matz
  1 sibling, 0 replies; 3+ messages in thread
From: Michael Matz @ 2021-10-11 13:07 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: gcc-patches

Hello,

On Sat, 9 Oct 2021, apinski--- via Gcc-patches wrote:

> +      (lshift (convert (convert:boolean_type_node @0)) { shift; })))
> +    /* a ? -1 : 0 -> -a.  No need to check the TYPE_PRECISION not being 1
> +       here as the powerof2cst case above will handle that case correctly.  */

Well, but the QoI will improve quite a bit when you just do the check, 
instead of relying on order of patterns.  It's not slow or harmful to 
check and will make the order irrelevant, which, given the number of 
patterns we already have, is a good thing.  (It will also be smaller to 
check than to document why the check isn't needed :-) )


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-10-11 13:07 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-10  5:42 [PATCH] tree-optimization: [PR102622]: wrong code due to signed one bit integer and "a?-1:0" apinski
2021-10-10  8:03 ` Richard Biener
2021-10-11 13:07 ` Michael Matz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).