Coverage Report

Created: 2025-10-13 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xnnpack/src/qd8-f16-qc4w-gemm/gen/qd8-f16-qc4w-gemm-1x8c8-minmax-avx256vnni.c
Line
Count
Source
1
// clang-format off
2
// Auto-generated file. Do not edit!
3
//   Template: src/qs8-gemm/MRx8c8-avxvnni.c.in
4
//   Generator: tools/xngen
5
//
6
// Copyright 2024 Google LLC
7
//
8
// This source code is licensed under the BSD-style license found in the
9
// LICENSE file in the root directory of this source tree.
10
11
#include <assert.h>
12
#include <stddef.h>
13
#include <stdint.h>
14
15
#include <immintrin.h>
16
17
#include "src/xnnpack/common.h"
18
#include "src/xnnpack/gemm.h"
19
#include "src/xnnpack/intrinsics-polyfill.h"
20
#include "src/xnnpack/math.h"
21
#include "src/xnnpack/microparams.h"
22
#include "src/xnnpack/unaligned.h"
23
24
25
void xnn_qd8_f16_qc4w_gemm_minmax_ukernel_1x8c8__avx256vnni(
26
    size_t mr,
27
    size_t nc,
28
    size_t kc,
29
    const int8_t* restrict a,
30
    size_t a_stride,
31
    const void* restrict w,
32
    xnn_float16* restrict c,
33
    size_t cm_stride,
34
    size_t cn_stride,
35
    const struct xnn_f16_qc4w_minmax_params* restrict params,
36
    const struct xnn_qd8_quantization_params* restrict quantization_params) XNN_OOB_READS
37
0
{
38
0
  assert(mr != 0);
39
0
  assert(mr <= 1);
40
0
  assert(nc != 0);
41
0
  assert(kc != 0);
42
0
  assert(kc % sizeof(int8_t) == 0);
43
0
  assert(a != NULL);
44
0
  assert(w != NULL);
45
0
  assert(c != NULL);
46
47
0
  kc = round_up_po2(kc, 8 * sizeof(int8_t));
48
0
  const int8_t* a0 = a;
49
0
  uint16_t* c0 = (uint16_t*) c;
50
51
0
  const __m256i vinput_zero_point0 = _mm256_set1_epi32((int) quantization_params[0].zero_point);
52
0
  const __m256 voutput_min = _mm256_cvtph_ps(_mm_set1_epi16(*(const uint16_t*) &params->scalar.min));
53
0
  const __m256 voutput_max = _mm256_cvtph_ps(_mm_set1_epi16(*(const uint16_t*) &params->scalar.max));
54
  // XNN_FORCE_REALIZATION(voutput_min);
55
  // XNN_FORCE_REALIZATION(voutput_max);
56
0
  const __m256i vmask = _mm256_set1_epi8(0xF0);
57
0
  XNN_FORCE_REALIZATION(vmask);
58
0
  do {
59
0
    const __m256i vksum01234567 = _mm256_load_si256(w);
60
0
    __m256i vsum0x01234567 = _mm256_mullo_epi32(vksum01234567, vinput_zero_point0);
61
0
    __m256i vacc0x0123 = _mm256_cvtepu32_epi64(_mm256_extracti128_si256(vsum0x01234567, 0));
62
0
    __m256i vacc0x4567 = _mm256_cvtepu32_epi64(_mm256_extracti128_si256(vsum0x01234567, 1));
63
0
    __m256i vacc1x0x0123 = _mm256_setzero_si256();
64
0
    __m256i vacc1x0x4567 = _mm256_setzero_si256();
65
0
    w = (const int32_t*) w + 8;
66
67
0
    size_t k = kc;
68
0
    while (k >= 16 * sizeof(int8_t)) {
69
0
      const __m256i va0x01234567 = _mm256_set1_epi64x((int64_t) unaligned_load_u64(a0));
70
0
      const __m256i va0x89ABCDEF = _mm256_set1_epi64x((int64_t) unaligned_load_u64(a0 + 8));
71
0
      a0 += 16;
72
73
0
      const __m256i vbb01234567x01234567 = _mm256_load_si256(w);
74
0
      const __m256i vbb89ABCDEFx01234567 = _mm256_load_si256((const __m256i*) ((const int8_t*) w + 32));
75
0
      const __m256i vbs01234567x0123 = _mm256_slli_epi32(vbb01234567x01234567, 4);
76
0
      const __m256i vbs89ABCDEFx0123 = _mm256_slli_epi32(vbb89ABCDEFx01234567, 4);
77
0
      const __m256i vb01234567x4567 = _mm256_and_si256(vbb01234567x01234567, vmask);
78
0
      const __m256i vb89ABCDEFx4567 = _mm256_and_si256(vbb89ABCDEFx01234567, vmask);
79
0
      const __m256i vb01234567x0123 = _mm256_and_si256(vbs01234567x0123, vmask);
80
0
      const __m256i vb89ABCDEFx0123 = _mm256_and_si256(vbs89ABCDEFx0123, vmask);
81
82
0
      vacc0x0123 = _mm256_dpbusd_epi32(vacc0x0123, va0x01234567, vb01234567x0123);
83
0
      vacc0x4567 = _mm256_dpbusd_epi32(vacc0x4567, va0x01234567, vb89ABCDEFx0123);
84
0
      vacc1x0x0123 = _mm256_dpbusd_epi32(vacc1x0x0123, va0x89ABCDEF, vb01234567x4567);
85
0
      vacc1x0x4567 = _mm256_dpbusd_epi32(vacc1x0x4567, va0x89ABCDEF, vb89ABCDEFx4567);
86
87
0
      w = (const int8_t*) w + 64;
88
0
      k -= 16 * sizeof(int8_t);
89
0
    }
90
91
0
    if (k != 0) {
92
0
      const __m256i va0x01234567 = _mm256_set1_epi64x((int64_t) unaligned_load_u64(a0));
93
0
      a0 += 8;
94
95
0
      const __m256i vbb01234567x01234567 = _mm256_load_si256(w);
96
0
      const __m256i vbb89ABCDEFx01234567 = _mm256_load_si256((const __m256i*) ((const int8_t*) w + 32));
97
0
      const __m256i vb01234567x0123 = _mm256_slli_epi32(vbb01234567x01234567, 4);
98
0
      const __m256i vb89ABCDEFx0123 = _mm256_slli_epi32(vbb89ABCDEFx01234567, 4);
99
100
0
      vacc0x0123 = _mm256_dpbusd_epi32(vacc0x0123, va0x01234567, vb01234567x0123);
101
0
      vacc0x4567 = _mm256_dpbusd_epi32(vacc0x4567, va0x01234567, vb89ABCDEFx0123);
102
103
0
      w = (const int8_t*) w + 64;
104
0
      k -= 8 * sizeof(int8_t);
105
0
    }
106
0
    vacc0x0123 = _mm256_add_epi32(vacc0x0123, vacc1x0x0123);
107
0
    vacc0x4567 = _mm256_add_epi32(vacc0x4567, vacc1x0x4567);
108
109
    // Add adjacent pairs
110
0
    const __m256i vsum0x02134657 = _mm256_hadd_epi32(vacc0x0123, vacc0x4567);
111
0
    __m256i vacc0x01234567 = _mm256_permute4x64_epi64(vsum0x02134657, _MM_SHUFFLE(3, 1, 2, 0));
112
113
0
    vacc0x01234567 = _mm256_srai_epi32(vacc0x01234567, 4);
114
0
    __m256 vout0x01234567 = _mm256_cvtepi32_ps(vacc0x01234567);
115
116
0
    vout0x01234567 = _mm256_mul_ps(vout0x01234567, _mm256_set1_ps(quantization_params[0].inv_scale));
117
118
0
    const __m256 vfilter_output_scale01234567 = _mm256_load_ps((const float*) w);
119
0
    const __m256 vbias01234567 = _mm256_load_ps((const float*) w + 8);
120
0
    w = (const float*) w + 16;
121
122
0
    vout0x01234567 = _mm256_fmadd_ps(vout0x01234567, vfilter_output_scale01234567, vbias01234567);
123
124
0
    vout0x01234567 = _mm256_max_ps(vout0x01234567, voutput_min);
125
126
0
    vout0x01234567 = _mm256_min_ps(vout0x01234567, voutput_max);
127
128
0
    __m128i vfp16out0x01234567 = _mm256_cvtps_ph(vout0x01234567, _MM_FROUND_TO_NEAREST_INT);
129
0
    if XNN_LIKELY(nc >= 8) {
130
0
      _mm_storeu_si128((__m128i*) c0, vfp16out0x01234567);
131
0
      a0 = (const int8_t*) ((uintptr_t) a0 - kc);
132
0
      c0 = (uint16_t*) ((uintptr_t) c0 + cn_stride);
133
0
      nc -= 8;
134
0
    } else {
135
      // Prepare mask for valid 16-bit elements (depends on nc).
136
0
      const __mmask8 vmask = _cvtu32_mask8((UINT32_C(1) << nc) - 1);
137
0
      _mm_mask_storeu_epi16(c0, vmask, vfp16out0x01234567);
138
0
      nc = 0;
139
0
    }
140
0
  } while (nc != 0);
141
0
}