On Tue, Oct 07, 2025 at 10:50:50PM +0100, Jason Merrill wrote:
> Tested x86_64-pc-linux-gnu.  Jakub, does this make sense to you?

It makes sense, I'm just worried about if consteval having high cost
(mce_unknown evaluations being non-constant, so either then repeated
as mce_true or failing to be optimized if it is just an optimization).

I was thinking about something like (untested) where in your
patch then you'd set IF_STMT_CONSTEVAL_INTERNAL_P flag instead of
IF_STMT_CONSTEVAL_P (and perhaps put the internal into the name
of the fn too).

But up to you...

2025-10-08  Jakub Jelinek  <[email protected]>

        * cp-tree.h (IF_STMT_CONSTEVAL_INTERNAL_P): Define.
        * constexpr.cc (cxx_eval_conditional_expression): Handle
        IF_STMT_CONSTEVAL_INTERNAL_P.
        (potential_constant_expression_1): Likewise.
        * pt.cc (tsubst_stmt): Copy over IF_STMT_CONSTEVAL_INTERNAL_P flag.
        * cp-gimplify.cc (genericize_if_stmt, cp_fold_immediate_r, cp_fold_r):
        Handle IF_STMT_CONSTEVAL_INTERNAL_P.

--- gcc/cp/cp-tree.h.jj 2025-10-04 09:49:59.962565960 +0200
+++ gcc/cp/cp-tree.h    2025-10-08 10:20:22.334841983 +0200
@@ -522,6 +522,7 @@ extern GTY(()) tree cp_global_trees[CPTI
       LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, ENUMERAL_TYPE, 
NAMESPACE_DECL)
       FNDECL_MANIFESTLY_CONST_EVALUATED (in FUNCTION_DECL)
       TARGET_EXPR_INTERNAL_P (in TARGET_EXPR)
+      IF_STMT_CONSTEVAL_INTERNAL_P (in IF_STMT)
    5: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
       CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
@@ -5691,6 +5692,13 @@ decl_template_parm_check (const_tree t,
 /* True on artificial if (0) around .DEFERRED_INIT calls added for
    !!flag_auto_var_init.  */
 #define IF_STMT_VACUOUS_INIT_P(NODE) TREE_LANG_FLAG_3 (IF_STMT_CHECK (NODE))
+/* This is similar to IF_STMT_CONSTEVAL_P, except it evaluates condition
+   to true when both mce_true and mce_unknown instead of just for mce_true
+   and being non-constant for mce_unknown.  This is solely for internally
+   emitted IL where some form is preferrable for constant evaluation and
+   different for gimplification purposes.  */
+#define IF_STMT_CONSTEVAL_INTERNAL_P(NODE) \
+  TREE_LANG_FLAG_4 (IF_STMT_CHECK (NODE))
 
 /* Like PACK_EXPANSION_EXTRA_ARGS, for constexpr if.  IF_SCOPE is used while
    building an IF_STMT; IF_STMT_EXTRA_ARGS is used after it is complete.  */
--- gcc/cp/constexpr.cc.jj      2025-10-04 09:49:59.991565551 +0200
+++ gcc/cp/constexpr.cc 2025-10-08 10:24:27.990449168 +0200
@@ -4985,6 +4985,12 @@ cxx_eval_conditional_expression (const c
       val = constant_boolean_node (ctx->manifestly_const_eval == mce_true,
                                   boolean_type_node);
     }
+  else if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_INTERNAL_P (t))
+    /* Internal variant of if consteval {} else {}.  Uses the THEN block
+       for constant evaluation and ELSE block for genericization.  */
+    val = constant_boolean_node (ctx->manifestly_const_eval != mce_true,
+                                boolean_type_node);
+
   /* Don't VERIFY_CONSTANT the other operands.  */
   const bool zero_p = integer_zerop (val);
   if (zero_p)
@@ -12416,6 +12422,8 @@ potential_constant_expression_1 (tree t,
        return false;
       if (!processing_template_decl)
        tmp = cxx_eval_outermost_constant_expr (tmp, true);
+      if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_INTERNAL_P (t))
+       return RECUR (TREE_OPERAND (t, 1), want_rval);
       /* potential_constant_expression* isn't told if it is called for
         manifestly_const_eval or not, so for consteval if always
         process both branches as if the condition is not a known
--- gcc/cp/pt.cc.jj     2025-10-08 09:23:48.670696822 +0200
+++ gcc/cp/pt.cc        2025-10-08 10:25:03.551958015 +0200
@@ -19453,6 +19453,7 @@ tsubst_stmt (tree t, tree args, tsubst_f
       stmt = begin_if_stmt ();
       IF_STMT_CONSTEXPR_P (stmt) = IF_STMT_CONSTEXPR_P (t);
       IF_STMT_CONSTEVAL_P (stmt) = IF_STMT_CONSTEVAL_P (t);
+      IF_STMT_CONSTEVAL_INTERNAL_P (stmt) = IF_STMT_CONSTEVAL_INTERNAL_P (t);
       if (IF_STMT_CONSTEXPR_P (t))
        args = add_extra_args (IF_STMT_EXTRA_ARGS (t), args, complain, in_decl);
       {
--- gcc/cp/cp-gimplify.cc.jj    2025-10-04 09:50:00.028565029 +0200
+++ gcc/cp/cp-gimplify.cc       2025-10-08 10:26:34.356703887 +0200
@@ -236,7 +236,7 @@ genericize_if_stmt (tree *stmt_p)
      entered by gotos/case labels from elsewhere, and as then_ block
      can contain unfolded immediate function calls, we have to discard
      the then_ block regardless of whether else_ has side-effects or not.  */
-  if (IF_STMT_CONSTEVAL_P (stmt))
+  if (IF_STMT_CONSTEVAL_P (stmt) || IF_STMT_CONSTEVAL_INTERNAL_P (stmt))
     {
       if (block_may_fallthru (then_))
        stmt = build3 (COND_EXPR, void_type_node, boolean_false_node,
@@ -1332,7 +1332,7 @@ cp_fold_immediate_r (tree *stmt_p, int *
        decl = TREE_OPERAND (stmt, 0);
       break;
     case IF_STMT:
-      if (IF_STMT_CONSTEVAL_P (stmt))
+      if (IF_STMT_CONSTEVAL_P (stmt) || IF_STMT_CONSTEVAL_INTERNAL_P (stmt))
        {
          if (!data->pset.add (stmt))
            cp_walk_tree (&ELSE_CLAUSE (stmt), cp_fold_immediate_r, data_,
@@ -1530,7 +1530,7 @@ cp_fold_r (tree *stmt_p, int *walk_subtr
       return NULL_TREE;
 
     case IF_STMT:
-      if (IF_STMT_CONSTEVAL_P (stmt))
+      if (IF_STMT_CONSTEVAL_P (stmt) || IF_STMT_CONSTEVAL_INTERNAL_P (stmt))
        {
          /* Don't walk THEN_CLAUSE (stmt) for consteval if.  IF_COND is always
             boolean_false_node.  */


        Jakub

Reply via email to