Index: gcc/simplify-rtx.c =================================================================== --- gcc/simplify-rtx.c (revision 173242) +++ gcc/simplify-rtx.c (working copy) @@ -1000,6 +1000,23 @@ simplify_unary_operation_1 (enum rtx_cod && GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF) return XEXP (op, 0); + /* Extending a widening multiplication should be canonicalized to + a wider widening multiplication. */ + if (GET_CODE (op) == MULT + && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND + && GET_CODE (XEXP (op, 1)) == SIGN_EXTEND) + { + rtx op0 = XEXP (XEXP (op, 0), 0); + rtx op1 = XEXP (XEXP (op, 1), 0); + enum machine_mode op0_mode = GET_MODE (op0); + enum machine_mode op1_mode = GET_MODE (op1); + return simplify_gen_binary (MULT, mode, + simplify_gen_unary (SIGN_EXTEND, mode, + op0, op0_mode), + simplify_gen_unary (SIGN_EXTEND, mode, + op1, op1_mode)); + } + /* Check for a sign extension of a subreg of a promoted variable, where the promotion is sign-extended, and the target mode is the same as the variable's promotion. */ @@ -1071,6 +1088,23 @@ simplify_unary_operation_1 (enum rtx_cod && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0)))) return rtl_hooks.gen_lowpart_no_emit (mode, op); + /* Extending a widening multiplication should be canonicalized to + a wider widening multiplication. */ + if (GET_CODE (op) == MULT + && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND + && GET_CODE (XEXP (op, 1)) == ZERO_EXTEND) + { + rtx op0 = XEXP (XEXP (op, 0), 0); + rtx op1 = XEXP (XEXP (op, 1), 0); + enum machine_mode op0_mode = GET_MODE (op0); + enum machine_mode op1_mode = GET_MODE (op1); + return simplify_gen_binary (MULT, mode, + simplify_gen_unary (ZERO_EXTEND, mode, + op0, op0_mode), + simplify_gen_unary (ZERO_EXTEND, mode, + op1, op1_mode)); + } + /* (zero_extend:M (zero_extend:N )) is (zero_extend:M ). */ if (GET_CODE (op) == ZERO_EXTEND) return simplify_gen_unary (ZERO_EXTEND, mode, XEXP (op, 0),