https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118217

            Bug ID: 118217
           Summary: Dot-product for square on difference of two small type
                    integers
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: fxue at os dot amperecomputing.com
  Target Milestone: ---

Consider a case:

  int foo(const signed char *a, const signed char *b, int n)
  {
    int sum = 0;

    for (int i = 0; i < n; ++i) {
      int diff = a[i] - b[i];

      sum += diff * diff;
    }
    return sum;
  }

In the case, "diff" is only referenced in a square expression. For architecture
that has absolute difference instruction(IFN_ABD), such as aarch64, we could
think that there is a hidden abs() around "diff", which ends up with equivalent
result as original, in that abs(diff) * abs(diff) = diff * diff. One advantage
of this transformation is that we could compute abs(diff) with ABD instruction,
at the same time, keeps the result as the same width with two operands, and
this exposes an opportunity to generate a more compact dot-product to avoid
type-conversions, then code-gen could be as:

  int foo(const signed char *a, const signed char *b, int n)
  {
    int sum = 0;

    for (int i = 0; i < n; i += 16) {
      vector(16) signed char v_a = *(vector(16) signed char *)(&a[i]);
      vector(16) signed char v_b = *(vector(16) signed char *)(&b[i]);
      vector(16) unsigned char v_diff = IFN_ABD(v_a, v_b);

      v_sum += DOT_PROD_EXPR(v_diff, v_diff, v_sum);
    }

    return .REDUC_PLUS(v_sum);
  }

Reply via email to