Hi, On Thu, 8 Sep 2011, Richard Sandiford wrote:
> if (TREE_CODE (from) == CALL_EXPR && ! aggregate_value_p (from, from) > && COMPLETE_TYPE_P (TREE_TYPE (from)) > && TREE_CODE (TYPE_SIZE (TREE_TYPE (from))) == INTEGER_CST > && ! (((TREE_CODE (to) == VAR_DECL || TREE_CODE (to) == PARM_DECL) > && REG_P (DECL_RTL (to))) > || TREE_CODE (to) == SSA_NAME)) > { > rtx value; > > push_temp_slots (); > value = expand_normal (from); > if (to_rtx == 0) > to_rtx = expand_expr (to, NULL_RTX, VOIDmode, EXPAND_WRITE); > > block of expand_assignment, but I think the REG_P exclusion that applies > to VAR_DECLs and PARM_DECLs also applies to RESULT_DECLs. Right, when I saw your conversation on IRC that was also my first reaction. My second was similar to this hunk ... > @@ -8950,10 +9061,15 @@ expand_expr_real_1 (tree exp, rtx target > return temp; > } > > - /* If the mode of DECL_RTL does not match that of the decl, it > - must be a promoted value. We return a SUBREG of the wanted mode, > - but mark it so that we know that it was already extended. */ > - if (REG_P (decl_rtl) && GET_MODE (decl_rtl) != DECL_MODE (exp)) > + /* If the mode of DECL_RTL does not match that of the decl, > + there are two cases: we are dealing with a BLKmode value > + that is returned in a register, or we are dealing with > + a promoted value. In the latter case, return a SUBREG > + of the wanted mode, but mark it so that we know that it > + was already extended. */ > + if (REG_P (decl_rtl) > + && !(code == RESULT_DECL && DECL_MODE (exp) == BLKmode) > + && GET_MODE (decl_rtl) != DECL_MODE (exp)) ... though I don't see the need for a RESULT_DECL check. If GET_MODE(exp) is BLKmode, then the code inside the if never will do anything sane (promote_function_mode and promote_decl_mode will return BLKmode). And you miss a ChangeLog entry for this hunk. After these two changes I would have had to split out the expand_return code to make progress, and stopped poking at it :) So, I think your approach makes sense. Ciao, Michael.