On November 16, 2018 10:23:33 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> 
wrote:
>Hi!
>
>The documentation for this function says that it wants to go through
>all
>(integral) conversions (both promotions and demotions), as long as the
>whole sequence of conversions is functionally equivalent to
>(optionally)
>casting the returned value to a signed or unsigned type with the same
>precision as the returned value (depending on the ->type filled in)
>and then (optionally) promoting it to the original argument's type.
>
>On the following testcase, we have:
>  _39 = (long int) iftmp.0_19;
>in the loop and
>  _4 = _2 >> a.4_3;
>  iftmp.0_19 = (signed char) _4;
>before the loop, with
>  int _4;
>  signed char iftmp.0_19;
>  long int _39;
>Currently we return _4, which is incorrect, we can't represent the
>series of
>conversions as simple zero or sign extension from int to long int,
>because
>there is a (signed char) cast in the middle.  So, instead of returning
>_4 we
>need to return iftmp.0_19 in this case.  That doesn't mean we need to
>stop
>the search for further candidates at that point, but just that all
>further
>candidates need to be at most with that precision.
>
>The following patch fixes that, bootstrapped/regtested on x86_64-linux
>and
>i686-linux, ok for trunk?

OK. 

Richard. 

>2018-11-16  Jakub Jelinek  <ja...@redhat.com>
>
>       PR tree-optimization/87546
>       * tree-vect-patterns.c (vect_look_through_possible_promotion): Add
>       min_precision variable, initially set it to orig_precision, only does
>       something if op_type's precision is <= min_precision and update
>       min_precision whenever calling set_op.
>
>       * gcc.dg/vect/O3-pr87546.c: New test.
>
>--- gcc/tree-vect-patterns.c.jj        2018-10-23 10:13:25.200876565 +0200
>+++ gcc/tree-vect-patterns.c   2018-11-16 16:53:08.668610905 +0100
>@@ -367,6 +367,7 @@ vect_look_through_possible_promotion (ve
>   tree res = NULL_TREE;
>   tree op_type = TREE_TYPE (op);
>   unsigned int orig_precision = TYPE_PRECISION (op_type);
>+  unsigned int min_precision = orig_precision;
>   stmt_vec_info caster = NULL;
>   while (TREE_CODE (op) == SSA_NAME && INTEGRAL_TYPE_P (op_type))
>     {
>@@ -385,7 +386,7 @@ vect_look_through_possible_promotion (ve
>        This copes with cases such as the result of an arithmetic
>        operation being truncated before being stored, and where that
>        arithmetic operation has been recognized as an over-widened one.  */
>-      if (TYPE_PRECISION (op_type) <= orig_precision)
>+      if (TYPE_PRECISION (op_type) <= min_precision)
>       {
>         /* Use OP as the UNPROM described above if we haven't yet
>            found a promotion, or if using the new input preserves the
>@@ -393,7 +394,10 @@ vect_look_through_possible_promotion (ve
>         if (!res
>             || TYPE_PRECISION (unprom->type) == orig_precision
>             || TYPE_SIGN (unprom->type) == TYPE_SIGN (op_type))
>-          unprom->set_op (op, dt, caster);
>+          {
>+            unprom->set_op (op, dt, caster);
>+            min_precision = TYPE_PRECISION (op_type);
>+          }
>         /* Stop if we've already seen a promotion and if this
>            conversion does more than change the sign.  */
>         else if (TYPE_PRECISION (op_type)
>--- gcc/testsuite/gcc.dg/vect/O3-pr87546.c.jj  2018-11-16
>17:03:39.294149070 +0100
>+++ gcc/testsuite/gcc.dg/vect/O3-pr87546.c     2018-11-16
>17:05:25.620385151 +0100
>@@ -0,0 +1,29 @@
>+#include "tree-vect.h"
>+
>+int a;
>+long b, f;
>+signed char c, g;
>+short int d = 219;
>+int e[64];
>+
>+__attribute__((noipa)) void
>+foo (void)
>+{
>+  asm volatile ("" : : "g" (&a), "g" (&d) : "memory");
>+  for (c = 0; c < 64; c++)
>+    {
>+      g = d < 0 ? d : d >> a;
>+      f = g + b;
>+      e[c] = f;
>+    }
>+  if (e[1] != (signed char) d)
>+    __builtin_abort ();
>+}
>+
>+int
>+main ()
>+{
>+  check_vect ();
>+  foo ();
>+  return 0;
>+}
>
>
>       Jakub

Reply via email to