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);
