https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94482
--- Comment #21 from Martin Jambor <jamborm at gcc dot gnu.org> ---
As Richi already found out, the path in sra_modify_expr handling type
incompatible replacement does not work when the replaced expr comes
from within a BIT_FIELD_REF - it does only half of what is necessary.
A conservative (not yet much tested) fix would be to emit a full RMW:
*** /tmp/UTN9NX_tree-sra.c Mon Apr 6 15:28:23 2020
--- gcc/tree-sra.c Mon Apr 6 15:22:40 2020
*************** sra_modify_expr (tree *expr, gimple_stmt
*** 3742,3768 ****
ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
! if (write)
{
gassign *stmt;
if (access->grp_partial_lhs)
! ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
! false, GSI_NEW_STMT);
! stmt = gimple_build_assign (repl, ref);
gimple_set_location (stmt, loc);
! gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
}
! else
{
gassign *stmt;
if (access->grp_partial_lhs)
! repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
! true, GSI_SAME_STMT);
! stmt = gimple_build_assign (ref, repl);
gimple_set_location (stmt, loc);
! gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
}
}
else
--- 3742,3771 ----
ref = build_ref_for_model (loc, orig_expr, 0, access, gsi, false);
! if (!write || bfr)
{
gassign *stmt;
+ tree src = repl;
if (access->grp_partial_lhs)
! src = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
! true, GSI_SAME_STMT);
! stmt = gimple_build_assign (ref, src);
gimple_set_location (stmt, loc);
! gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
}
! if (bfr)
! ref = unshare_expr (ref);
! if (write || bfr)
{
gassign *stmt;
if (access->grp_partial_lhs)
! ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
! false, GSI_NEW_STMT);
! stmt = gimple_build_assign (repl, ref);
gimple_set_location (stmt, loc);
! gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
}
}
else
But I wonder whether we care about type incompatibility within a B_F_R
at all - isn't B_F_R also an implicit V_C_E, always looking at the
binary image? So perhaps something as simple as the following might
work?
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index b2056b58750..d22b03814d2 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -3736,7 +3736,7 @@ sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi,
bool write)
be accessed as a different type too, potentially creating a need for
type conversion (see PR42196) and when scalarized unions are involved
in assembler statements (see PR42398). */
- if (!useless_type_conversion_p (type, access->type))
+ if (!bfr && !useless_type_conversion_p (type, access->type))
{
tree ref;
I'll test both options ...and it seems we need the RMW one to handle
REALPART_EXPR and IMAGPART_EXPR.