match.pd: Disallow side-effects in GENERIC for non-COND_EXPR to COND_EXPR simplifications [PR93744]

Message ID 20200215060951.GA2155@tucnak
State New
Headers show
Series
  • match.pd: Disallow side-effects in GENERIC for non-COND_EXPR to COND_EXPR simplifications [PR93744]
Related show

Commit Message

Jakub Jelinek Feb. 15, 2020, 6:09 a.m.
Hi!

As the following testcases show (the first one reported, last two
found by code inspection), we need to disallow side-effects
in simplifications that turn some unconditional expression into conditional
one.  From my little understanding of genmatch.c, it is able to
automatically disallow side effects if the same operand is used multiple
times in the match pattern, maybe if it is used multiple times in the
replacement pattern, and if it is used in conditional contexts in the match
pattern, could it be taught to handle this case too?  If yes, perhaps
just the first hunk could be usable for 8/9 backports (+ the testcases).

Bootstrapped/regtested on x86_64-linux and i686-linux.

2020-02-15  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/93744
	* match.pd (((m1 >/</>=/<= m2) * d -> (m1 >/</>=/<= m2) ? d : 0,
	A - ((A - B) & -(C cmp D)) -> (C cmp D) ? B : A,
	A + ((B - A) & -(C cmp D)) -> (C cmp D) ? B : A): For GENERIC, make
	sure @2 in the first and @1 in the other patterns has no side-effects.

	* gcc.c-torture/execute/pr93744-1.c: New test.
	* gcc.c-torture/execute/pr93744-2.c: New test.
	* gcc.c-torture/execute/pr93744-3.c: New test.


	Jakub

Comments

Richard Biener Feb. 15, 2020, 11 a.m. | #1
On February 15, 2020 7:09:51 AM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!

>

>As the following testcases show (the first one reported, last two

>found by code inspection), we need to disallow side-effects

>in simplifications that turn some unconditional expression into

>conditional

>one.  From my little understanding of genmatch.c, it is able to

>automatically disallow side effects if the same operand is used

>multiple

>times in the match pattern, maybe if it is used multiple times in the

>replacement pattern, and if it is used in conditional contexts in the

>match

>pattern, could it be taught to handle this case too?  If yes, perhaps

>just the first hunk could be usable for 8/9 backports (+ the

>testcases).


It could possibly be done but then it's only three cases so far. 

OK. 

Richard. 

>Bootstrapped/regtested on x86_64-linux and i686-linux.

>

>2020-02-15  Jakub Jelinek  <jakub@redhat.com>

>

>	PR tree-optimization/93744

>	* match.pd (((m1 >/</>=/<= m2) * d -> (m1 >/</>=/<= m2) ? d : 0,

>	A - ((A - B) & -(C cmp D)) -> (C cmp D) ? B : A,

>	A + ((B - A) & -(C cmp D)) -> (C cmp D) ? B : A): For GENERIC, make

>	sure @2 in the first and @1 in the other patterns has no side-effects.

>

>	* gcc.c-torture/execute/pr93744-1.c: New test.

>	* gcc.c-torture/execute/pr93744-2.c: New test.

>	* gcc.c-torture/execute/pr93744-3.c: New test.

>

>--- gcc/match.pd.jj	2020-02-05 11:12:33.679383217 +0100

>+++ gcc/match.pd	2020-02-14 22:49:22.858771394 +0100

>@@ -1472,7 +1472,8 @@ (define_operator_list COND_TERNARY

> (for cmp (gt lt ge le)

> (simplify

>  (mult (convert (cmp @0 @1)) @2)

>-  (cond (cmp @0 @1) @2 { build_zero_cst (type); })))

>+  (if (GIMPLE || !TREE_SIDE_EFFECTS (@2))

>+   (cond (cmp @0 @1) @2 { build_zero_cst (type); }))))

> 

> /* For integral types with undefined overflow and C != 0 fold

>    x * C EQ/NE y * C into x EQ/NE y.  */

>@@ -2709,7 +2710,8 @@ (define_operator_list COND_TERNARY

>        && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE

>        && INTEGRAL_TYPE_P (TREE_TYPE (@5))

>        && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)

>-	   || !TYPE_UNSIGNED (TREE_TYPE (@4))))

>+	   || !TYPE_UNSIGNED (TREE_TYPE (@4)))

>+       && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))

>    (cond (cmp @2 @3) @1 @0)))

>  (simplify

>   (plus:c @0 (bit_and:c (minus @1 @0)

>@@ -2719,7 +2721,8 @@ (define_operator_list COND_TERNARY

>        && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE

>        && INTEGRAL_TYPE_P (TREE_TYPE (@5))

>        && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)

>-	   || !TYPE_UNSIGNED (TREE_TYPE (@4))))

>+	   || !TYPE_UNSIGNED (TREE_TYPE (@4)))

>+       && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))

>    (cond (cmp @2 @3) @1 @0))))

> 

> /* Simplifications of shift and rotates.  */

>--- gcc/testsuite/gcc.c-torture/execute/pr93744-1.c.jj	2020-02-14

>22:50:58.993346192 +0100

>+++ gcc/testsuite/gcc.c-torture/execute/pr93744-1.c	2020-02-14

>22:49:57.934251395 +0100

>@@ -0,0 +1,14 @@

>+/* PR tree-optimization/93744 */

>+

>+typedef int I;

>+

>+int

>+main ()

>+{

>+  int a = 0;

>+  I b = 0;

>+  (a > 0) * (b |= 2);

>+  if (b != 2)

>+    __builtin_abort ();

>+  return 0;

>+}

>--- gcc/testsuite/gcc.c-torture/execute/pr93744-2.c.jj	2020-02-14

>22:51:01.100314955 +0100

>+++ gcc/testsuite/gcc.c-torture/execute/pr93744-2.c	2020-02-14

>22:50:18.299949478 +0100

>@@ -0,0 +1,21 @@

>+/* PR tree-optimization/93744 */

>+

>+int w;

>+

>+int

>+foo (int x, int y, int z)

>+{

>+  int r = z - ((z - w++) & -(x < y));

>+  return r;

>+}

>+

>+int

>+main ()

>+{

>+  w = 4;

>+  if (foo (5, 7, 12) != 4 || w != 5)

>+    __builtin_abort ();

>+  if (foo (7, 5, 12) != 12 || w != 6)

>+    __builtin_abort ();

>+  return 0;

>+}

>--- gcc/testsuite/gcc.c-torture/execute/pr93744-3.c.jj	2020-02-14

>22:51:03.415280636 +0100

>+++ gcc/testsuite/gcc.c-torture/execute/pr93744-3.c	2020-02-14

>22:50:25.820837971 +0100

>@@ -0,0 +1,21 @@

>+/* PR tree-optimization/93744 */

>+

>+int w;

>+

>+int

>+foo (int x, int y, int z)

>+{

>+  int r = z + ((w++ - z) & -(x < y));

>+  return r;

>+}

>+

>+int

>+main ()

>+{

>+  w = 4;

>+  if (foo (5, 7, 12) != 4 || w != 5)

>+    __builtin_abort ();

>+  if (foo (7, 5, 12) != 12 || w != 6)

>+    __builtin_abort ();

>+  return 0;

>+}

>

>	Jakub

Patch

--- gcc/match.pd.jj	2020-02-05 11:12:33.679383217 +0100
+++ gcc/match.pd	2020-02-14 22:49:22.858771394 +0100
@@ -1472,7 +1472,8 @@  (define_operator_list COND_TERNARY
 (for cmp (gt lt ge le)
 (simplify
  (mult (convert (cmp @0 @1)) @2)
-  (cond (cmp @0 @1) @2 { build_zero_cst (type); })))
+  (if (GIMPLE || !TREE_SIDE_EFFECTS (@2))
+   (cond (cmp @0 @1) @2 { build_zero_cst (type); }))))
 
 /* For integral types with undefined overflow and C != 0 fold
    x * C EQ/NE y * C into x EQ/NE y.  */
@@ -2709,7 +2710,8 @@  (define_operator_list COND_TERNARY
        && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE
        && INTEGRAL_TYPE_P (TREE_TYPE (@5))
        && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)
-	   || !TYPE_UNSIGNED (TREE_TYPE (@4))))
+	   || !TYPE_UNSIGNED (TREE_TYPE (@4)))
+       && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
    (cond (cmp @2 @3) @1 @0)))
  (simplify
   (plus:c @0 (bit_and:c (minus @1 @0)
@@ -2719,7 +2721,8 @@  (define_operator_list COND_TERNARY
        && TREE_CODE (TREE_TYPE (@4)) != BOOLEAN_TYPE
        && INTEGRAL_TYPE_P (TREE_TYPE (@5))
        && (TYPE_PRECISION (TREE_TYPE (@4)) >= TYPE_PRECISION (type)
-	   || !TYPE_UNSIGNED (TREE_TYPE (@4))))
+	   || !TYPE_UNSIGNED (TREE_TYPE (@4)))
+       && (GIMPLE || !TREE_SIDE_EFFECTS (@1)))
    (cond (cmp @2 @3) @1 @0))))
 
 /* Simplifications of shift and rotates.  */
--- gcc/testsuite/gcc.c-torture/execute/pr93744-1.c.jj	2020-02-14 22:50:58.993346192 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr93744-1.c	2020-02-14 22:49:57.934251395 +0100
@@ -0,0 +1,14 @@ 
+/* PR tree-optimization/93744 */
+
+typedef int I;
+
+int
+main ()
+{
+  int a = 0;
+  I b = 0;
+  (a > 0) * (b |= 2);
+  if (b != 2)
+    __builtin_abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.c-torture/execute/pr93744-2.c.jj	2020-02-14 22:51:01.100314955 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr93744-2.c	2020-02-14 22:50:18.299949478 +0100
@@ -0,0 +1,21 @@ 
+/* PR tree-optimization/93744 */
+
+int w;
+
+int
+foo (int x, int y, int z)
+{
+  int r = z - ((z - w++) & -(x < y));
+  return r;
+}
+
+int
+main ()
+{
+  w = 4;
+  if (foo (5, 7, 12) != 4 || w != 5)
+    __builtin_abort ();
+  if (foo (7, 5, 12) != 12 || w != 6)
+    __builtin_abort ();
+  return 0;
+}
--- gcc/testsuite/gcc.c-torture/execute/pr93744-3.c.jj	2020-02-14 22:51:03.415280636 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr93744-3.c	2020-02-14 22:50:25.820837971 +0100
@@ -0,0 +1,21 @@ 
+/* PR tree-optimization/93744 */
+
+int w;
+
+int
+foo (int x, int y, int z)
+{
+  int r = z + ((w++ - z) & -(x < y));
+  return r;
+}
+
+int
+main ()
+{
+  w = 4;
+  if (foo (5, 7, 12) != 4 || w != 5)
+    __builtin_abort ();
+  if (foo (7, 5, 12) != 12 || w != 6)
+    __builtin_abort ();
+  return 0;
+}