aboutsummaryrefslogtreecommitdiff
path: root/gcc/optabs.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-11-01 12:30:39 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-11-01 12:30:39 +0000
commit4b926feae10ecec6555dca641c03a8239a824eab (patch)
tree14a00e419d6b7f3b8f89dc41f37a4d056346f85c /gcc/optabs.c
parentef1d3b57d2d00795c6eb01fe6b8ef6f413163c67 (diff)
downloadgcc-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.c57
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)))
{