https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118068

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason at gcc dot gnu.org

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Marek/Jason, what do you think about doing cp_walk_tree with
cp_fold_immediate_r callback from cp_fold_function and cp_fully_fold_init?

Though, tried
--- gcc/cp/cp-gimplify.cc.jj    2025-02-01 00:47:07.881079292 +0100
+++ gcc/cp/cp-gimplify.cc       2025-03-06 15:31:11.713951494 +0100
@@ -1204,7 +1204,8 @@ cp_build_init_expr_for_ctor (tree call,
   return init;
 }

-/* A subroutine of cp_fold_r to handle immediate functions.  */
+/* A walk_tree callback for cp_fold_function and cp_fully_fold_init to handle
+   immediate functions.  */

 static tree
 cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_)
@@ -1370,45 +1371,8 @@ cp_fold_r (tree *stmt_p, int *walk_subtr
   tree stmt = *stmt_p;
   enum tree_code code = TREE_CODE (stmt);

-  if (cxx_dialect >= cxx20)
-    {
-      /* Unfortunately we must handle code like
-          false ? bar () : 42
-        where we have to check bar too.  The cp_fold call below could
-        fold the ?: into a constant before we've checked it.  */
-      if (code == COND_EXPR)
-       {
-         auto then_fn = cp_fold_r, else_fn = cp_fold_r;
-         /* See if we can figure out if either of the branches is dead.  If it
-            is, we don't need to do everything that cp_fold_r does.  */
-         cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_fold_r, data, nullptr);
-         if (integer_zerop (TREE_OPERAND (stmt, 0)))
-           then_fn = cp_fold_immediate_r;
-         else if (integer_nonzerop (TREE_OPERAND (stmt, 0)))
-           else_fn = cp_fold_immediate_r;
-
-         if (TREE_OPERAND (stmt, 1))
-           cp_walk_tree (&TREE_OPERAND (stmt, 1), then_fn, data,
-                         nullptr);
-         if (TREE_OPERAND (stmt, 2))
-           cp_walk_tree (&TREE_OPERAND (stmt, 2), else_fn, data,
-                         nullptr);
-         *walk_subtrees = 0;
-         /* Don't return yet, still need the cp_fold below.  */
-       }
-      else
-       cp_fold_immediate_r (stmt_p, walk_subtrees, data);
-    }
-
   *stmt_p = stmt = cp_fold (*stmt_p, data->flags);

-  /* For certain trees, like +foo(), the cp_fold above will remove the +,
-     and the subsequent tree walk would go straight down to the CALL_EXPR's
-     operands, meaning that cp_fold_immediate_r would never see the
-     CALL_EXPR.  Ew :(.  */
-  if (TREE_CODE (stmt) == CALL_EXPR && code != CALL_EXPR)
-    cp_fold_immediate_r (stmt_p, walk_subtrees, data);
-
   if (data->pset.add (stmt))
     {
       /* Don't walk subtrees of stmts we've already walked once, otherwise
@@ -1537,6 +1501,13 @@ cp_fold_function (tree fndecl)
      been constant-evaluated already if possible, so we can safely
      pass ff_mce_false.  */
   cp_fold_data data (ff_genericize | ff_mce_false);
+  /* Do cp_fold_immediate_r in separate whole IL walk instead of during
+     cp_fold_r, as otherwise expressions using results of immediate functions
+     might not be folded as cp_fold is called on those before cp_fold_r is
+     called on their argument.  And calling cp_fold_immediate_r during
+     cp_fold can mean evaluation of the immediate functions many times.  */
+  if (cxx_dialect >= cxx20)
+    cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_immediate_r, &data,
NULL);
   cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, &data, NULL);

   /* This is merely an optimization: if FNDECL has no i-e expressions,
@@ -2910,6 +2881,8 @@ cp_fully_fold_init (tree x)
     return x;
   x = cp_fully_fold (x, mce_false);
   cp_fold_data data (ff_mce_false);
+  if (cxx_dialect >= cxx20)
+    cp_walk_tree (&x, cp_fold_immediate_r, &data, NULL);
   cp_walk_tree (&x, cp_fold_r, &data, NULL);
   return x;
 }
--- gcc/testsuite/g++.target/i386/pr118068.C.jj 2025-03-06 15:25:59.849944651
+0100
+++ gcc/testsuite/g++.target/i386/pr118068.C    2025-03-06 15:25:51.152064565
+0100
@@ -0,0 +1,17 @@
+// PR target/118068
+// { dg-do compile { target c++20 } }
+// { dg-options "-O0 -mavx" }
+
+typedef float V __attribute__((vector_size (32)));
+
+consteval unsigned char
+foo (int x)
+{
+  return x;
+}
+
+V
+bar (V x, V y)
+{
+  return __builtin_ia32_blendps256 (x, y, (int) foo (0x23));
+}

and so far saw
FAIL: g++.dg/cpp23/consteval-if1.C  -std=gnu++20 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if1.C  -std=gnu++23 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if1.C  -std=gnu++26 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if10.C  -std=gnu++20 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if10.C  -std=gnu++23 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if10.C  -std=gnu++26 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if11.C  -std=gnu++20 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if11.C  -std=gnu++23 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if11.C  -std=gnu++26 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if13.C  -std=c++23 (test for excess errors)
FAIL: g++.dg/cpp23/consteval-if13.C  -std=c++26 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop15.C  -std=gnu++20 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop15.C  -std=gnu++23 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop15.C  -std=gnu++26 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop8.C  -std=gnu++20 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop17.C  -std=gnu++20 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop8.C  -std=gnu++23 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop1.C  -std=c++20 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop17.C  -std=gnu++23 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop8.C  -std=gnu++26 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop17.C  -std=gnu++26 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop1.C  -std=c++23 (test for excess errors)
FAIL: g++.dg/cpp2a/consteval-prop1.C  -std=c++26 (test for excess errors)
regressions.

Reply via email to