Hi,

fold_ctor_reference already punts on a CONSTRUCTOR whose type has reverse 
storage order, but it can be invoked in a couple of places on a CONSTRUCTOR 
with native storage order that has been wrapped in a VIEW_CONVERT_EXPR to a 
type with reverse storage order; this would require a post adjustment that 
does not currently exist, thus yield wrong code for this admittedly quite 
pathological (but supported) case.

Technically, this is a regression in GCC 10.x and later but, being quite 
pathological, at least in Ada, I don't think that we need to bother about it 
on earlier branches than gcc-13.

Tested on x86-64/Linux, OK for mainline down to the gcc-13 branch?


2025-06-26  Eric Botcazou  <ebotca...@adacore.com>

        * gimple-fold.cc (fold_const_aggregate_ref_1) <COMPONENT_REF>:
        Bail out immediately if the reference has reverse storage order.
        * tree-ssa-sccvn.cc (fully_constant_vn_reference_p): Likewise.


2025-06-26  Eric Botcazou  <ebotca...@adacore.com>

        * gnat.dg/sso20.adb: New test.

-- 
Eric Botcazou
diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
index 729080ad6e5..e9635d1005d 100644
--- a/gcc/gimple-fold.cc
+++ b/gcc/gimple-fold.cc
@@ -10117,19 +10117,21 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
       base = get_ref_base_and_extent (t, &offset, &size, &max_size, &reverse);
       ctor = get_base_constructor (base, &offset, valueize);
 
+      /* We cannot determine ctor.  */
+      if (!ctor)
+	return NULL_TREE;
       /* Empty constructor.  Always fold to 0.  */
       if (ctor == error_mark_node)
 	return build_zero_cst (TREE_TYPE (t));
-      /* We do not know precise address.  */
+      /* We do not know precise access.  */
       if (!known_size_p (max_size) || maybe_ne (max_size, size))
 	return NULL_TREE;
-      /* We cannot determine ctor.  */
-      if (!ctor)
-	return NULL_TREE;
-
       /* Out of bound array access.  Value is undefined, but don't fold.  */
       if (maybe_lt (offset, 0))
 	return NULL_TREE;
+      /* Access with reverse storage order.  */
+      if (reverse)
+	return NULL_TREE;
 
       tem = fold_ctor_reference (TREE_TYPE (t), ctor, offset, size, base);
       if (tem)
@@ -10149,7 +10151,6 @@ fold_const_aggregate_ref_1 (tree t, tree (*valueize) (tree))
 	      && offset.is_constant (&coffset)
 	      && (coffset % BITS_PER_UNIT != 0
 		  || csize % BITS_PER_UNIT != 0)
-	      && !reverse
 	      && BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN)
 	    {
 	      poly_int64 bitoffset;
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index f7f50c3de99..9cdbf3da772 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -1615,6 +1615,8 @@ fully_constant_vn_reference_p (vn_reference_t ref)
 	      ++i;
 	      break;
 	    }
+	  if (operands[i].reverse)
+	    return NULL_TREE;
 	  if (known_eq (operands[i].off, -1))
 	    return NULL_TREE;
 	  off += operands[i].off;
--  { dg-do run }
--  { dg-options "-O" }

with Ada.Unchecked_Conversion;
with Interfaces;  use Interfaces;
with System;      use System;

procedure SSO20 is

  type Bytes_Ref is array (1 .. 4) of Unsigned_8
    with Convention => Ada_Pass_By_Reference;

  type U32_BE is record
    Value : Unsigned_32;
  end record
    with
      Pack,
      Bit_Order            => High_Order_First,
      Scalar_Storage_Order => High_Order_First;

  function Conv is new Ada.Unchecked_Conversion (Bytes_Ref, U32_BE);

  function Value (B : Bytes_Ref) return Unsigned_32 is (Conv (B).Value);

begin
  if Value ((16#11#, 16#22#, 16#33#, 16#44#)) /= 16#11223344# then
     raise Program_Error;
  end if;
end;

Reply via email to