1  /* { dg-require-effective-target vect_int } */
       2  /* { dg-require-effective-target vect_shift } */
       3  /* { dg-require-effective-target vect_pack_trunc } */
       4  /* { dg-require-effective-target vect_unpack } */
       5  
       6  #include "tree-vect.h"
       7  
       8  #ifndef SIGNEDNESS
       9  #define SIGNEDNESS signed
      10  #define BASE_B -128
      11  #define BASE_C -100
      12  #endif
      13  
      14  #define N 50
      15  
      16  /* Both range analysis and backward propagation from the truncation show
      17     that these calculations can be done in SIGNEDNESS short, with "res"
      18     being extended for the store to d[i].  */
      19  void __attribute__ ((noipa))
      20  f (SIGNEDNESS char *restrict a, SIGNEDNESS char *restrict b,
      21     SIGNEDNESS char *restrict c, int *restrict d)
      22  {
      23    for (int i = 0; i < N; ++i)
      24      {
      25        /* Deliberate use of signed >>.  */
      26        int res = b[i] + c[i];
      27        a[i] = (res + (res >> 1)) >> 2;
      28        d[i] = res;
      29      }
      30  }
      31  
      32  int
      33  main (void)
      34  {
      35    check_vect ();
      36  
      37    SIGNEDNESS char a[N], b[N], c[N];
      38    int d[N];
      39    for (int i = 0; i < N; ++i)
      40      {
      41        b[i] = BASE_B + i * 5;
      42        c[i] = BASE_C + i * 4;
      43        asm volatile ("" ::: "memory");
      44      }
      45    f (a, b, c, d);
      46    for (int i = 0; i < N; ++i)
      47      {
      48        int res = BASE_B + BASE_C + i * 9;
      49        if (a[i] != ((res + (res >> 1)) >> 2))
      50  	__builtin_abort ();
      51        if (d[i] != res)
      52  	__builtin_abort ();
      53      }
      54  
      55    return 0;
      56  }
      57  
      58  /* { dg-final { scan-tree-dump {Splitting statement} "vect" } } */
      59  /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* \+ } "vect" } } */
      60  /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 1} "vect" } } */
      61  /* { dg-final { scan-tree-dump {vect_recog_over_widening_pattern: detected:[^\n]* >> 2} "vect" } } */
      62  /* { dg-final { scan-tree-dump {vect_recog_cast_forwprop_pattern: detected:[^\n]* \(signed char\)} "vect" } } */
      63  /* { dg-final { scan-tree-dump {vector[^ ]* int} "vect" } } */
      64  /* { dg-final { scan-tree-dump-times "vectorized 1 loop" 1 "vect" } } */