public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] gccrs constant folding port: ports over - more cases into constexpr_expression. - cxx_eval_condtiona
@ 2022-08-29 15:33 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-08-29 15:33 UTC (permalink / raw)
  To: gcc-cvs

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_hasher> *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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-08-29 15:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-29 15:33 [gcc/devel/rust/master] gccrs constant folding port: ports over - more cases into constexpr_expression. - cxx_eval_condtiona Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).