http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55235
--- Comment #3 from Uros Bizjak <ubizjak at gmail dot com> 2012-11-07 19:05:33 UTC --- It looks to me that this is the problematic change: --- trunk/gcc/expr.c 2012/10/20 20:16:27 192640 +++ trunk/gcc/expr.c 2012/10/20 21:00:23 192641 (...) @@ -5225,21 +5244,26 @@ supposed to be bit-copied or bit-initialized. */ && expr_size (exp) != const0_rtx) { - if (GET_MODE (temp) != GET_MODE (target) - && GET_MODE (temp) != VOIDmode) + if (GET_MODE (temp) != GET_MODE (target) && GET_MODE (temp) != VOIDmode) { - int unsignedp = TYPE_UNSIGNED (TREE_TYPE (exp)); - if (GET_MODE (target) == BLKmode - && GET_MODE (temp) == BLKmode) - emit_block_move (target, temp, expr_size (exp), - (call_param_p - ? BLOCK_OP_CALL_PARM - : BLOCK_OP_NORMAL)); - else if (GET_MODE (target) == BLKmode) - store_bit_field (target, INTVAL (expr_size (exp)) * BITS_PER_UNIT, - 0, 0, 0, GET_MODE (temp), temp); + if (GET_MODE (target) == BLKmode) + { + if (REG_P (temp)) + { + if (TREE_CODE (exp) == CALL_EXPR) + copy_blkmode_from_reg (target, temp, TREE_TYPE (exp)); + else + store_bit_field (target, + INTVAL (expr_size (exp)) * BITS_PER_UNIT, + 0, 0, 0, GET_MODE (temp), temp); + } + else + emit_block_move (target, temp, expr_size (exp), + (call_param_p + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); + } emit_block_move was guarded with BLKmode guard on both operands, all other went through store_bit_field.