Hi! On the following testcase, the widen multiplies etc. is introduced so late that no forwprop or ccp follows it. The WIDEN_MULT_EXPR tries hard not to use widening multiply if both arguments are INTEGER_CSTs, but if they are e.g. SSA_NAMEs that expand_normal into CONST_INT, we can still ICE.
The following patch attempts to handle those cases. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8? 2013-05-13 Jakub Jelinek <ja...@redhat.com> PR middle-end/57251 * expr.c (expand_expr_real_2) <case WIDEN_MULT_EXPR>: Handle the case when both op0 and op1 have VOIDmode. * gcc.dg/torture/pr57251.c: New test. --- gcc/expr.c.jj 2013-05-07 10:27:07.000000000 +0200 +++ gcc/expr.c 2013-05-13 12:01:49.339087536 +0200 @@ -8390,6 +8390,15 @@ expand_expr_real_2 (sepops ops, rtx targ else expand_operands (treeop0, treeop1, NULL_RTX, &op1, &op0, EXPAND_NORMAL); + /* op0 and op1 might still be constant, despite the above + != INTEGER_CST check. Handle it. */ + if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode) + { + op0 = convert_modes (innermode, mode, op0, true); + op1 = convert_modes (innermode, mode, op1, false); + return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, + target, unsignedp)); + } goto binop3; } } @@ -8412,6 +8421,19 @@ expand_expr_real_2 (sepops ops, rtx targ { expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL); + /* op0 and op1 might still be constant, despite the above + != INTEGER_CST check. Handle it. */ + if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode) + { + widen_mult_const: + op0 = convert_modes (innermode, mode, op0, zextend_p); + op1 + = convert_modes (innermode, mode, op1, + TYPE_UNSIGNED (TREE_TYPE (treeop1))); + return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, + target, + unsignedp)); + } temp = expand_widening_mult (mode, op0, op1, target, unsignedp, this_optab); return REDUCE_BIT_FIELD (temp); @@ -8424,9 +8446,14 @@ expand_expr_real_2 (sepops ops, rtx targ op0 = expand_normal (treeop0); if (TREE_CODE (treeop1) == INTEGER_CST) op1 = convert_modes (innermode, mode, - expand_normal (treeop1), unsignedp); + expand_normal (treeop1), + TYPE_UNSIGNED (TREE_TYPE (treeop1))); else op1 = expand_normal (treeop1); + /* op0 and op1 might still be constant, despite the above + != INTEGER_CST check. Handle it. */ + if (GET_MODE (op0) == VOIDmode && GET_MODE (op1) == VOIDmode) + goto widen_mult_const; temp = expand_binop (mode, other_optab, op0, op1, target, unsignedp, OPTAB_LIB_WIDEN); hipart = gen_highpart (innermode, temp); --- gcc/testsuite/gcc.dg/torture/pr57251.c.jj 2013-05-13 11:46:34.937151578 +0200 +++ gcc/testsuite/gcc.dg/torture/pr57251.c 2013-05-13 11:54:23.070414122 +0200 @@ -0,0 +1,12 @@ +/* PR middle-end/57251 */ +/* { dg-do compile } */ +/* { dg-options "-ftracer" } */ + +short a, b; +int +f (void) +{ + long long i = 2; + a ? f () ? : 0 : b--; + b &= i *= a |= 0; +} Jakub