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

commit r17-3170-gcfd84583a556889da6d8e777ab3a9e24557f9a02
Author: Andrea Pinski <[email protected]>
Date:   Sat Aug 8 11:22:49 2026 -0700

    phiopt: Fix up factoring out loads for REF_REVERSE_STORAGE_ORDER [PR126729]
    
    REF_REVERSE_STORAGE_ORDER is forgotten about when 
factor_out_conditional_load
    was written up so if REF_REVERSE_STORAGE_ORDER was set, it would be lost.
    If REF_REVERSE_STORAGE_ORDER was mismatched then it would mess up too.
    This fixes that oversight.
    
    Bootstrapped and tested on x86_64-linux-gnu.
    
            PR tree-optimization/126729
    
    gcc/ChangeLog:
    
            * tree-ssa-phiopt.cc (factor_out_conditional_load): Handle
            REF_REVERSE_STORAGE_ORDER being set correctly.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.dg/sso/factor_load-1.c: New test.
    
    Signed-off-by: Andrea Pinski <[email protected]>

Diff:
---
 gcc/testsuite/gcc.dg/sso/factor_load-1.c | 61 ++++++++++++++++++++++++++++++++
 gcc/tree-ssa-phiopt.cc                   | 14 ++++++--
 2 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/sso/factor_load-1.c 
b/gcc/testsuite/gcc.dg/sso/factor_load-1.c
new file mode 100644
index 000000000000..f5db8b44fba8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/sso/factor_load-1.c
@@ -0,0 +1,61 @@
+/* PR tree-optimization/126729 */
+/* { dg-do run } */
+
+struct S0 { int a; int v; } 
__attribute__((scalar_storage_order("little-endian")));
+union U0 { struct S0 s; int i[2]; } 
__attribute__((scalar_storage_order("little-endian")));
+struct S1 { int a; int v; } 
__attribute__((scalar_storage_order("big-endian")));
+union U1 { struct S1 s; int i[2]; } 
__attribute__((scalar_storage_order("big-endian")));
+
+
+__attribute__((noinline))
+int f(void *a, bool b, bool bb)
+{
+  if (b)
+  {
+    union U0 t = *((union U0*)a);
+    if (bb)
+      return t.i[0];
+    return t.s.a;
+  }
+  {
+    union U1 t = *((union U1*)a);
+    if (bb)
+      return t.i[0];
+    return t.s.a;
+  }
+}
+
+__attribute__((noinline))
+int f2(void *a, bool b, bool bb)
+{
+  if (b)
+  {
+    union U1 t = *((union U1*)a);
+    if (bb)
+      return t.i[0];
+    return t.s.a;
+  }
+  {
+    union U1 t = *((union U1*)a);
+    if (bb)
+      return t.i[0];
+    return t.s.a;
+  }
+}
+
+int main()
+{
+  union U1 a;
+  union U0 b;
+  int t = 0xabcd;
+  a.s.a = t;
+  b.s.a = t;
+  if (f((void*)&a, 0, 0) != t)
+    __builtin_abort();
+  if (f((void*)&b, 1, 0) != t)
+    __builtin_abort();
+  if (f2((void*)&a, 1, 0) != t)
+    __builtin_abort();
+  if (f2((void*)&a, 0, 0) != t)
+    __builtin_abort();
+}
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index 129a25abffbb..784221c83b32 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -4177,11 +4177,14 @@ factor_out_conditional_load (edge e0, edge e1, 
basic_block merge, gphi *phi,
   tree index = nullptr;
   tree step = nullptr;
   tree index2 = nullptr;
+  bool rev_order = false;
 
   /* Both must be *P loads of a compatible value type.  The
      TBAA alias-ptr type carried by MEM_REF operand 1 need not match; it is
      merged the way get_alias_type_for_stmts does when the load is built.  */
-  if (TREE_CODE (ref0) != MEM_REF)
+  if (TREE_CODE (ref0) == MEM_REF)
+    rev_order = REF_REVERSE_STORAGE_ORDER (ref0);
+  else
     {
       if (TREE_CODE (ref0) != TARGET_MEM_REF)
        return false;
@@ -4193,11 +4196,15 @@ factor_out_conditional_load (edge e0, edge e1, 
basic_block merge, gphi *phi,
     {
       if (index || step || index2)
        return false;
+      if (rev_order != REF_REVERSE_STORAGE_ORDER (ref1))
+       return false;
     }
   else
     {
       if (TREE_CODE (ref1) != TARGET_MEM_REF)
        return false;
+      if (rev_order)
+       return false;
       if (!safe_operand_equal_p (index, TMR_INDEX (ref1)))
        return false;
       if (!safe_operand_equal_p (step, TMR_STEP (ref1)))
@@ -4335,7 +4342,10 @@ factor_out_conditional_load (edge e0, edge e1, 
basic_block merge, gphi *phi,
     nref = build5 (TARGET_MEM_REF, TREE_TYPE (ref0), newptr,
                   newindex, index, step, index2);
   else
-    nref = build2 (MEM_REF, TREE_TYPE (ref0), newptr, newindex);
+    {
+      nref = build2 (MEM_REF, TREE_TYPE (ref0), newptr, newindex);
+      REF_REVERSE_STORAGE_ORDER (nref) = rev_order;
+    }
   MR_DEPENDENCE_CLIQUE (nref) = clique;
   MR_DEPENDENCE_BASE (nref) = base;
   tree res = gimple_phi_result (phi);

Reply via email to