https://gcc.gnu.org/g:2a6c6e9c6d32ddbd6cfea5319698a69b342d0e9c

commit r16-910-g2a6c6e9c6d32ddbd6cfea5319698a69b342d0e9c
Author: Eric Botcazou <ebotca...@adacore.com>
Date:   Tue May 27 19:42:17 2025 +0200

    Fix IPA-SRA issue with reverse SSO on specific pattern
    
    IPA-SRA generally works fine in the presence of reverse Scalar_Storage_Order
    by propagating the relevant flag onto the newly generated MEM_REFs.  However
    we have been recently faced with a specific Ada pattern that it does not
    handle correctly: the 'Valid attribute applied to a floating-point component
    of an aggregate type with reverse Scalar_Storage_Order.
    
    The attribute is implemented by a call to a specific routine of the runtime
    that expects a pointer to the object so, in the case of a component with
    reverse SSO, the compiler first loads it from the aggregate to get back the
    native storage order, but it does the load using an array of bytes instead
    of the floating-point type to prevent the FPU from fiddling with the value,
    which yields in the .original dump file:
    
      *(character[1:4] *) &F2b = VIEW_CONVERT_EXPR<character[1:4]>(item.f);
    
    Of course that's a bit convoluted, but it does not seem that another method
    would be simpler or even work, and using VIEW_CONVERT_EXPR to toggle the SSO
    is supposed to be supported in any case (unlike aliasing or type punning).
    
    The attached patch makes it work.  While the call to storage_order_barrier_p
    from IPA-SRA is quite natural (the regular SRA has it too), the tweak to the
    predicate itself is needed to handle the scalar->aggregate conversion, which
    is admittedly awkward but again without clear alternative.
    
    gcc/
            * ipa-sra.cc (scan_expr_access): Also disqualify storage order
            barriers from splitting.
            * tree.h (storage_order_barrier_p): Also return false if the
            operand of the VIEW_CONVERT_EXPR has reverse storage order.
    
    gcc/testsuite/
            * gnat.dg/sso19.adb: New test.
            * gnat.dg/sso19_pkg.ads, gnat.dg/sso19_pkg.adb: New helper.

Diff:
---
 gcc/ipa-sra.cc                      |  6 ++++++
 gcc/testsuite/gnat.dg/sso19.adb     | 13 +++++++++++++
 gcc/testsuite/gnat.dg/sso19_pkg.adb | 13 +++++++++++++
 gcc/testsuite/gnat.dg/sso19_pkg.ads | 24 ++++++++++++++++++++++++
 gcc/tree.h                          |  2 +-
 5 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc
index 88bfae9502c7..6e6cf895988e 100644
--- a/gcc/ipa-sra.cc
+++ b/gcc/ipa-sra.cc
@@ -1848,6 +1848,12 @@ scan_expr_access (tree expr, gimple *stmt, 
isra_scan_context ctx,
   if (!desc || !desc->split_candidate)
     return;
 
+  if (storage_order_barrier_p (expr))
+    {
+      disqualify_split_candidate (desc, "Encountered a storage order 
barrier.");
+      return;
+    }
+
   if (!poffset.is_constant (&offset)
       || !psize.is_constant (&size)
       || !pmax_size.is_constant (&max_size))
diff --git a/gcc/testsuite/gnat.dg/sso19.adb b/gcc/testsuite/gnat.dg/sso19.adb
new file mode 100644
index 000000000000..497d987441af
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso19.adb
@@ -0,0 +1,13 @@
+--  { dg-do run }
+--  { dg-options "-O2" }
+
+with SSO19_Pkg; use SSO19_Pkg;
+
+procedure SSO19 is
+  R : constant Rec := (D => (I => 8, F => 4.6095713E-41));
+
+begin
+  if not Is_Valid (R) then
+    raise Program_Error;
+  end if;
+end;
diff --git a/gcc/testsuite/gnat.dg/sso19_pkg.adb 
b/gcc/testsuite/gnat.dg/sso19_pkg.adb
new file mode 100644
index 000000000000..cbcb2f95e501
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso19_pkg.adb
@@ -0,0 +1,13 @@
+package body SSO19_Pkg is
+
+  function Is_Valid_Private (Item : Data) return Boolean is
+  begin
+    return Item.I'Valid and Item.F'Valid;
+  end Is_Valid_Private;
+
+  function Is_Valid (Item : Rec) return Boolean is
+  begin
+    return Is_Valid_Private (Item.D);
+  end Is_Valid;
+
+end SSO19_Pkg;
diff --git a/gcc/testsuite/gnat.dg/sso19_pkg.ads 
b/gcc/testsuite/gnat.dg/sso19_pkg.ads
new file mode 100644
index 000000000000..cad5368a6ad2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/sso19_pkg.ads
@@ -0,0 +1,24 @@
+with System;
+
+package SSO19_Pkg is
+
+  subtype Small_Int is Short_Integer range -1000 .. 1000;
+
+  type Data is record
+    I : Small_Int;
+    F : Float;
+  end record;
+  for Data use record
+    I at 0 range 0 .. 15;
+    F at 4 range 0 .. 31;
+  end record;
+  for Data'Bit_Order use System.High_Order_First;
+  for Data'Scalar_Storage_Order use System.High_Order_First;
+
+  type Rec is record
+    D : Data;
+  end record;
+
+  function Is_Valid (Item : Rec) return Boolean;
+
+end SSO19_Pkg;
diff --git a/gcc/tree.h b/gcc/tree.h
index 99f261776281..1e41316b4c95 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5499,7 +5499,7 @@ storage_order_barrier_p (const_tree t)
       && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (op)))
     return true;
 
-  return false;
+  return reverse_storage_order_for_component_p (op);
 }
 
 /* Given a DECL or TYPE, return the scope in which it was declared, or

Reply via email to