https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108199

--- Comment #7 from Andreas Krebbel <krebbel at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #6)
> (In reply to Andreas Krebbel from comment #5)
> > In:
> > 
> >   _1 = src_6(D)->a;
> >   dst$val_9 = _1;
> >   _2 = BIT_FIELD_REF <dst$val_9, 8, 0>;
> >   _3 = _2 & 64;
> >   if (_3 != 0)
> 
> There is only 2 accesses going on in the above IR because SRA removed the
> 3rd when it replaced the access of dst.val with dst$val but didn't update
> BIT_FIELD_REF to remove the byteswap ...

Ok, got it. It isn't the removal of the assignment. As you say it happens in
early SRA when changing dst.val to dst$val and with that going from the union
with the storage order marker to a long int without it. The marker on the
BIT_FIELD_REF needs to be in sync with the marker on its inner reference.
Dropping one without adjusting the other is the problem here. Thanks for the
pointer!

The following change helps with that testcase:

diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 8dfc923ed7e..6b1ce6e8b4a 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -3815,8 +3815,13 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi,
bool write)
            }
        }
       else
-       *expr = repl;
-      sra_stats.exprs++;
+       {
+         if (bfr && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (*expr)))
+           REF_REVERSE_STORAGE_ORDER (bfr) = 0;
+
+         *expr = repl;
+         sra_stats.exprs++;
+       }
     }
   else if (write && access->grp_to_be_debug_replaced)
     {

Reply via email to