For int test(long long a, long long b) { return a * b; } GCC generates a widening multiply, and cannot remove the DImode operations until after register allocation. This causes unnecessary splits. This could be fixed on the tree level by folding to (int)a * (int)b, or alternatively in expand. expand_expr is called with <mult_expr 0x2aaaae9032c0 type <integer_type 0x2aaaae937840 long long int DI> arg 0 <parm_decl 0x2aaaae92d2d0 b type <integer_type 0x2aaaae937840 long long int>> arg 1 <parm_decl 0x2aaaae92d240 a type <integer_type 0x2aaaae937840 long long int>>> and tmode SImode, still enough info to choose a better multiply. However, tmode is not passed on to expand_mult.
Prototype untested patch. Produces movl 12(%esp), %eax imull 4(%esp), %eax ret on the testcase. Index: expr.c =================================================================== --- expr.c (revision 130928) +++ expr.c (working copy) @@ -8642,7 +8642,8 @@ expand_expr_real_1 (tree exp, rtx target } expand_operands (TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1), subtarget, &op0, &op1, 0); - return REDUCE_BIT_FIELD (expand_mult (mode, op0, op1, target, unsignedp)); + return REDUCE_BIT_FIELD (expand_mult (tmode != VOIDmode ? tmode : mode, + op0, op1, target, unsignedp)); case TRUNC_DIV_EXPR: case FLOOR_DIV_EXPR:
Shouldn't tmode be only used if GET_MODE_CLASS (tmode) == MODE_INT && GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_BITSIZE (tmode) < GET_MODE_BITSIZE (mode), to make sure we optimize only narrow, never widen, and that float etc. multiplication is not affected?
Makes a lot of sense. I made the patch only to test that it would not crash, or something like that.
(In reply to comment #1) > Prototype untested patch. Produces Paolo, do you plan to test your patch and submit it to gcc-patches@ ?
I want to clear 17236 first (and Jakub's tweaks are needed anyway). Feel free to beat me to it.
testing
The expand patch does not bootstrap, even with the tweaks Jakub suggested. I'm also hesitant to fold it on the tree level because it's actually undefined code unless -fwrapv. For example if a = b = 65536LL, (int) a * (int) b = undefined (int) (a * b) = (int) (1LL << 32) = 0
Hmm maybe I can go through an unsigned type.
fixed in 4.4
Fixed by r133144 and r133163 (with wrong PR number in the changelogs)