https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65932
--- Comment #12 from Jim Wilson <wilson at gcc dot gnu.org> --- Part of the problem here is that the arm port defines PROMOTE_MODE to force short local variables to unsigned, but arm_promote_function_mode doesn't change signedness. So a signed short parameter and a signed short local have different representations in a register. Another part of the problem is that the eipa_sra pass is creating phi nodes that mix parameters and local variables. Copying a signed short local into a signed short parameter requires a conversion, even though they have the same type, because they get different in register promotion. Another part of the problem is that the out-of-ssa pass when evaluating phi nodes doesn't go through expand_expr, and hence doesn't handle mode promotion. The code is copying DECL_RTL directly into SA.partition_to_pseudo, and then using SA.partition_to_pseudo when emitting the copy instructions. Thus these phi nodes won't emit any conversion instructions even though one is apparently required. I can get correct code if I pass DECL_RTL through expand_expr before storing it into SA.partition_to_pseudo for VAR_DECLs. However, if I then do the same thing for PARM_DECLS, then I get a movhi insn instead of a conversion, because both the source and dest are promoted subregs. I think the problem here is that emit_partition_copy doesn't handle promoted subregs. I think we need something like what store_expr_with_bounds does, when the dest is a promoted subreg, to do the copy to the smaller mode, and then convert to the wider mode. But I have a few too many suppositions at this point and am not sure if this makes sense. It might be simpler to change the arm port so that promote_mode and function_promote_mode match.