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