Revision 192641 [1] introduced following testsuite failure on i686: FAIL: gcc.target/i386/pr44948-2a.c (internal compiler error) FAIL: gcc.target/i386/pr44948-2a.c (test for excess errors) [1] http://gcc.gnu.org/ml/gcc-cvs/2012-10/msg00764.html ~/gcc-build-fast/gcc/cc1 -O -m32 -mno-sse -quiet pr44948-2a.c pr44948-2a.c: In function ‘main’: pr44948-2a.c:18:12: internal compiler error: in emit_block_move_hints, at expr.c:1153 struct A a = { { 0, 1, 2, 3 } }; ^ 0x6b9f68 emit_block_move_hints(rtx_def*, rtx_def*, rtx_def*, block_op_methods, unsigned int, long) ../../gcc-svn/trunk/gcc/expr.c:1153 0x6ba261 emit_block_move(rtx_def*, rtx_def*, rtx_def*, block_op_methods) ../../gcc-svn/trunk/gcc/expr.c:1205 0x6c5e57 store_expr(tree_node*, rtx_def*, int, bool) ../../gcc-svn/trunk/gcc/expr.c:5261 0x6ca835 store_field ../../gcc-svn/trunk/gcc/expr.c:6531 0x6c3f57 expand_assignment(tree_node*, tree_node*, bool) ../../gcc-svn/trunk/gcc/expr.c:4838 0x5fc845 expand_gimple_stmt_1 ../../gcc-svn/trunk/gcc/cfgexpand.c:2108 0x5fc845 expand_gimple_stmt ../../gcc-svn/trunk/gcc/cfgexpand.c:2204 0x5fe137 expand_gimple_basic_block ../../gcc-svn/trunk/gcc/cfgexpand.c:3979 0x60034b gimple_expand_cfg ../../gcc-svn/trunk/gcc/cfgexpand.c:4498 Please submit a full bug report, (gdb) f 2 #2 0x00000000006b9f69 in emit_block_move_hints (x=0x7ffff1aca150, y=0x7ffff1ab55b0, size=0x7ffff19a0570, method=BLOCK_OP_NORMAL, expected_align=0, expected_size=-1) at ../../gcc-svn/trunk/gcc/expr.c:1153 1153 gcc_assert (MEM_P (x) && MEM_P (y)); (gdb) lis 1148 1149 default: 1150 gcc_unreachable (); 1151 } 1152 1153 gcc_assert (MEM_P (x) && MEM_P (y)); 1154 align = MIN (MEM_ALIGN (x), MEM_ALIGN (y)); 1155 gcc_assert (align >= BITS_PER_UNIT); 1156 1157 /* Make sure we've got BLKmode addresses; store_one_arg can decide that
(gdb) p debug_rtx (x) (mem/j/c:BLK (plus:SI (reg/f:SI 54 virtual-stack-vars) (const_int -16 [0xfffffffffffffff0])) [0 a.V4SF+0 S16 A128]) $1 = void (gdb) p debug_rtx (y) (const_vector:V4SF [ (const_double:SF 0.0 [0x0.0p+0]) (const_double:SF 1.0e+0 [0x0.8p+1]) (const_double:SF 2.0e+0 [0x0.8p+2]) (const_double:SF 3.0e+0 [0x0.cp+2]) ]) $2 = void
The test looks nonsensical: it mixes vectors defined with -mno-sse and later used with -msse2. Moving struct A to within 'main' eliminates the ICE, presumably the structure somehow sees the -msse2.
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.
Please note that before your patch, emit_block_move was never called. Following patch fixes testcase for me: --cut here-- Index: expr.c =================================================================== --- expr.c (revision 193296) +++ expr.c (working copy) @@ -5246,19 +5246,12 @@ store_expr (tree exp, rtx target, int call_param_p { 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); - } + if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR) + copy_blkmode_from_reg (target, temp, TREE_TYPE (exp)); else - emit_block_move (target, temp, expr_size (exp), - (call_param_p - ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); + store_bit_field (target, + INTVAL (expr_size (exp)) * BITS_PER_UNIT, + 0, 0, 0, GET_MODE (temp), temp); } else convert_move (target, temp, TYPE_UNSIGNED (TREE_TYPE (exp))); --cut here-- I am running bootstrap and regression test.
> Please note that before your patch, emit_block_move was never called. Indeed, I missed that. > Following patch fixes testcase for me: > > --cut here-- > Index: expr.c > =================================================================== > --- expr.c (revision 193296) > +++ expr.c (working copy) > @@ -5246,19 +5246,12 @@ store_expr (tree exp, rtx target, int call_param_p > { > 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); > - } > + if (REG_P (temp) && TREE_CODE (exp) == CALL_EXPR) > + copy_blkmode_from_reg (target, temp, TREE_TYPE (exp)); > else > - emit_block_move (target, temp, expr_size (exp), > - (call_param_p > - ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); > + store_bit_field (target, > + INTVAL (expr_size (exp)) * BITS_PER_UNIT, > + 0, 0, 0, GET_MODE (temp), temp); > } > else > convert_move (target, temp, TYPE_UNSIGNED (TREE_TYPE (exp))); This looks fine, although this is papering over the real problem: (gdb) p debug_tree(field) <field_decl 0x7ffff6dfe390 V4SF type <vector_type 0x7ffff6df75e8 type <real_type 0x7ffff6d1de70 float SF size <integer_cst 0x7ffff6d09d40 constant 32> unit size <integer_cst 0x7ffff6d09d60 constant 4> align 32 symtab 0 alias set -1 canonical type 0x7ffff6d1de70 precision 32 pointer_to_this <pointer_type 0x7ffff6d250a8>> sizes-gimplified V4SF size <integer_cst 0x7ffff6d212a0 constant 128> unit size <integer_cst 0x7ffff6d212c0 constant 16> align 128 symtab 0 alias set -1 canonical type 0x7ffff6df75e8 nunits 4> BLK file pr44948-2a.c line 12 col 9 size <integer_cst 0x7ffff6d212a0 128> unit size <integer_cst 0x7ffff6d212c0 16> align 128 offset_align 128 offset <integer_cst 0x7ffff6d09d80 type <integer_type 0x7ffff6d1d000 sizetype> constant 0> bit offset <integer_cst 0x7ffff6d09e00 type <integer_type 0x7ffff6d1d0a8 bitsizetype> constant 0> context <record_type 0x7ffff6e342a0 A>> (gdb) p field->decl_common.mode $20 = BLKmode (gdb) p field->typed.type->type_common.mode $21 = V4SFmode The field has BLKmode as DECL_MODE but V4SFmode as TYPE_MODE (TREE_TYPE) so a VIEW_CONVERT_EXPR is missing somewhere if we need to support this nonsense...
Author: uros Date: Wed Nov 7 22:34:48 2012 New Revision: 193314 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=193314 Log: PR middle-end/55235 * expr.c (store_expr): Do not call emit_block_move for non-BLKmode values. Modified: trunk/gcc/ChangeLog trunk/gcc/expr.c
Fixed.