diff options
author | Richard Sandiford <richard.sandiford@linaro.org> | 2017-11-01 12:30:39 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2017-11-01 12:30:39 +0000 |
commit | 4b926feae10ecec6555dca641c03a8239a824eab (patch) | |
tree | 14a00e419d6b7f3b8f89dc41f37a4d056346f85c /gcc/optabs.c | |
parent | ef1d3b57d2d00795c6eb01fe6b8ef6f413163c67 (diff) | |
download | gcc-4b926feae10ecec6555dca641c03a8239a824eab.zip gcc-4b926feae10ecec6555dca641c03a8239a824eab.tar.gz gcc-4b926feae10ecec6555dca641c03a8239a824eab.tar.bz2 |
Widening optab cleanup
widening_optab_handler had the comment:
/* ??? Why does find_widening_optab_handler_and_mode attempt to
widen things that can't be widened? E.g. add_optab... */
if (op > LAST_CONV_OPTAB)
return CODE_FOR_nothing;
I think it comes from expand_binop using
find_widening_optab_handler_and_mode for two things: to test whether
a "normal" optab like add_optab is supported for a standard binary
operation and to test whether a "convert" optab is supported for a
widening operation like umul_widen_optab. In the former case from_mode
and to_mode must be the same, in the latter from_mode must be narrower
than to_mode.
For the former case, find_widening_optab_handler_and_mode is only really
testing the modes that are passed in. permit_non_widening must be true
here.
For the latter case, find_widening_optab_handler_and_mode should only
really consider new from_modes that are wider than the original
from_mode and narrower than the original to_mode. Logically
permit_non_widening should be false, since widening optabs aren't
supposed to take operands that are the same width as the destination.
We get away with permit_non_widening being true because no target
would/should define a widening .md pattern with matching modes.
But really, it seems better for expand_binop to handle these two
cases itself rather than pushing them down. With that change,
find_widening_optab_handler_and_mode is only ever called with
permit_non_widening set to false and is only ever called with
a "proper" convert optab. We then no longer need widening_optab_handler,
we can just use convert_optab_handler directly.
The patch also passes the instruction code down to expand_binop_directly.
This should be more efficient and removes an extra call to
find_widening_optab_handler_and_mode.
2017-11-01 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
gcc/
* optabs-query.h (convert_optab_p): New function, split out from...
(convert_optab_handler): ...here.
(widening_optab_handler): Delete.
(find_widening_optab_handler): Remove permit_non_widening parameter.
(find_widening_optab_handler_and_mode): Likewise. Provide an
override that operates on mode class wrappers.
* optabs-query.c (widening_optab_handler): Delete.
(find_widening_optab_handler_and_mode): Remove permit_non_widening
parameter. Assert that the two modes are the same class and that
the "from" mode is narrower than the "to" mode. Use
convert_optab_handler instead of widening_optab_handler.
* expmed.c (expmed_mult_highpart_optab): Use convert_optab_handler
instead of widening_optab_handler.
* expr.c (expand_expr_real_2): Update calls to
find_widening_optab_handler.
* optabs.c (expand_widen_pattern_expr): Likewise.
(expand_binop_directly): Take the insn_code as a parameter.
(expand_binop): Only call find_widening_optab_handler for
conversion optabs; use optab_handler otherwise. Update calls
to find_widening_optab_handler and expand_binop_directly.
Use convert_optab_handler instead of widening_optab_handler.
* tree-ssa-math-opts.c (convert_mult_to_widen): Update calls to
find_widening_optab_handler and use scalar_mode rather than
machine_mode.
(convert_plusminus_to_widen): Likewise.
Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r254302
Diffstat (limited to 'gcc/optabs.c')
-rw-r--r-- | gcc/optabs.c | 57 |
1 files changed, 33 insertions, 24 deletions
diff --git a/gcc/optabs.c b/gcc/optabs.c index 7b3d595..7cf4d8e 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -264,7 +264,7 @@ expand_widen_pattern_expr (sepops ops, rtx op0, rtx op1, rtx wide_op, || ops->code == WIDEN_MULT_MINUS_EXPR) icode = find_widening_optab_handler (widen_pattern_optab, TYPE_MODE (TREE_TYPE (ops->op2)), - tmode0, 0); + tmode0); else icode = optab_handler (widen_pattern_optab, tmode0); gcc_assert (icode != CODE_FOR_nothing); @@ -979,17 +979,14 @@ avoid_expensive_constant (machine_mode mode, optab binoptab, } /* Helper function for expand_binop: handle the case where there - is an insn that directly implements the indicated operation. + is an insn ICODE that directly implements the indicated operation. Returns null if this is not possible. */ static rtx -expand_binop_directly (machine_mode mode, optab binoptab, +expand_binop_directly (enum insn_code icode, machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx target, int unsignedp, enum optab_methods methods, rtx_insn *last) { - machine_mode from_mode = widened_mode (mode, op0, op1); - enum insn_code icode = find_widening_optab_handler (binoptab, mode, - from_mode, 1); machine_mode xmode0 = insn_data[(int) icode].operand[1].mode; machine_mode xmode1 = insn_data[(int) icode].operand[2].mode; machine_mode mode0, mode1, tmp_mode; @@ -1113,6 +1110,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, = (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN ? OPTAB_WIDEN : methods); enum mode_class mclass; + enum insn_code icode; machine_mode wider_mode; scalar_int_mode int_mode; rtx libfunc; @@ -1146,23 +1144,30 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, /* If we can do it with a three-operand insn, do so. */ - if (methods != OPTAB_MUST_WIDEN - && find_widening_optab_handler (binoptab, mode, - widened_mode (mode, op0, op1), 1) - != CODE_FOR_nothing) + if (methods != OPTAB_MUST_WIDEN) { - temp = expand_binop_directly (mode, binoptab, op0, op1, target, - unsignedp, methods, last); - if (temp) - return temp; + if (convert_optab_p (binoptab)) + { + machine_mode from_mode = widened_mode (mode, op0, op1); + icode = find_widening_optab_handler (binoptab, mode, from_mode); + } + else + icode = optab_handler (binoptab, mode); + if (icode != CODE_FOR_nothing) + { + temp = expand_binop_directly (icode, mode, binoptab, op0, op1, + target, unsignedp, methods, last); + if (temp) + return temp; + } } /* If we were trying to rotate, and that didn't work, try rotating the other direction before falling back to shifts and bitwise-or. */ if (((binoptab == rotl_optab - && optab_handler (rotr_optab, mode) != CODE_FOR_nothing) + && (icode = optab_handler (rotr_optab, mode)) != CODE_FOR_nothing) || (binoptab == rotr_optab - && optab_handler (rotl_optab, mode) != CODE_FOR_nothing)) + && (icode = optab_handler (rotl_optab, mode)) != CODE_FOR_nothing)) && is_int_mode (mode, &int_mode)) { optab otheroptab = (binoptab == rotl_optab ? rotr_optab : rotl_optab); @@ -1178,7 +1183,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, gen_int_mode (bits, GET_MODE (op1)), op1, NULL_RTX, unsignedp, OPTAB_DIRECT); - temp = expand_binop_directly (int_mode, otheroptab, op0, newop1, + temp = expand_binop_directly (icode, int_mode, otheroptab, op0, newop1, target, unsignedp, methods, last); if (temp) return temp; @@ -1225,7 +1230,8 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, else if (binoptab == rotr_optab) otheroptab = vrotr_optab; - if (otheroptab && optab_handler (otheroptab, mode) != CODE_FOR_nothing) + if (otheroptab + && (icode = optab_handler (otheroptab, mode)) != CODE_FOR_nothing) { /* The scalar may have been extended to be too wide. Truncate it back to the proper size to fit in the broadcast vector. */ @@ -1239,7 +1245,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, rtx vop1 = expand_vector_broadcast (mode, op1); if (vop1) { - temp = expand_binop_directly (mode, otheroptab, op0, vop1, + temp = expand_binop_directly (icode, mode, otheroptab, op0, vop1, target, unsignedp, methods, last); if (temp) return temp; @@ -1262,7 +1268,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, && (find_widening_optab_handler ((unsignedp ? umul_widen_optab : smul_widen_optab), - next_mode, mode, 0) + next_mode, mode) != CODE_FOR_nothing))) { rtx xop0 = op0, xop1 = op1; @@ -1693,7 +1699,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, && optab_handler (add_optab, word_mode) != CODE_FOR_nothing) { rtx product = NULL_RTX; - if (widening_optab_handler (umul_widen_optab, int_mode, word_mode) + if (convert_optab_handler (umul_widen_optab, int_mode, word_mode) != CODE_FOR_nothing) { product = expand_doubleword_mult (int_mode, op0, op1, target, @@ -1703,7 +1709,7 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, } if (product == NULL_RTX - && (widening_optab_handler (smul_widen_optab, int_mode, word_mode) + && (convert_optab_handler (smul_widen_optab, int_mode, word_mode) != CODE_FOR_nothing)) { product = expand_doubleword_mult (int_mode, op0, op1, target, @@ -1796,10 +1802,13 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, if (CLASS_HAS_WIDER_MODES_P (mclass)) { + /* This code doesn't make sense for conversion optabs, since we + wouldn't then want to extend the operands to be the same size + as the result. */ + gcc_assert (!convert_optab_p (binoptab)); FOR_EACH_WIDER_MODE (wider_mode, mode) { - if (find_widening_optab_handler (binoptab, wider_mode, mode, 1) - != CODE_FOR_nothing + if (optab_handler (binoptab, wider_mode) || (methods == OPTAB_LIB && optab_libfunc (binoptab, wider_mode))) { |