https://gcc.gnu.org/g:947a0417737071a7fbc10a826a3bff75e252b660

commit 947a0417737071a7fbc10a826a3bff75e252b660
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Mon May 26 10:47:41 2025 +0200

    gimple-exec: correction prise en charge offset adresse MEM_REF

Diff:
---
 gcc/cgraphunit.cc | 251 ++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 161 insertions(+), 90 deletions(-)

diff --git a/gcc/cgraphunit.cc b/gcc/cgraphunit.cc
index 62fb874dbdba..97013daa9fbd 100644
--- a/gcc/cgraphunit.cc
+++ b/gcc/cgraphunit.cc
@@ -3880,14 +3880,13 @@ exec_context::evaluate (tree expr) const
        storage_address *address = val_ptr.get_address ();
        gcc_assert (address != nullptr);
        data_value storage_value = address->storage.get ().get_value ();
-       unsigned ptr_offset = address->offset;
+       wide_int ptr_off = wi::uhwi (address->offset,
+                                    HOST_BITS_PER_WIDE_INT);
 
        tree offset_bytes = TREE_OPERAND (expr, 1);
        data_value val_off = evaluate (offset_bytes);
        gcc_assert (val_off.classify () == VAL_CONSTANT);
        wide_int wi_off = val_off.get_cst ();
-       gcc_assert (wi::fits_uhwi_p (wi_off));
-       unsigned offset = wi_off.to_uhwi ();
 
        unsigned bit_width;
        if (!get_constant_type_size (TREE_TYPE (expr), bit_width))
@@ -3909,13 +3908,14 @@ exec_context::evaluate (tree expr) const
                gcc_assert (val_step.classify () == VAL_CONSTANT);
                wide_int wi_step = val_step.get_cst ();
 
-               wide_int additional_off = wi_idx * wi_step;
-               gcc_assert (wi::fits_uhwi_p (additional_off));
-               offset += additional_off.to_uhwi ();
+               wi_off += wi_idx * wi_step;
              }
          }
 
-       return storage_value.get_at (offset * CHAR_BIT + ptr_offset, bit_width);
+       wi_off = wi_off * CHAR_BIT + ptr_off;
+       gcc_assert (wi::fits_uhwi_p (wi_off));
+
+       return storage_value.get_at (wi_off.to_shwi (), bit_width);
       }
       break;
 
@@ -4206,105 +4206,130 @@ exec_context::evaluate_binary (enum tree_code code, 
tree type, tree lhs, tree rh
     gcc_unreachable ();
 }
 
-void
-exec_context::decompose_ref (tree data_ref, data_storage * & storage, int & 
offset) const
+
+static bool
+is_zero_offset_data_ref (enum tree_code code)
 {
-  offset = -1;
-  enum tree_code code = TREE_CODE (data_ref);
   switch (code)
     {
     case VAR_DECL:
     case SSA_NAME:
-      {
-       tree var = data_ref;
-       offset = 0;
-       storage = find_reachable_var (var);
-      }
-      break;
+      return true;
 
-    case ARRAY_REF:
-      {
-       data_storage *parent_storage = nullptr;
-       int parent_offset = -1;
-       tree parent_ref = TREE_OPERAND (data_ref, 0);
-       decompose_ref (parent_ref, parent_storage, parent_offset);
-       gcc_assert (parent_offset >= 0);
-       gcc_assert (parent_storage != nullptr);
-
-       tree idx = TREE_OPERAND (data_ref, 1);
-       data_value val = evaluate (idx);
-       gcc_assert (val.classify () == VAL_CONSTANT);
-       wide_int wi_idx = val.get_cst ();
-       gcc_assert (wi::fits_uhwi_p (wi_idx));
-       unsigned HOST_WIDE_INT hw_idx = wi_idx.to_uhwi ();
-
-       gcc_assert (TREE_OPERAND (data_ref, 3) == NULL_TREE);
-       tree elt_type = TREE_TYPE (TREE_TYPE (parent_ref));
-       unsigned size_bits;
-       bool found_size = get_constant_type_size (elt_type, size_bits);
-       gcc_assert (found_size);
-       unsigned this_offset = hw_idx * size_bits;
+    default:
+      return false;
+    }
+}
 
-       storage = parent_storage;
-       offset = parent_offset + this_offset;
-      }
-      break;
 
-    case COMPONENT_REF:
-      {
-       data_storage *parent_storage = nullptr;
-       int parent_offset = -1;
-       decompose_ref (TREE_OPERAND (data_ref, 0), parent_storage, 
parent_offset);
-       gcc_assert (parent_offset >= 0);
-       gcc_assert (parent_storage != nullptr);
+void
+exec_context::decompose_ref (tree data_ref, data_storage * & storage, int & 
offset) const
+{
+  offset = -1;
+  enum tree_code code = TREE_CODE (data_ref);
+  if (is_zero_offset_data_ref (code))
+    {
+      offset = 0;
+      storage = find_reachable_var (data_ref);
+    }
+  else
+    {
+      tree parent_data_ref = nullptr;
+      wide_int add_offset = wi::zero (HOST_BITS_PER_WIDE_INT);
+      wide_int add_index = wi::zero (HOST_BITS_PER_WIDE_INT);
+      wide_int add_multiplier = wi::zero (HOST_BITS_PER_WIDE_INT);
+      switch (code)
+       {
+       case ARRAY_REF:
+         {
+           parent_data_ref = TREE_OPERAND (data_ref, 0);
+
+           tree idx = TREE_OPERAND (data_ref, 1);
+           data_value val = evaluate (idx);
+           gcc_assert (val.classify () == VAL_CONSTANT);
+           add_index = val.get_cst ();
+
+           gcc_assert (TREE_OPERAND (data_ref, 3) == NULL_TREE);
+           tree elt_type = TREE_TYPE (TREE_TYPE (parent_data_ref));
+           unsigned size_bits;
+           bool found_size = get_constant_type_size (elt_type, size_bits);
+           gcc_assert (found_size);
+           add_multiplier = wi::uhwi (size_bits, HOST_BITS_PER_WIDE_INT);
+         }
+         break;
 
-       int this_offset = int_bit_position (TREE_OPERAND (data_ref, 1));
-       gcc_assert (this_offset >= 0);
+       case COMPONENT_REF:
+         {
+           parent_data_ref = TREE_OPERAND (data_ref, 0);
 
-       storage = parent_storage;
-       offset = parent_offset + this_offset;
-      }
-      break;
+           int comp_offset = int_bit_position (TREE_OPERAND (data_ref, 1));
+           gcc_assert (comp_offset >= 0);
 
-    case MEM_REF:
-    case TARGET_MEM_REF:
-      {
-       tree var = TREE_OPERAND (data_ref, 0);
-       data_value addr = evaluate (var);
-       gcc_assert (addr.classify () == VAL_ADDRESS);
-       storage = &(addr.get_address ()->storage.get ());
-
-       tree off = TREE_OPERAND (data_ref, 1);
-       data_value off_val = evaluate (off);
-       gcc_assert (off_val.classify () == VAL_CONSTANT);
-       wide_int wi_off = off_val.get_cst ();
-       gcc_assert (wi::fits_uhwi_p (wi_off));
-       unsigned HOST_WIDE_INT uhwi_off = wi_off.to_uhwi ();
+           add_offset = wi::shwi (comp_offset, HOST_BITS_PER_WIDE_INT);
+         }
+         break;
 
-       if (code == TARGET_MEM_REF)
+       case MEM_REF:
+       case TARGET_MEM_REF:
          {
-           tree index = TREE_OPERAND (data_ref, 2);
-           data_value idx_val = evaluate (index);
-           gcc_assert (idx_val.classify () == VAL_CONSTANT);
-           wide_int wi_idx = idx_val.get_cst ();
-
-           tree step = TREE_OPERAND (data_ref, 3);
-           data_value step_val = evaluate (step);
-           gcc_assert (step_val.classify () == VAL_CONSTANT);
-           wide_int wi_step = step_val.get_cst ();
-
-           wide_int additional_off = wi_idx * wi_step;
-           gcc_assert (wi::fits_uhwi_p (additional_off));
-           uhwi_off += additional_off.to_uhwi ();
+           tree var = TREE_OPERAND (data_ref, 0);
+           data_value var_val = evaluate (var);
+           gcc_assert (var_val.classify () == VAL_ADDRESS);
+           storage_address *addr = var_val.get_address ();
+           gcc_assert (addr != nullptr);
+           storage = &(addr->storage.get ());
+
+           add_offset = wi::uhwi (addr->offset, HOST_BITS_PER_WIDE_INT);
+           tree off = TREE_OPERAND (data_ref, 1);
+           data_value off_val = evaluate (off);
+           gcc_assert (off_val.classify () == VAL_CONSTANT);
+           add_offset += off_val.get_cst () * CHAR_BIT;
+
+           if (code == TARGET_MEM_REF)
+             {
+               tree index = TREE_OPERAND (data_ref, 2);
+               data_value idx_val = evaluate (index);
+               gcc_assert (idx_val.classify () == VAL_CONSTANT);
+               add_index = idx_val.get_cst ();
+
+               tree step = TREE_OPERAND (data_ref, 3);
+               data_value step_val = evaluate (step);
+               gcc_assert (step_val.classify () == VAL_CONSTANT);
+               add_multiplier = step_val.get_cst ();
+               add_multiplier *= CHAR_BIT;
+             }
          }
+         break;
 
-       gcc_assert (uhwi_off <= UINT_MAX / CHAR_BIT);
-       offset = uhwi_off * CHAR_BIT;
-      }
-      break;
+       default:
+         gcc_unreachable ();
+       }
 
-    default:
-      gcc_unreachable ();
+      if (parent_data_ref != nullptr)
+       {
+         int parent_offset;
+         decompose_ref (parent_data_ref, storage, parent_offset);
+         add_offset += parent_offset;
+       }
+
+      if (add_offset.get_precision () < HOST_BITS_PER_WIDE_INT)
+       add_offset = wide_int_storage::from (add_offset,
+                                            HOST_BITS_PER_WIDE_INT,
+                                            UNSIGNED);
+
+      if (add_index.get_precision () < HOST_BITS_PER_WIDE_INT)
+       add_index = wide_int_storage::from (add_index,
+                                           HOST_BITS_PER_WIDE_INT,
+                                           UNSIGNED);
+
+      if (add_multiplier.get_precision () < HOST_BITS_PER_WIDE_INT)
+       add_multiplier = wide_int_storage::from (add_multiplier,
+                                                HOST_BITS_PER_WIDE_INT,
+                                                UNSIGNED);
+
+      wide_int off = add_offset + add_index * add_multiplier;
+      gcc_assert (wi::fits_shwi_p (off));
+      offset = off.to_shwi ();
     }
 
   gcc_assert (storage != nullptr);
@@ -7110,6 +7135,52 @@ exec_context_evaluate_tests ()
   wide_int wi19_0 = val19_0.get_cst ();
   ASSERT_PRED1 (wi::fits_uhwi_p, wi19_0);
   ASSERT_EQ  (wi19_0.to_uhwi (), 23);
+
+
+  tree ta11 = build_array_type_nelts (integer_type_node, 2);
+  tree taa11 = build_array_type_nelts (ta11, 2);
+  tree a11 = create_var (taa11, "a11");
+  tree p11 = create_var (ptr_type_node, "p11");
+
+  vec<tree> decls11{};
+  decls11.safe_push (a11);
+  decls11.safe_push (p11);
+
+  context_builder builder11;
+  builder11.add_decls (&decls11);
+  exec_context ctx11 = builder11.build (mem, printer);
+
+  data_value val_a11 (integer_type_node);
+  wide_int wi_a11 = wi::shwi (7, TYPE_PRECISION (integer_type_node));
+  val_a11.set_cst (wi_a11);
+
+  data_storage * strg_a11 = ctx11.find_reachable_var (a11);
+  gcc_assert (strg_a11 != nullptr);
+  strg_a11->set_at (val_a11, 2 * HOST_BITS_PER_INT);
+
+  storage_address addr_a11 (strg_a11->get_ref (), 2 * HOST_BITS_PER_INT);
+
+  data_value val_p11 (ptr_type_node);
+  val_p11.set_address (addr_a11);
+
+  data_storage * strg_p11 = ctx11.find_reachable_var (p11);
+  gcc_assert (strg_p11 != nullptr);
+  strg_p11->set (val_p11);
+
+  tree pta11 = build_pointer_type (ta11);
+  tree mem11 = build2 (MEM_REF, ta11,
+                      p11, build_zero_cst (pta11));
+  tree ar11 = build4 (ARRAY_REF, integer_type_node,
+                     mem11, build_zero_cst (integer_type_node),
+                     NULL_TREE, NULL_TREE);
+
+  data_value val_ref11 = ctx11.evaluate (ar11);
+
+  ASSERT_EQ (val_ref11.get_bitwidth (), HOST_BITS_PER_INT);
+  ASSERT_EQ (val_ref11.classify (), VAL_CONSTANT);
+  wide_int wi_ref11 = val_ref11.get_cst ();
+  ASSERT_PRED1 (wi::fits_uhwi_p, wi_ref11);
+  ASSERT_EQ  (wi_ref11.to_uhwi (), 7);
 }

Reply via email to