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.