https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82569
--- Comment #10 from Eric Botcazou <ebotcazou at gcc dot gnu.org> --- Index: cfgexpand.c =================================================================== --- cfgexpand.c (revision 253921) +++ cfgexpand.c (working copy) @@ -3661,7 +3661,9 @@ expand_gimple_stmt_1 (gimple *stmt) bool promoted = false; target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE); - if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target)) + if (GET_CODE (target) == SUBREG + && (SUBREG_PROMOTED_VAR_P (target) + || TREE_CODE (lhs) == SSA_NAME)) promoted = true; ops.code = gimple_assign_rhs_code (assign_stmt); @@ -3693,7 +3695,16 @@ expand_gimple_stmt_1 (gimple *stmt) ; else if (promoted) { - int unsignedp = SUBREG_PROMOTED_SIGN (target); + int unsignedp; + + if (SUBREG_PROMOTED_VAR_P (target)) + unsignedp = SUBREG_PROMOTED_SIGN (target); + else + { + machine_mode pmode = promote_ssa_mode (lhs, &unsignedp); + gcc_assert (GET_MODE (SUBREG_REG (target)) == pmode); + } + /* If TEMP is a VOIDmode constant, use convert_modes to make sure that we properly convert it. */ if (CONSTANT_P (temp) && GET_MODE (temp) == VOIDmode)