From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id A5D873856947; Mon, 29 Aug 2022 15:33:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A5D873856947 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1661787214; bh=Bst8WZib0P7Vvu20knb5jjzDIaPV7lH62g0agf7Iyvc=; h=From:To:Subject:Date:From; b=iZytq5QYRjuQuErkfkZXUO0zyCbpGwGIA6YvLkTS+qZAloIgQTkY6D0a0aqGR5NxI gBDuBk+HXdoJ7kiacN3UpFlpgTzaowAKIas0TXLuf0HXrkLYOTYeAISSdCaE2bpWeO RzRGecySZ6z93lGaakJSBB3OVnCGO5YLrCRQfxaI= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] gccrs constant folding port: ports over - more cases into constexpr_expression. - cxx_eval_condtiona X-Act-Checkin: gcc X-Git-Author: Faisal Abbas <90.abbasfaisal@gmail.com> X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: d4e80fd645a9b4cac48957283e820f23d6e18aab X-Git-Newrev: 17663caca44a5be8fd9d9de7eab3190c40bc594a Message-Id: <20220829153334.A5D873856947@sourceware.org> Date: Mon, 29 Aug 2022 15:33:34 +0000 (GMT) List-Id: https://gcc.gnu.org/g:17663caca44a5be8fd9d9de7eab3190c40bc594a commit 17663caca44a5be8fd9d9de7eab3190c40bc594a Author: Faisal Abbas <90.abbasfaisal@gmail.com> Date: Thu Jul 28 17:06:53 2022 +0100 gccrs constant folding port: ports over - more cases into constexpr_expression. - cxx_eval_condtional_expression. Note that COND_EXPR and IF_STMT are defined in cp-tree.def Also renames constexpr_expression to eval_constant_expression. Signed-off-by: Faisal Abbas <90.abbasfaisal@gmail.com> Diff: --- gcc/rust/backend/rust-constexpr.cc | 161 ++++++++++++++++++++++++++++--------- 1 file changed, 125 insertions(+), 36 deletions(-) diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index fef1de8dcf5..6c3fedffc51 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -332,8 +332,8 @@ uid_sensitive_constexpr_evaluation_checker::evaluation_restricted_p () const static GTY (()) hash_table *constexpr_call_table; static tree -cxx_eval_constant_expression (const constexpr_ctx *, tree, bool, bool *, bool *, - tree * = NULL); +constexp_expression (const constexpr_ctx *, tree, bool, bool *, bool *, + tree * = NULL); /* Compute a hash value for a constexpr call representation. */ @@ -459,8 +459,8 @@ static void non_const_var_error (location_t loc, tree r); static tree -constexpr_expression (const constexpr_ctx *ctx, tree, bool, bool *, bool *, - tree * = NULL); +eval_constant_expression (const constexpr_ctx *ctx, tree, bool, bool *, bool *, + tree * = NULL); static tree constexpr_fn_retval (const constexpr_ctx *ctx, tree r); @@ -483,6 +483,11 @@ eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p, static tree extract_string_elt (tree string, unsigned chars_per_elt, unsigned index); +static tree +eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, + bool *non_constant_p, bool *overflow_p, + tree *jump_target); + /* Variables and functions to manage constexpr call expansion context. These do not need to be marked for PCH or GC. */ @@ -543,8 +548,8 @@ fold_expr (tree expr) bool non_constant_p = false; bool overflow_p = false; - tree folded - = constexpr_expression (&ctx, expr, false, &non_constant_p, &overflow_p); + tree folded = eval_constant_expression (&ctx, expr, false, &non_constant_p, + &overflow_p); rust_assert (folded != NULL_TREE); // more logic here to possibly port @@ -553,9 +558,9 @@ fold_expr (tree expr) } static tree -constexpr_expression (const constexpr_ctx *ctx, tree t, bool lval, - bool *non_constant_p, bool *overflow_p, - tree *jump_target /* = NULL */) +eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, + bool *non_constant_p, bool *overflow_p, + tree *jump_target /* = NULL */) { location_t loc = EXPR_LOCATION (t); @@ -671,8 +676,8 @@ constexpr_expression (const constexpr_ctx *ctx, tree t, bool lval, case RETURN_EXPR: rust_assert (TREE_OPERAND (t, 0) != NULL_TREE); - r = constexpr_expression (ctx, TREE_OPERAND (t, 0), false, non_constant_p, - overflow_p); + r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, + non_constant_p, overflow_p); break; case MODIFY_EXPR: @@ -686,8 +691,8 @@ constexpr_expression (const constexpr_ctx *ctx, tree t, bool lval, jump_target); case BIND_EXPR: - return constexpr_expression (ctx, BIND_EXPR_BODY (t), lval, - non_constant_p, overflow_p, jump_target); + return eval_constant_expression (ctx, BIND_EXPR_BODY (t), lval, + non_constant_p, overflow_p, jump_target); case RESULT_DECL: if (lval) @@ -711,8 +716,8 @@ constexpr_expression (const constexpr_ctx *ctx, tree t, bool lval, r = *p; else { - r = constexpr_expression (ctx, TREE_OPERAND (t, 0), false, - non_constant_p, overflow_p); + r = eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, + non_constant_p, overflow_p); if (*non_constant_p) break; ctx->global->values.put (t, r); @@ -721,6 +726,45 @@ constexpr_expression (const constexpr_ctx *ctx, tree t, bool lval, } break; + case COND_EXPR: + case IF_STMT: + if (jump_target && *jump_target) + { + tree orig_jump = *jump_target; + tree arg = ((TREE_CODE (t) != IF_STMT || TREE_OPERAND (t, 1)) + ? TREE_OPERAND (t, 1) + : void_node); + /* When jumping to a label, the label might be either in the + then or else blocks, so process then block first in skipping + mode first, and if we are still in the skipping mode at its end, + process the else block too. */ + r = eval_constant_expression (ctx, arg, lval, non_constant_p, + overflow_p, jump_target); + /* It's possible that we found the label in the then block. But + it could have been followed by another jumping statement, e.g. + say we're looking for case 1: + if (cond) + { + // skipped statements + case 1:; // clears up *jump_target + return 1; // and sets it to a RETURN_EXPR + } + else { ... } + in which case we need not go looking to the else block. + (goto is not allowed in a constexpr function.) */ + if (*jump_target == orig_jump) + { + arg = ((TREE_CODE (t) != IF_STMT || TREE_OPERAND (t, 2)) + ? TREE_OPERAND (t, 2) + : void_node); + r = eval_constant_expression (ctx, arg, lval, non_constant_p, + overflow_p, jump_target); + } + break; + } + r = eval_conditional_expression (ctx, t, lval, non_constant_p, overflow_p, + jump_target); + break; default: break; } @@ -890,8 +934,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, stored in, so that any side-effects happen first. */ if (!SCALAR_TYPE_P (type)) new_ctx.ctor = new_ctx.object = NULL_TREE; - init = constexpr_expression (&new_ctx, init, false, non_constant_p, - overflow_p); + init = eval_constant_expression (&new_ctx, init, false, non_constant_p, + overflow_p); if (*non_constant_p) return t; } @@ -902,8 +946,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, /* If we want to return a reference to the target, we need to evaluate it as a whole; otherwise, only evaluate the innermost piece to avoid building up unnecessary *_REFs. */ - target - = constexpr_expression (ctx, target, true, non_constant_p, overflow_p); + target = eval_constant_expression (ctx, target, true, non_constant_p, + overflow_p); evaluated = true; if (*non_constant_p) return t; @@ -955,8 +999,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, object = probe; else { - probe = constexpr_expression (ctx, probe, true, non_constant_p, - overflow_p); + probe = eval_constant_expression (ctx, probe, true, + non_constant_p, overflow_p); evaluated = true; if (*non_constant_p) return t; @@ -1146,8 +1190,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, if (TREE_CODE (init) == TARGET_EXPR) if (tree tinit = TARGET_EXPR_INITIAL (init)) init = tinit; - init = constexpr_expression (&new_ctx, init, false, non_constant_p, - overflow_p); + init = eval_constant_expression (&new_ctx, init, false, non_constant_p, + overflow_p); /* The hash table might have moved since the get earlier, and the initializer might have mutated the underlying CONSTRUCTORs, so we must recompute VALP. */ @@ -1250,8 +1294,10 @@ eval_binary_expression (const constexpr_ctx *ctx, tree t, bool lval, tree orig_rhs = TREE_OPERAND (t, 1); tree lhs, rhs; - lhs = constexpr_expression (ctx, orig_lhs, lval, non_constant_p, overflow_p); - rhs = constexpr_expression (ctx, orig_rhs, lval, non_constant_p, overflow_p); + lhs = eval_constant_expression (ctx, orig_lhs, lval, non_constant_p, + overflow_p); + rhs = eval_constant_expression (ctx, orig_rhs, lval, non_constant_p, + overflow_p); location_t loc = EXPR_LOCATION (t); enum tree_code code = TREE_CODE (t); @@ -1333,8 +1379,8 @@ rs_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun, /* Normally we would strip a TARGET_EXPR in an initialization context such as this, but here we do the elision differently: we keep the TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */ - arg = constexpr_expression (ctx, x, /*lval=*/false, non_constant_p, - overflow_p); + arg = eval_constant_expression (ctx, x, /*lval=*/false, non_constant_p, + overflow_p); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p && ctx->quiet) break; @@ -1604,8 +1650,8 @@ eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval, unsigned save_heap_dealloc_count = ctx->global->heap_dealloc_count; tree jump_target = NULL_TREE; - constexpr_expression (&ctx_with_save_exprs, body, lval, - non_constant_p, overflow_p, &jump_target); + eval_constant_expression (&ctx_with_save_exprs, body, lval, + non_constant_p, overflow_p, &jump_target); if (VOID_TYPE_P (TREE_TYPE (res))) result = void_node; @@ -1712,8 +1758,8 @@ constexpr_fn_retval (const constexpr_ctx *ctx, tree body) case RETURN_EXPR: { bool non_constant_p = false; bool overflow_p = false; - return constexpr_expression (ctx, body, false, &non_constant_p, - &overflow_p); + return eval_constant_expression (ctx, body, false, &non_constant_p, + &overflow_p); } case DECL_EXPR: { tree decl = DECL_EXPR_DECL (body); @@ -2328,7 +2374,8 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type, gcc_unreachable (); /* For VLAs, the number of elements won't be an integer constant. */ - nelts = constexpr_expression (ctx, nelts, false, non_constant_p, overflow_p); + nelts + = eval_constant_expression (ctx, nelts, false, non_constant_p, overflow_p); return nelts; } @@ -2345,8 +2392,8 @@ eval_and_check_array_index (const constexpr_ctx *ctx, tree t, location_t loc = rs_expr_loc_or_input_loc (t); tree ary = TREE_OPERAND (t, 0); t = TREE_OPERAND (t, 1); - tree index - = constexpr_expression (ctx, t, allow_one_past, non_constant_p, overflow_p); + tree index = eval_constant_expression (ctx, t, allow_one_past, non_constant_p, + overflow_p); VERIFY_CONSTANT (index); if (!tree_fits_shwi_p (index) || tree_int_cst_sgn (index) < 0) @@ -2561,8 +2608,8 @@ eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p, // } if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT) continue; - r = constexpr_expression (ctx, stmt, false, non_constant_p, overflow_p, - jump_target); + r = eval_constant_expression (ctx, stmt, false, non_constant_p, + overflow_p, jump_target); if (*non_constant_p) break; // FIXME @@ -2580,6 +2627,48 @@ eval_statement_list (const constexpr_ctx *ctx, tree t, bool *non_constant_p, return r; } +// forked from gcc/cp/constexpr.cc cxx_eval_conditional_expression + +/* Subroutine of cxx_eval_constant_expression. + Attempt to evaluate condition expressions. Dead branches are not + looked into. */ + +static tree +eval_conditional_expression (const constexpr_ctx *ctx, tree t, bool lval, + bool *non_constant_p, bool *overflow_p, + tree *jump_target) +{ + tree val + = eval_constant_expression (ctx, TREE_OPERAND (t, 0), + /*lval*/ false, non_constant_p, overflow_p); + VERIFY_CONSTANT (val); + if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t)) + { + /* Evaluate the condition as if it was + if (__builtin_is_constant_evaluated ()), i.e. defer it if not + ctx->manifestly_const_eval (as sometimes we try to constant evaluate + without manifestly_const_eval even expressions or parts thereof which + will later be manifestly const_eval evaluated), otherwise fold it to + true. */ + if (ctx->manifestly_const_eval) + val = boolean_true_node; + else + { + *non_constant_p = true; + return t; + } + } + /* Don't VERIFY_CONSTANT the other operands. */ + if (integer_zerop (val)) + val = TREE_OPERAND (t, 2); + else + val = TREE_OPERAND (t, 1); + if (TREE_CODE (t) == IF_STMT && !val) + val = void_node; + return eval_constant_expression (ctx, val, lval, non_constant_p, overflow_p, + jump_target); +} + // #include "gt-rust-rust-constexpr.h" } // namespace Compile