diff mbox series

Check for bitwise identity when encoding VECTOR_CSTs (PR 92768)

Message ID mpth82fcbl1.fsf@arm.com
State New
Headers show
Series Check for bitwise identity when encoding VECTOR_CSTs (PR 92768) | expand

Commit Message

Richard Sandiford Dec. 5, 2019, 10:26 a.m. UTC
This PR shows that we weren't checking for bitwise-identical values
when trying to encode a VECTOR_CST, so -0.0 was treated the same as
0.0 for -fno-signed-zeros.  The patch adds a new OEP flag to select
that behaviour.

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard


2019-12-05  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	PR middle-end/92768
	* tree-core.h (OEP_BITWISE): New flag.
	* fold-const.c (operand_compare::operand_equal_p): Handle it.
	* tree-vector-builder.h (tree_vector_builder::equal_p): Pass it.

gcc/testsuite/
	PR middle-end/92768
	* gcc.dg/pr92768.c: New test.

Comments

Richard Biener Dec. 5, 2019, 12:42 p.m. UTC | #1
On Thu, Dec 5, 2019 at 11:26 AM Richard Sandiford
<richard.sandiford@arm.com> wrote:
>
> This PR shows that we weren't checking for bitwise-identical values
> when trying to encode a VECTOR_CST, so -0.0 was treated the same as
> 0.0 for -fno-signed-zeros.  The patch adds a new OEP flag to select
> that behaviour.
>
> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

OK.

Thanks,
Richard.

> Richard
>
>
> 2019-12-05  Richard Sandiford  <richard.sandiford@arm.com>
>
> gcc/
>         PR middle-end/92768
>         * tree-core.h (OEP_BITWISE): New flag.
>         * fold-const.c (operand_compare::operand_equal_p): Handle it.
>         * tree-vector-builder.h (tree_vector_builder::equal_p): Pass it.
>
> gcc/testsuite/
>         PR middle-end/92768
>         * gcc.dg/pr92768.c: New test.
>
> Index: gcc/tree-core.h
> ===================================================================
> --- gcc/tree-core.h     2019-11-29 13:04:14.458669072 +0000
> +++ gcc/tree-core.h     2019-12-05 10:25:10.660172853 +0000
> @@ -881,7 +881,8 @@ enum operand_equal_flag {
>    /* Internal within inchash::add_expr:  */
>    OEP_HASH_CHECK = 32,
>    /* Makes operand_equal_p handle more expressions:  */
> -  OEP_LEXICOGRAPHIC = 64
> +  OEP_LEXICOGRAPHIC = 64,
> +  OEP_BITWISE = 128
>  };
>
>  /* Enum and arrays used for tree allocation stats.
> Index: gcc/fold-const.c
> ===================================================================
> --- gcc/fold-const.c    2019-12-04 13:14:12.222218581 +0000
> +++ gcc/fold-const.c    2019-12-05 10:25:10.656172882 +0000
> @@ -2938,6 +2938,11 @@ combine_comparisons (location_t loc,
>     If OEP_LEXICOGRAPHIC is set, then also handle expressions with side-effects
>     such as MODIFY_EXPR, RETURN_EXPR, as well as STATEMENT_LISTs.
>
> +   If OEP_BITWISE is set, then require the values to be bitwise identical
> +   rather than simply numerically equal.  Do not take advantage of things
> +   like math-related flags or undefined behavior; only return true for
> +   values that are provably bitwise identical in all circumstances.
> +
>     Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on
>     any operand with side effect.  This is unnecesarily conservative in the
>     case we know that arg0 and arg1 are in disjoint code paths (such as in
> @@ -2967,6 +2972,11 @@ operand_compare::operand_equal_p (const_
>    if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1))
>      return false;
>
> +  /* Bitwise identity makes no sense if the values have different layouts.  */
> +  if ((flags & OEP_BITWISE)
> +      && !tree_nop_conversion_p (TREE_TYPE (arg0), TREE_TYPE (arg1)))
> +    return false;
> +
>    /* We cannot consider pointers to different address space equal.  */
>    if (POINTER_TYPE_P (TREE_TYPE (arg0))
>        && POINTER_TYPE_P (TREE_TYPE (arg1))
> @@ -3099,8 +3109,7 @@ operand_compare::operand_equal_p (const_
>         if (real_identical (&TREE_REAL_CST (arg0), &TREE_REAL_CST (arg1)))
>           return true;
>
> -
> -       if (!HONOR_SIGNED_ZEROS (arg0))
> +       if (!(flags & OEP_BITWISE) && !HONOR_SIGNED_ZEROS (arg0))
>           {
>             /* If we do not distinguish between signed and unsigned zero,
>                consider them equal.  */
> @@ -3152,7 +3161,9 @@ operand_compare::operand_equal_p (const_
>         break;
>        }
>
> -  if (flags & OEP_ONLY_CONST)
> +  /* Don't handle more cases for OEP_BITWISE, since we can't guarantee that
> +     two instances of undefined behavior will give identical results.  */
> +  if (flags & (OEP_ONLY_CONST | OEP_BITWISE))
>      return false;
>
>  /* Define macros to test an operand from arg0 and arg1 for equality and a
> Index: gcc/tree-vector-builder.h
> ===================================================================
> --- gcc/tree-vector-builder.h   2019-07-29 09:40:10.142001362 +0100
> +++ gcc/tree-vector-builder.h   2019-12-05 10:25:10.660172853 +0000
> @@ -88,7 +88,7 @@ tree_vector_builder::new_vector (tree ty
>  inline bool
>  tree_vector_builder::equal_p (const_tree elt1, const_tree elt2) const
>  {
> -  return operand_equal_p (elt1, elt2, 0);
> +  return operand_equal_p (elt1, elt2, OEP_BITWISE);
>  }
>
>  /* Return true if a stepped representation is OK.  We don't allow
> Index: gcc/testsuite/gcc.dg/pr92768.c
> ===================================================================
> --- /dev/null   2019-09-17 11:41:18.176664108 +0100
> +++ gcc/testsuite/gcc.dg/pr92768.c      2019-12-05 10:25:10.660172853 +0000
> @@ -0,0 +1,6 @@
> +/* { dg-options "-O2 -fno-signed-zeros -fdump-tree-optimized" } */
> +
> +typedef float v4sf __attribute__((vector_size(16)));
> +v4sf f () { return (v4sf) { 0.0, -0.0, 0.0, -0.0 }; }
> +
> +/* { dg-final { scan-tree-dump {{ 0\.0, -0\.0, 0\.0, -0\.0 }} "optimized" } } */
Jakub Jelinek Dec. 5, 2019, 11:56 p.m. UTC | #2
On Thu, Dec 05, 2019 at 10:26:34AM +0000, Richard Sandiford wrote:
> 2019-12-05  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	PR middle-end/92768
> 	* tree-core.h (OEP_BITWISE): New flag.
> 	* fold-const.c (operand_compare::operand_equal_p): Handle it.
> 	* tree-vector-builder.h (tree_vector_builder::equal_p): Pass it.
> 
> gcc/testsuite/
> 	PR middle-end/92768
> 	* gcc.dg/pr92768.c: New test.

This test FAILs on i686-linux:
FAIL: gcc.dg/pr92768.c (test for excess errors)
Excess errors:
/home/jakub/src/gcc/gcc/testsuite/gcc.dg/pr92768.c:4:1: warning: SSE vector return without SSE enabled changes the ABI [-Wpsabi]
Similarly to other tests, I've added -w -Wno-psabi to disable such warnings,
different targets have different and not all have it under -Wno-psabi.
Tested on x86_64-linux and i686-linux, committed to trunk as obvious:

2019-12-06  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/92768
	* gcc.dg/pr92768.c: Add -w -Wno-psabi to dg-options.

--- gcc/testsuite/gcc.dg/pr92768.c.jj	2019-12-06 00:40:41.033681697 +0100
+++ gcc/testsuite/gcc.dg/pr92768.c	2019-12-06 00:51:57.503480293 +0100
@@ -1,4 +1,5 @@
-/* { dg-options "-O2 -fno-signed-zeros -fdump-tree-optimized" } */
+/* PR tree-optimization/92768 */
+/* { dg-options "-O2 -fno-signed-zeros -fdump-tree-optimized -w -Wno-psabi" } */
 
 typedef float v4sf __attribute__((vector_size(16)));
 v4sf f () { return (v4sf) { 0.0, -0.0, 0.0, -0.0 }; }


	Jakub
diff mbox series

Patch

Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h	2019-11-29 13:04:14.458669072 +0000
+++ gcc/tree-core.h	2019-12-05 10:25:10.660172853 +0000
@@ -881,7 +881,8 @@  enum operand_equal_flag {
   /* Internal within inchash::add_expr:  */
   OEP_HASH_CHECK = 32,
   /* Makes operand_equal_p handle more expressions:  */
-  OEP_LEXICOGRAPHIC = 64
+  OEP_LEXICOGRAPHIC = 64,
+  OEP_BITWISE = 128
 };
 
 /* Enum and arrays used for tree allocation stats.
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	2019-12-04 13:14:12.222218581 +0000
+++ gcc/fold-const.c	2019-12-05 10:25:10.656172882 +0000
@@ -2938,6 +2938,11 @@  combine_comparisons (location_t loc,
    If OEP_LEXICOGRAPHIC is set, then also handle expressions with side-effects
    such as MODIFY_EXPR, RETURN_EXPR, as well as STATEMENT_LISTs.
 
+   If OEP_BITWISE is set, then require the values to be bitwise identical
+   rather than simply numerically equal.  Do not take advantage of things
+   like math-related flags or undefined behavior; only return true for
+   values that are provably bitwise identical in all circumstances.
+
    Unless OEP_MATCH_SIDE_EFFECTS is set, the function returns false on
    any operand with side effect.  This is unnecesarily conservative in the
    case we know that arg0 and arg1 are in disjoint code paths (such as in
@@ -2967,6 +2972,11 @@  operand_compare::operand_equal_p (const_
   if (!TREE_TYPE (arg0) || !TREE_TYPE (arg1))
     return false;
 
+  /* Bitwise identity makes no sense if the values have different layouts.  */
+  if ((flags & OEP_BITWISE)
+      && !tree_nop_conversion_p (TREE_TYPE (arg0), TREE_TYPE (arg1)))
+    return false;
+
   /* We cannot consider pointers to different address space equal.  */
   if (POINTER_TYPE_P (TREE_TYPE (arg0))
       && POINTER_TYPE_P (TREE_TYPE (arg1))
@@ -3099,8 +3109,7 @@  operand_compare::operand_equal_p (const_
 	if (real_identical (&TREE_REAL_CST (arg0), &TREE_REAL_CST (arg1)))
 	  return true;
 
-
-	if (!HONOR_SIGNED_ZEROS (arg0))
+	if (!(flags & OEP_BITWISE) && !HONOR_SIGNED_ZEROS (arg0))
 	  {
 	    /* If we do not distinguish between signed and unsigned zero,
 	       consider them equal.  */
@@ -3152,7 +3161,9 @@  operand_compare::operand_equal_p (const_
 	break;
       }
 
-  if (flags & OEP_ONLY_CONST)
+  /* Don't handle more cases for OEP_BITWISE, since we can't guarantee that
+     two instances of undefined behavior will give identical results.  */
+  if (flags & (OEP_ONLY_CONST | OEP_BITWISE))
     return false;
 
 /* Define macros to test an operand from arg0 and arg1 for equality and a
Index: gcc/tree-vector-builder.h
===================================================================
--- gcc/tree-vector-builder.h	2019-07-29 09:40:10.142001362 +0100
+++ gcc/tree-vector-builder.h	2019-12-05 10:25:10.660172853 +0000
@@ -88,7 +88,7 @@  tree_vector_builder::new_vector (tree ty
 inline bool
 tree_vector_builder::equal_p (const_tree elt1, const_tree elt2) const
 {
-  return operand_equal_p (elt1, elt2, 0);
+  return operand_equal_p (elt1, elt2, OEP_BITWISE);
 }
 
 /* Return true if a stepped representation is OK.  We don't allow
Index: gcc/testsuite/gcc.dg/pr92768.c
===================================================================
--- /dev/null	2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/gcc.dg/pr92768.c	2019-12-05 10:25:10.660172853 +0000
@@ -0,0 +1,6 @@ 
+/* { dg-options "-O2 -fno-signed-zeros -fdump-tree-optimized" } */
+
+typedef float v4sf __attribute__((vector_size(16)));
+v4sf f () { return (v4sf) { 0.0, -0.0, 0.0, -0.0 }; }
+
+/* { dg-final { scan-tree-dump {{ 0\.0, -0\.0, 0\.0, -0\.0 }} "optimized" } } */