]> git.ipfire.org Git - thirdparty/gcc.git/commit
Vect: Optimize truncation for .SAT_SUB operands
authorPan Li <pan2.li@intel.com>
Sun, 30 Jun 2024 02:55:50 +0000 (10:55 +0800)
committerPan Li <pan2.li@intel.com>
Wed, 10 Jul 2024 23:05:37 +0000 (07:05 +0800)
commit3918bea620e826b0df68a9c8492b791a67f294b5
tree0c34a3a078b68f03a7eec1cc95d3092b7de5cf08
parentd8cd8521185436ea45ed48c5dd481277e9b8a98d
Vect: Optimize truncation for .SAT_SUB operands

To get better vectorized code of .SAT_SUB,  we would like to avoid the
truncated operation for the assignment.  For example, as below.

unsigned int _1;
unsigned int _2;
unsigned short int _4;
_9 = (unsigned short int).SAT_SUB (_1, _2);

If we make sure that the _1 is in the range of unsigned short int.  Such
as a def similar to:

_1 = (unsigned short int)_4;

Then we can do the distribute the truncation operation to:

_3 = (unsigned short int) MIN (65535, _2); // aka _3 = .SAT_TRUNC (_2);
_9 = .SAT_SUB (_4, _3);

Then,  we can better vectorized code and avoid the unnecessary narrowing
stmt during vectorization with below stmt(s).

_3 = .SAT_TRUNC(_2); // SI => HI
_9 = .SAT_SUB (_4, _3);

Let's take RISC-V vector as example to tell the changes.  For below
sample code:

__attribute__((noinline))
void test (uint16_t *x, unsigned b, unsigned n)
{
  unsigned a = 0;
  uint16_t *p = x;

  do {
    a = *--p;
    *p = (uint16_t)(a >= b ? a - b : 0);
  } while (--n);
}

Before this patch:
  ...
  .L3:
  vle16.v v1,0(a3)
  vrsub.vx v5,v2,t1
  mv t3,a4
  addw a4,a4,t5
  vrgather.vv v3,v1,v5
  vsetvli zero,zero,e32,m1,ta,ma
  vzext.vf2 v1,v3
  vssubu.vx v1,v1,a1
  vsetvli zero,zero,e16,mf2,ta,ma
  vncvt.x.x.w v1,v1
  vrgather.vv v3,v1,v5
  vse16.v v3,0(a3)
  sub a3,a3,t4
  bgtu t6,a4,.L3
  ...

After this patch:
test:
  ...
  .L3:
  vle16.v     v3,0(a3)
  vrsub.vx    v5,v2,a6
  mv          a7,a4
  addw        a4,a4,t3
  vrgather.vv v1,v3,v5
  vssubu.vv   v1,v1,v6
  vrgather.vv v3,v1,v5
  vse16.v     v3,0(a3)
  sub     a3,a3,t1
  bgtu    t4,a4,.L3
  ...

The below test suites are passed for this patch:
1. The rv64gcv fully regression tests.
2. The rv64gcv build with glibc.
3. The x86 bootstrap tests.
4. The x86 fully regression tests.

gcc/ChangeLog:

* tree-vect-patterns.cc (vect_recog_sat_sub_pattern_transform):
Add new func impl to perform the truncation distribution.
(vect_recog_sat_sub_pattern): Perform above optimize before
generate .SAT_SUB call.

Signed-off-by: Pan Li <pan2.li@intel.com>
gcc/tree-vect-patterns.cc