Hi!

As the following testcases show, fold_builtin_expect replaces
__builtin_expect (x && y, z) with
__builtin_expect (x, z) && __builtin_expect (y, z)
and similarly for || instead of &&.  It does so without any kind of
copying of the z argument, which means if it is e.g. statement expression
without side-effects we try to destructively gimplify it multiple times
and ICE the second time we do so.  Or, as the other testcase shows,
if there are any side-effects in that argument, we evaluate them multiple
times.

Fixed by doing save_expr on that argument first.  arg2 doesn't need it,
as it is provided only internally from the compiler and is always
INTEGER_CST or NULL, nothing else.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-04-03  Jakub Jelinek  <ja...@redhat.com>

        PR tree-optimization/85156
        * builtins.c (fold_builtin_expect): Use save_expr on arg1 to avoid
        evaluating the argument multiple times.

        * c-c++-common/pr85156.c: New test.
        * gcc.c-torture/execute/pr85156.c: New test.

--- gcc/builtins.c.jj   2018-04-01 08:03:09.786562444 +0200
+++ gcc/builtins.c      2018-04-03 12:03:53.673566330 +0200
@@ -7998,6 +7998,7 @@ fold_builtin_expect (location_t loc, tre
     {
       tree op0 = TREE_OPERAND (inner, 0);
       tree op1 = TREE_OPERAND (inner, 1);
+      arg1 = save_expr (arg1);
 
       op0 = build_builtin_expect_predicate (loc, op0, arg1, arg2);
       op1 = build_builtin_expect_predicate (loc, op1, arg1, arg2);
--- gcc/testsuite/c-c++-common/pr85156.c.jj     2018-04-03 12:06:53.056572306 
+0200
+++ gcc/testsuite/c-c++-common/pr85156.c        2018-04-03 12:07:34.557573689 
+0200
@@ -0,0 +1,11 @@
+/* PR tree-optimization/85156 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -g" } */
+
+int a, b;
+
+int
+foo (void)
+{
+  return __builtin_expect (a ? b != 0 : 0, ({ 1; }));
+}
--- gcc/testsuite/gcc.c-torture/execute/pr85156.c.jj    2018-04-03 
12:09:34.095577676 +0200
+++ gcc/testsuite/gcc.c-torture/execute/pr85156.c       2018-04-03 
12:09:20.886577235 +0200
@@ -0,0 +1,21 @@
+/* PR tree-optimization/85156 */
+
+int x, y;
+
+__attribute__((noipa)) int
+foo (int z)
+{
+  if (__builtin_expect (x ? y != 0 : 0, z++))
+    return 7;
+  return z;
+}
+
+int
+main ()
+{
+  x = 1;
+  asm volatile ("" : "+m" (x), "+m" (y));
+  if (foo (10) != 11)
+    __builtin_abort ();
+  return 0;
+}

        Jakub

Reply via email to