[12/n] PR85694: Rework detection of widened operations
authorRichard Sandiford <richard.sandiford@arm.com>
Sat, 30 Jun 2018 12:49:06 +0000 (12:49 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 30 Jun 2018 12:49:06 +0000 (12:49 +0000)
commit003479340f5ae6b7407b5c92e3e1915101552377
tree51918c55262a737b8078aa62210f1d5bf92c4471
parent41949de9de0c8ebabb7adb2701e775ecd671aa72
[12/n] PR85694: Rework detection of widened operations

This patch adds helper functions for detecting widened operations and
generalises the existing code to handle more cases.

One of the main changes is to recognise multi-stage type conversions,
which are possible even in the original IR and can also occur as a
result of earlier pattern matching (especially after the main
over-widening patch).  E.g. for:

  unsigned int res = 0;
  for (__INTPTR_TYPE__ i = 0; i < N; ++i)
    {
      int av = a[i];
      int bv = b[i];
      short diff = av - bv;
      unsigned short abs = diff < 0 ? -diff : diff;
      res += abs;
    }

we have:

  _9 = _7 - _8;
  diff_20 = (short int) _9;
  _10 = (int) diff_20;
  _11 = ABS_EXPR <_10>;

where the first cast establishes the sign of the promotion done
by the second cast.

vect_recog_sad_pattern didn't handle this kind of intermediate promotion
between the MINUS_EXPR and the ABS_EXPR.  Sign extensions and casts from
unsigned to signed are both OK there.  Unsigned promotions aren't, and
need to be rejected, but should have been folded away earlier anyway.

Also, the dot_prod and widen_sum patterns both required the promotions
to be from one signedness to the same signedness, rather than say signed
char to unsigned int.  That shouldn't be necessary, since it's only the
sign of the input to the promotion that matters.  Nothing requires the
narrow and wide types in a DOT_PROD_EXPR or WIDEN_SUM_EXPR to have the
same sign (and IMO that's a good thing).

Fixing these fixed an XFAIL in gcc.dg/vect/vect-widen-mult-sum.c.

vect_widened_op_tree is a bit more general than the current patch needs,
since it copes with a tree of operations rather than a single statement.
This is used by the later average-detection patch.

The patch also uses a common routine to handle both the WIDEN_MULT_EXPR
and WIDEN_LSHIFT_EXPR patterns.  I hope this could be reused for other
similar operations in future.

Also, the patch means we recognise the index calculations in
vect-mult-const-pattern*.c as widening multiplications, whereas the
scan test was expecting them to be recognised as mult patterns instead.
The patch makes the tests check specifically for the multiplication we
care about.

2018-06-30  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* tree-vect-patterns.c (append_pattern_def_seq): Take an optional
vector type.  If given, install it in the new statement's
STMT_VINFO_VECTYPE.
(vect_element_precision): New function.
(vect_unpromoted_value): New struct.
(vect_unpromoted_value::vect_unpromoted_value): New function.
(vect_unpromoted_value::set_op): Likewise.
(vect_look_through_possible_promotion): Likewise.
(vect_joust_widened_integer, vect_joust_widened_type): Likewise.
(vect_widened_op_tree, vect_convert_input): Likewise.
(vect_convert_inputs, vect_convert_output): Likewise.
(vect_recog_dot_prod_pattern): Use vect_look_through_possible_promotion
to handle the optional cast of the multiplication result and
vect_widened_op_tree to detect the widened multiplication itself.
Do not require the input and output of promotion casts to have
the same sign, but base the signedness of the operation on the
input rather than the result.  If the pattern includes two
promotions, check that those promotions have the same sign.
Do not restrict the MULT_EXPR handling to a double-width result;
handle quadruple-width results and wider.  Use vect_convert_inputs
to convert the inputs to the common type.
(vect_recog_sad_pattern):  Use vect_look_through_possible_promotion
to handle the optional cast of the ABS result.  Also allow a sign
change or a sign extension between the ABS and MINUS.
Use vect_widened_op_tree to detect the widened subtraction and use
vect_convert_inputs to convert the inputs to the common type.
(vect_handle_widen_op_by_const): Delete.
(vect_recog_widen_op_pattern): New function.
(vect_recog_widen_mult_pattern): Use it.
(vect_recog_widen_shift_pattern): Likewise.
(vect_recog_widen_sum_pattern): Use
vect_look_through_possible_promotion to handle the promoted
PLUS_EXPR operand.

gcc/testsuite/
* gcc.dg/vect/vect-widen-mult-sum.c: Remove xfail.
* gcc.dg/vect/no-scevccp-outer-6.c: Don't match widened multiplications
by 4 in the computation of a[i].
* gcc.dg/vect/vect-mult-const-pattern-1.c: Test specifically for the
main multiplication constant.
* gcc.dg/vect/vect-mult-const-pattern-2.c: Likewise.
* gcc.dg/vect/vect-widen-mult-const-s16.c: Likewise.
* gcc.dg/vect/vect-widen-mult-const-u16.c: Likewise.  Expect the
pattern to cast the result to int.
* gcc.dg/vect/vect-reduc-dot-1.c: New test.
* gcc.dg/vect/vect-reduc-dot-2.c: Likewise.
* gcc.dg/vect/vect-reduc-dot-3.c: Likewise.
* gcc.dg/vect/vect-reduc-dot-4.c: Likewise.
* gcc.dg/vect/vect-reduc-dot-5.c: Likewise.
* gcc.dg/vect/vect-reduc-dot-6.c: Likewise.
* gcc.dg/vect/vect-reduc-dot-7.c: Likewise.
* gcc.dg/vect/vect-reduc-dot-8.c: Likewise.
* gcc.dg/vect/vect-reduc-sad-1.c: Likewise.
* gcc.dg/vect/vect-reduc-sad-2.c: Likewise.
* gcc.dg/vect/vect-reduc-sad-3.c: Likewise.
* gcc.dg/vect/vect-reduc-sad-4.c: Likewise.
* gcc.dg/vect/vect-reduc-sad-5.c: Likewise.
* gcc.dg/vect/vect-reduc-sad-6.c: Likewise.
* gcc.dg/vect/vect-reduc-sad-7.c: Likewise.
* gcc.dg/vect/vect-reduc-sad-8.c: Likewise.
* gcc.dg/vect/vect-widen-mult-1.c: Likewise.
* gcc.dg/vect/vect-widen-mult-2.c: Likewise.
* gcc.dg/vect/vect-widen-mult-3.c: Likewise.
* gcc.dg/vect/vect-widen-mult-4.c: Likewise.

From-SVN: r262276
29 files changed:
gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/no-scevccp-outer-6.c
gcc/testsuite/gcc.dg/vect/vect-mult-const-pattern-1.c
gcc/testsuite/gcc.dg/vect/vect-mult-const-pattern-2.c
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-dot-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-sad-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-sad-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-sad-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-sad-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-sad-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-sad-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-sad-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-reduc-sad-8.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-widen-mult-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-widen-mult-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-widen-mult-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-widen-mult-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-s16.c
gcc/testsuite/gcc.dg/vect/vect-widen-mult-const-u16.c
gcc/testsuite/gcc.dg/vect/vect-widen-mult-sum.c
gcc/tree-vect-patterns.c