https://gcc.gnu.org/g:09d39db7f1cc4caa4d58cc2b6a6ad56cb1280999

commit 09d39db7f1cc4caa4d58cc2b6a6ad56cb1280999
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Tue Mar 4 12:27:12 2025 +0100

    Sauvegarde gimple-exec

Diff:
---
 gcc/cgraphunit.cc | 337 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 240 insertions(+), 97 deletions(-)

diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 1bcf56daded8..dfeb89ab8194 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -2333,15 +2333,21 @@ class data_storage;
 static bool
 get_constant_type_size (tree type, unsigned &result)
 {
-  tree tree_size = TYPE_SIZE (type);
-  gcc_assert (TREE_CODE (tree_size) == INTEGER_CST);
-  wide_int wi_size = wi::to_wide (tree_size);
+  if (TREE_CODE (type) == INTEGER_TYPE
+      || TREE_CODE (type) == BOOLEAN_TYPE)
+    result = TYPE_PRECISION (type);
+  else
+    {
+      tree tree_size = TYPE_SIZE (type);
+      gcc_assert (TREE_CODE (tree_size) == INTEGER_CST);
+      wide_int wi_size = wi::to_wide (tree_size);
 
-  gcc_assert (wi::fits_uhwi_p (wi_size));
-  unsigned HOST_WIDE_INT hwi_size = wi_size.to_uhwi ();
+      gcc_assert (wi::fits_uhwi_p (wi_size));
+      unsigned HOST_WIDE_INT hwi_size = wi_size.to_uhwi ();
 
-  gcc_assert (hwi_size <= UINT_MAX);
-  result = hwi_size;
+      gcc_assert (hwi_size <= UINT_MAX);
+      result = hwi_size;
+    }
   return true;
 }
 
@@ -2398,8 +2404,8 @@ namespace selftest
   void context_printer_print_first_data_ref_part_tests ();
   void context_printer_print_value_update_tests ();
   void exec_context_evaluate_tests ();
-  void exec_context_evaluate_unary_tests ();
   void exec_context_evaluate_literal_tests ();
+  void exec_context_evaluate_binary_tests ();
   void exec_context_execute_assign_tests ();
   void exec_context_execute_call_tests ();
 }
@@ -2451,6 +2457,7 @@ public:
   data_storage *get_address_at (unsigned offset) const;
   data_value get_at (unsigned offset, unsigned width) const;
   bool is_fully_defined () const { return (~(constant_mask | address_mask)) == 
0; }
+  tree to_tree (tree type) const;
 };
 
 
@@ -2561,9 +2568,9 @@ class exec_context
   context_printer & printer;
   vec<data_storage> storages;
   unsigned next_alloc_index;
-  //void add_variables (const exec_context &);
   data_value evaluate_constructor (tree cstr) const;
-  data_value evaluate_unary (enum tree_code code, tree arg) const;
+  data_value evaluate_unary (enum tree_code code, tree type, tree arg) const;
+  data_value evaluate_binary (enum tree_code code, tree type, tree lhs, tree 
rhs) const;
   template <typename A, typename L>
   void add_variables (vec<tree, A, L> *variables, unsigned vars_count);
   template <typename A>
@@ -2578,32 +2585,18 @@ class exec_context
   data_storage *allocate (unsigned amount);
   void decompose_ref (tree data_ref, data_storage * & storage, int & offset) 
const;
   void execute_phi (gphi *phi, edge e);
-#if 0
-  template <typename A, typename L>
-  exec_context (exec_context *caller, context_printer & printer,
-               unsigned storage_size,
-               vec<tree, A, L> *local_decls, vec<tree, A, L> *ssa_names);
-#endif
 
   friend void selftest::data_value_print_tests ();
   friend void selftest::data_value_set_address_tests ();
   friend void selftest::data_value_set_tests ();
-  friend void selftest::exec_context_evaluate_unary_tests ();
   friend void selftest::exec_context_evaluate_literal_tests ();
+  friend void selftest::exec_context_evaluate_binary_tests ();
   friend void selftest::exec_context_execute_assign_tests ();
   friend void selftest::exec_context_execute_call_tests ();
 
 public:
   exec_context (exec_context *caller, context_printer & printer,
                vec<tree> & decls);
-#if 0
-  template <typename A>
-  exec_context (exec_context *caller, context_printer & printer,
-               vec<tree, A, vl_embed> *local_decls, vec<tree, A, vl_embed> 
*ssa_names);
-  template <typename A>
-  exec_context (exec_context *caller, context_printer & printer,
-               vec<tree, A, vl_ptr> *local_decls, vec<tree, A, vl_ptr> 
*ssa_names);
-#endif
   const exec_context & root () const;
   int find (const data_storage &storage) const;
   data_storage *find_reachable_var (tree variable) const;
@@ -2615,7 +2608,6 @@ public:
   data_value execute_function (struct function *);
   edge select_leaving_edge (basic_block bb, gimple *last_stmt);
   void jump (edge e);
-//  bool evaluate (tree var, tree *result) const;
 };
 
 
@@ -2685,24 +2677,6 @@ exec_context::exec_context (exec_context *caller, 
context_printer & printer,
 }
 
 
-#if 0
-void
-exec_context::add_variables (const exec_context & ctx)
-{
-  storages.reserve (ctx.storages.length ());
-
-  auto_vec<tree> ctx_vars(ctx.storages.length ());
-
-  data_storage *strgp;
-  unsigned i;
-  FOR_EACH_VEC_ELT (ctx.storages, i, strgp)
-    ctx_vars.quick_push (strgp->get_variable ());
-
-  add_variables (&ctx_vars);
-}
-#endif
-
-
 template <typename A, typename L>
 void
 exec_context::add_variables (vec<tree, A, L> *variables, unsigned vars_count)
@@ -2734,29 +2708,6 @@ exec_context::add_variables (vec<tree, A, vl_embed> 
*variables)
   add_variables (variables, vec_safe_length (variables));
 }
 
-#if 0
-template <typename A, typename L>
-exec_context::exec_context (exec_context *caller,
-                           context_printer & cp,
-                           vec<tree> &decls)
-  : parent (caller), printer (cp), storages (vNULL), next_alloc_index (0)
-{
-  if (vars_count == 0)
-    return;
-
-  storages.reserve (vars_count);
-
-  tree *varp;
-  unsigned i;
-  FOR_EACH_VEC_ELT (decls, i, varp)
-    if (*varp != NULL_TREE
-       && TYPE_SIZE (TREE_TYPE (*varp)) != NULL_TREE)
-      storages.quick_push (data_storage (*this, *varp));
-}
-#endif
-
-
-
 context_printer::context_printer (dump_flags_t f)
   : pp (), flags (f), indent (0)
 {
@@ -3335,6 +3286,22 @@ data_value::get_at (unsigned offset, unsigned width) 
const
 }
 
 
+tree
+data_value::to_tree (tree type) const
+{
+  gcc_assert (classify () == VAL_CONSTANT);
+  wide_int value = get_cst ();
+  if (TREE_CODE (type) == INTEGER_TYPE)
+    return wide_int_to_tree (type, value);
+  else
+    {
+      tree int_type = build_nonstandard_integer_type (bit_width, false);
+      tree int_val = wide_int_to_tree (int_type, value);
+      return fold_build1 (VIEW_CONVERT_EXPR, type, int_val);
+    }
+}
+
+
 void
 context_printer::print_at (const data_value & value, tree type, unsigned 
offset,
                           unsigned width)
@@ -3711,7 +3678,7 @@ exec_context::evaluate_constructor (tree cstr) const
 
 
 data_value
-exec_context::evaluate_unary (enum tree_code code, tree arg) const
+exec_context::evaluate_unary (enum tree_code code, tree type ATTRIBUTE_UNUSED, 
tree arg) const
 {
   switch (code)
     {
@@ -3723,6 +3690,31 @@ exec_context::evaluate_unary (enum tree_code code, tree 
arg) const
     }
 }
 
+data_value
+exec_context::evaluate_binary (enum tree_code code, tree type, tree lhs, tree 
rhs) const
+{
+  gcc_assert (TREE_TYPE (lhs) == TREE_TYPE (rhs)
+             || (TREE_CODE (rhs) == INTEGER_CST
+                 && TREE_CODE (TREE_TYPE (lhs)) == INTEGER_TYPE
+                 && TYPE_PRECISION (TREE_TYPE (lhs)) == TYPE_PRECISION 
(TREE_TYPE (rhs))
+                 && TYPE_UNSIGNED (TREE_TYPE (lhs)) == TYPE_UNSIGNED 
(TREE_TYPE (rhs))));
+  switch (code)
+    {
+    default:
+      {
+       gcc_assert (TREE_CODE (type) == INTEGER_TYPE
+                   || TREE_CODE (type) == BOOLEAN_TYPE);
+       tree lval = evaluate (lhs).to_tree (TREE_TYPE (lhs));
+       tree rval = evaluate (rhs).to_tree (TREE_TYPE (rhs));
+       tree t = fold_binary (code, type, lval, rval);
+       gcc_assert (t != NULL_TREE);
+       data_value result (type);
+       result.set_cst (wi::to_wide (t));
+       return result;
+      }
+    }
+}
+
 void
 exec_context::decompose_ref (tree data_ref, data_storage * & storage, int & 
offset) const
 {
@@ -3816,7 +3808,8 @@ exec_context::execute_assign (gassign *g)
              || TREE_CODE (lhs) == SSA_NAME
              || TREE_CODE (lhs) == VAR_DECL
              || TREE_CODE (lhs) == COMPONENT_REF);
-  data_value value (TREE_TYPE (lhs));
+  tree lhs_type = TREE_TYPE (lhs);
+  data_value value (lhs_type);
 
   enum tree_code rhs_code = gimple_assign_rhs_code (g);
   enum gimple_rhs_class rhs_class = get_gimple_rhs_class (rhs_code);
@@ -3827,7 +3820,12 @@ exec_context::execute_assign (gassign *g)
       break;
 
     case GIMPLE_UNARY_RHS:
-      value = evaluate_unary (rhs_code, gimple_assign_rhs1 (g));
+      value = evaluate_unary (rhs_code, lhs_type, gimple_assign_rhs1 (g));
+      break;
+
+    case GIMPLE_BINARY_RHS:
+      value = evaluate_binary (rhs_code, lhs_type,
+                              gimple_assign_rhs1 (g), gimple_assign_rhs2 (g));
       break;
 
     default:
@@ -3852,8 +3850,11 @@ exec_context::execute_call (gcall *g)
     {
       gcc_assert (gimple_call_num_args (g) == 1);
       tree arg = gimple_call_arg (g, 0);
-      gcc_assert (tree_fits_uhwi_p (arg));
-      HOST_WIDE_INT alloc_amount = tree_to_uhwi (arg);
+      data_value size = evaluate (arg);
+      gcc_assert (size.classify () == VAL_CONSTANT);
+      wide_int wi_size = size.get_cst ();
+      gcc_assert (wi::fits_uhwi_p (wi_size));
+      HOST_WIDE_INT alloc_amount = wi_size.to_uhwi ();
       data_storage *storage = allocate (alloc_amount);
 
       tree lhs = gimple_call_lhs (g);
@@ -3950,20 +3951,10 @@ exec_context::select_leaving_edge (basic_block bb, 
gimple *last_stmt)
 
       enum tree_code code = gimple_cond_code (cond);
       tree lhs = gimple_cond_lhs (cond);
-      data_value lhs_val = evaluate (lhs);
-      gcc_assert (lhs_val.classify () == VAL_CONSTANT);
-      wide_int wi_lhs = lhs_val.get_cst ();
-      tree ltype = build_nonstandard_integer_type (lhs_val.get_bitwidth (), 
false);
-      tree lval = wide_int_to_tree (ltype, wi_lhs);
-      lval = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), lval);
-
       tree rhs = gimple_cond_rhs (cond);
-      data_value rhs_val = evaluate (rhs);
-      gcc_assert (rhs_val.classify () == VAL_CONSTANT);
-      wide_int wi_rhs = rhs_val.get_cst ();
-      tree rtype = build_nonstandard_integer_type (rhs_val.get_bitwidth (), 
false);
-      tree rval = wide_int_to_tree (rtype, wi_rhs);
-      rval = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (rhs), rval);
+
+      tree lval = evaluate (lhs).to_tree (TREE_TYPE (lhs));
+      tree rval = evaluate (rhs).to_tree (TREE_TYPE (rhs));
 
       tree result = fold_binary (code, boolean_type_node, lval, rval);
       gcc_assert (result != NULL_TREE);
@@ -4492,17 +4483,19 @@ cgraph_node::create_wrapper (cgraph_node *target)
 namespace selftest
 {
 
-//void
-//get_constant_type_size_tests ()
-//{
-//  ASSERT_EQ (get_constant_type_size (ptr_type_node), HOST_BITS_PER_PTR);
-//
-//  tree vec2ptr = build_vector_type (ptr_type_node, 2);
-//  
-//  int val = get_constant_type_size (vec2ptr);
-//  ASSERT_EQ (val, 2 * HOST_BITS_PER_PTR);
-//  //ASSERT_EQ (get_constant_type_size (vec2ptr), 2 * HOST_BITS_PER_PTR);
-//}
+void
+get_constant_type_size_tests ()
+{
+  ASSERT_EQ (get_constant_type_size (integer_type_node), HOST_BITS_PER_INT);
+
+  ASSERT_EQ (get_constant_type_size (ptr_type_node), HOST_BITS_PER_PTR);
+
+  tree vec2ptr = build_vector_type (ptr_type_node, 2);
+  int val = get_constant_type_size (vec2ptr);
+  ASSERT_EQ (val, 2 * HOST_BITS_PER_PTR);
+
+  ASSERT_EQ (get_constant_type_size (boolean_type_node), 1);
+}
 
 static tree
 create_var (tree type, const char * name)
@@ -5856,6 +5849,74 @@ exec_context_evaluate_constructor_tests ()
   ASSERT_PRED1 (strg2->matches, b);
 }
 
+void
+exec_context_evaluate_binary_tests ()
+{
+  context_printer printer;
+
+  tree a = create_var (integer_type_node, "a");
+  tree b = create_var (integer_type_node, "b");
+
+  vec<tree> decls{};
+  decls.safe_push (a);
+  decls.safe_push (b);
+  vec<tree> empty{};
+
+  context_builder builder {};
+  builder.add_decls (&decls);
+  exec_context ctx = builder.build (nullptr, printer);
+
+  wide_int cst12 = wi::shwi (12, HOST_BITS_PER_INT);
+  data_value val12 (HOST_BITS_PER_INT);
+  val12.set_cst (cst12);
+  data_storage *strg_a = ctx.find_reachable_var (a);
+  gcc_assert (strg_a != nullptr);
+  strg_a->set (val12);
+
+  wide_int cst7 = wi::shwi (7, HOST_BITS_PER_INT);
+  data_value val7 (HOST_BITS_PER_INT);
+  val7.set_cst (cst7);
+  data_storage *strg_b = ctx.find_reachable_var (b);
+  gcc_assert (strg_b != nullptr);
+  strg_b->set (val7);
+
+  data_value val = ctx.evaluate_binary (MINUS_EXPR, integer_type_node, a, b);
+
+  ASSERT_EQ (val.classify (), VAL_CONSTANT);
+  wide_int wi_val = val.get_cst ();
+  ASSERT_PRED1 (wi::fits_shwi_p, wi_val);
+  ASSERT_EQ (wi_val.to_shwi (), 5);
+
+
+  tree a_bis = create_var (integer_type_node, "a");
+  tree b_bis = create_var (integer_type_node, "b");
+
+  vec<tree> decls2{};
+  decls2.safe_push (a_bis);
+  decls2.safe_push (b_bis);
+
+  context_builder builder2 {};
+  builder2.add_decls (&decls2);
+  exec_context ctx2 = builder2.build (nullptr, printer);
+
+  data_value val12_bis (HOST_BITS_PER_INT);
+  val12_bis.set_cst (wi::shwi (12, HOST_BITS_PER_INT));
+  ctx2.find_reachable_var (a_bis)->set (val12_bis);
+
+  data_value val7_bis (HOST_BITS_PER_INT);
+  val7_bis.set_cst (wi::shwi (7, HOST_BITS_PER_INT));
+  ctx2.find_reachable_var (b_bis)->set (val7_bis);
+
+  data_value val2 = ctx2.evaluate_binary (GT_EXPR, boolean_type_node, a_bis, 
b_bis);
+
+  ASSERT_EQ (val2.classify (), VAL_CONSTANT);
+  ASSERT_EQ (val2.get_bitwidth (), 1);
+  wide_int wi_val2 = val2.get_cst ();
+  ASSERT_PRED1 (wi::fits_uhwi_p, wi_val2);
+  ASSERT_EQ (wi_val2.to_uhwi (), 1);
+}
+
+
 void
 exec_context_execute_assign_tests ()
 {
@@ -6129,6 +6190,50 @@ exec_context_execute_assign_tests ()
   wide_int wi_val = c8val.get_cst_at (3 * CHAR_BIT, CHAR_BIT);
   ASSERT_PRED1 (wi::fits_shwi_p, wi_val);
   ASSERT_EQ (wi_val.to_shwi (), 8);
+
+
+  tree var_a = create_var (integer_type_node, "var_a");
+  tree var_b = create_var (integer_type_node, "var_b");
+  tree var_x = create_var (integer_type_node, "var_x");
+
+  vec<tree> decls7{};
+  decls7.safe_push (var_a);
+  decls7.safe_push (var_b);
+  decls7.safe_push (var_x);
+
+  context_builder builder7 {};
+  builder7.add_decls (&decls7);
+  exec_context ctx7 = builder7.build (nullptr, printer);
+
+  wide_int cst12 = wi::shwi (12, HOST_BITS_PER_INT);
+  data_value val12 (HOST_BITS_PER_INT);
+  val12.set_cst (cst12);
+  data_storage *strg_a = ctx7.find_reachable_var (var_a);
+  gcc_assert (strg_a != nullptr);
+  strg_a->set (val12);
+
+  wide_int cst7 = wi::shwi (7, HOST_BITS_PER_INT);
+  data_value val7_bis (HOST_BITS_PER_INT);
+  val7_bis.set_cst (cst7);
+  data_storage *strg_b = ctx7.find_reachable_var (var_b);
+  gcc_assert (strg_b != nullptr);
+  strg_b->set (val7_bis);
+
+  data_storage *strg_x = ctx7.find_reachable_var (var_x);
+  gcc_assert (strg_x != nullptr);
+
+  gassign *assign7 = gimple_build_assign (var_x, MINUS_EXPR, var_a, var_b);
+
+  data_value x_before = strg_x->get_value ();
+  ASSERT_EQ (x_before.classify (), VAL_UNDEFINED);
+
+  ctx7.execute (assign7);
+
+  data_value x_after = strg_x->get_value ();
+  ASSERT_EQ (x_after.classify (), VAL_CONSTANT);
+  wide_int x_val = x_after.get_cst ();
+  ASSERT_PRED1 (wi::fits_shwi_p, x_val);
+  ASSERT_EQ (x_val.to_shwi (), 5);
 }
 
 void
@@ -6301,12 +6406,49 @@ exec_context_execute_call_tests ()
   wide_int func_result2 = ival4.get_cst ();
   ASSERT_PRED1 (wi::fits_shwi_p, func_result2);
   ASSERT_EQ (func_result2.to_shwi (), 19);
+
+
+  tree i18 = create_var (size_type_node, "i18");
+
+  vec<tree> decls5{};
+  decls5.safe_push (p);
+  decls5.safe_push (i18);
+
+  context_builder builder5 {};
+  builder5.add_decls (&decls5);
+  exec_context ctx5 = builder5.build (nullptr, printer);
+
+  wide_int cst18 = wi::shwi (18, HOST_BITS_PER_LONG);
+  data_value val18 (size_type_node);
+  val18.set_cst (cst18);
+  data_storage *i18_strg = ctx5.find_reachable_var (i18);
+  gcc_assert (i18_strg != nullptr);
+  i18_strg->set (val18);
+
+  gcall * malloc_call5 = gimple_build_call (malloc_fn, 1, i18);
+  gimple_set_lhs (malloc_call5, p);
+
+  ASSERT_EQ (ctx5.find_alloc (0), nullptr);
+
+  ctx5.execute (malloc_call5);
+
+  data_storage *alloc_strg5 = ctx5.find_alloc (0);
+  ASSERT_NE (alloc_strg5, nullptr);
+  data_value alloc_val5 = alloc_strg5->get_value ();
+  ASSERT_EQ (alloc_val5.classify (), VAL_UNDEFINED);
+  ASSERT_EQ (alloc_val5.get_bitwidth (), 144);
+
+  data_storage *p_strg5 = ctx5.find_var (p);
+  ASSERT_NE (p_strg5, nullptr);
+  data_value p_val5 = p_strg5->get_value ();
+  ASSERT_EQ (p_val5.classify (), VAL_ADDRESS);
+  ASSERT_EQ (p_val5.get_address (), alloc_strg5);
 }
 
 void
 gimple_exec_cc_tests ()
 {
-  //get_constant_type_size_tests ();
+  get_constant_type_size_tests ();
   data_value_classify_tests ();
   exec_context_find_reachable_var_tests ();
   data_value_set_address_tests ();
@@ -6318,6 +6460,7 @@ gimple_exec_cc_tests ()
   exec_context_evaluate_tests ();
   exec_context_evaluate_literal_tests ();
   exec_context_evaluate_constructor_tests ();
+  exec_context_evaluate_binary_tests ();
   exec_context_execute_assign_tests ();
   exec_context_execute_call_tests ();
 }

Reply via email to