https://gcc.gnu.org/g:a8aae299bba557f783b84472a5a1850f0fc6f881

commit a8aae299bba557f783b84472a5a1850f0fc6f881
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Sat May 3 22:31:11 2025 +0200

    gimple-exec: évaluation comparaison adresse avec NULL

Diff:
---
 gcc/cgraphunit.cc | 167 ++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 107 insertions(+), 60 deletions(-)

diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 6eaa7c8832ad..7fe0e85f472b 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -4094,69 +4094,85 @@ exec_context::evaluate_unary (enum tree_code code, tree 
type, 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 (TREE_TYPE (rhs)) == INTEGER_TYPE
-                 && 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)))
-             || code == POINTER_PLUS_EXPR);
-  switch (code)
+  gcc_assert (TREE_CODE (type) == INTEGER_TYPE
+             || TREE_CODE (type) == BOOLEAN_TYPE
+             || TREE_CODE (type) == POINTER_TYPE
+             || TREE_CODE (type) == REAL_TYPE);
+  data_value val_lhs = evaluate (lhs);
+  data_value val_rhs = evaluate (rhs);
+  enum value_type lhs_type = val_lhs.classify ();
+  enum value_type rhs_type = val_rhs.classify ();
+  if (lhs_type == VAL_CONSTANT && rhs_type == VAL_CONSTANT)
     {
-    default:
-      {
-       gcc_assert (TREE_CODE (type) == INTEGER_TYPE
-                   || TREE_CODE (type) == BOOLEAN_TYPE
-                   || TREE_CODE (type) == POINTER_TYPE
-                   || TREE_CODE (type) == REAL_TYPE);
-       data_value val_lhs = evaluate (lhs);
-       data_value val_rhs = evaluate (rhs);
-       enum value_type lhs_type = val_lhs.classify ();
-       enum value_type rhs_type = val_rhs.classify ();
-       if (lhs_type == VAL_CONSTANT && rhs_type == VAL_CONSTANT)
-         {
-           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))));
-           tree lval = val_lhs.to_tree (TREE_TYPE (lhs));
-           tree rval = val_rhs.to_tree (TREE_TYPE (rhs));
-           tree t = fold_binary (code, type, lval, rval);
-           gcc_assert (t != NULL_TREE);
-           return evaluate (t);
-         }
-       else
-         {
-           gcc_assert (code == PLUS_EXPR
-                       || code == POINTER_PLUS_EXPR);
-           data_value *val_address = nullptr, *val_offset = nullptr;
-           if (lhs_type == VAL_ADDRESS && rhs_type == VAL_CONSTANT)
-             {
-               val_address = &val_lhs;
-               val_offset = &val_rhs;
-             }
-           else if (lhs_type == VAL_CONSTANT && rhs_type == VAL_ADDRESS)
-             {
-               val_address = &val_rhs;
-               val_offset = &val_lhs;
-             }
-           else
-             gcc_unreachable ();
+      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))));
+      tree lval = val_lhs.to_tree (TREE_TYPE (lhs));
+      tree rval = val_rhs.to_tree (TREE_TYPE (rhs));
+      tree t = fold_binary (code, type, lval, rval);
+      gcc_assert (t != NULL_TREE);
+      return evaluate (t);
+    }
+  else if ((lhs_type == VAL_ADDRESS && rhs_type == VAL_CONSTANT)
+          || (lhs_type == VAL_CONSTANT && rhs_type == VAL_ADDRESS))
+    {
+      if (code == PLUS_EXPR || code == POINTER_PLUS_EXPR)
+       {
+         data_value *val_address = nullptr, *val_offset = nullptr;
+         if (lhs_type == VAL_ADDRESS && rhs_type == VAL_CONSTANT)
+           {
+             val_address = &val_lhs;
+             val_offset = &val_rhs;
+           }
+         else if (lhs_type == VAL_CONSTANT && rhs_type == VAL_ADDRESS)
+           {
+             val_address = &val_rhs;
+             val_offset = &val_lhs;
+           }
+         else
+           gcc_unreachable ();
+
+         storage_address *address = val_address->get_address ();
+         gcc_assert (address != nullptr);
+         wide_int offset = val_offset->get_cst ();
+         wide_int bit_offset = offset * CHAR_BIT;
+         wide_int total_offset = address->offset + bit_offset;
+         gcc_assert (wi::fits_uhwi_p (total_offset));
+         storage_address final_address (address->storage,
+                                        total_offset.to_uhwi ());
+         data_value result (type);
+         result.set_address (final_address);
+         return result;
+       }
+      else if (code == EQ_EXPR || code == NE_EXPR)
+       {
+         data_value *val_null = nullptr;
+         if (lhs_type == VAL_ADDRESS && rhs_type == VAL_CONSTANT)
+           val_null = &val_rhs;
+         else if (lhs_type == VAL_CONSTANT && rhs_type == VAL_ADDRESS)
+           val_null = &val_lhs;
+         else
+           gcc_unreachable ();
 
-           storage_address *address = val_address->get_address ();
-           gcc_assert (address != nullptr);
-           wide_int offset = val_offset->get_cst ();
-           wide_int bit_offset = offset * CHAR_BIT;
-           wide_int total_offset = address->offset + bit_offset;
-           gcc_assert (wi::fits_uhwi_p (total_offset));
-           storage_address final_address (address->storage,
-                                          total_offset.to_uhwi ());
-           data_value result (type);
-           result.set_address (final_address);
-           return result;
-         }
-      }
+         /* Check that val_null really is the null pointer.  */
+         wide_int wi_null_val = val_null->get_cst ();
+         gcc_assert (wi_null_val == 0);
+
+         data_value result (type);
+         bool bool_result = code == NE_EXPR;
+         wide_int wi_result = wi::uhwi (bool_result, result.get_bitwidth ());
+         result.set_cst (wi_result);
+         return result;
+       }
+      else
+       gcc_unreachable ();
     }
+  else
+    gcc_unreachable ();
 }
 
 void
@@ -7575,6 +7591,37 @@ exec_context_evaluate_binary_tests ()
   ASSERT_EQ (TREE_CODE (f), REAL_CST);
   REAL_VALUE_TYPE val575 = REAL_VALUE_ATOF ("5.75", float_mode);
   ASSERT_TRUE (real_equal (TREE_REAL_CST_PTR (f), &val575));
+
+
+  tree i5 = create_var (integer_type_node, "i5");
+  tree p5 = create_var (build_pointer_type (integer_type_node), "p5");
+
+  vec<tree> decls5{};
+  decls5.safe_push (i5);
+  decls5.safe_push (p5);
+
+  context_builder builder5 {};
+  builder5.add_decls (&decls5);
+  exec_context ctx5 = builder5.build (mem, printer);
+
+  data_storage *strg_i5 = ctx5.find_reachable_var (i5);
+  gcc_assert (strg_i5 != nullptr);
+  data_value addr_i5 (ptr_type_node);
+  storage_address strg_addr_i5 (strg_i5->get_ref (), 0);
+  addr_i5.set_address (strg_addr_i5);
+
+  data_storage *strg_p5 = ctx5.find_reachable_var (p5);
+  gcc_assert (strg_p5 != nullptr);
+  strg_p5->set (addr_i5);
+
+  data_value val_ne5 = ctx5.evaluate_binary (NE_EXPR, boolean_type_node,
+                                            p5,
+                                            build_int_cst (ptr_type_node, 0));
+
+  ASSERT_EQ (val_ne5.classify (), VAL_CONSTANT);
+  wide_int wi_ne5 = val_ne5.get_cst ();
+  ASSERT_PRED1 (wi::fits_uhwi_p, wi_ne5);
+  ASSERT_EQ (wi_ne5.to_uhwi (), 1);
 }

Reply via email to