Coverage Report

Created: 2026-06-13 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xnnpack/src/qs8-qc2w-gemm/gen/qs8-qc2w-gemm-1x8c8-minmax-avx2-madd.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_qs8_qc2w_gemm_minmax_fp32_ukernel_1x8c8__avx2_madd(
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
    int8_t* restrict c,
33
    size_t cm_stride,
34
    size_t cn_stride,
35
    const union xnn_qs8_qc8w_conv_minmax_params* restrict params) XNN_OOB_READS
36
0
{
37
0
  assert(mr != 0);
38
0
  assert(mr <= 1);
39
0
  assert(nc != 0);
40
0
  assert(kc != 0);
41
0
  assert(kc % sizeof(int8_t) == 0);
42
0
  assert(a != NULL);
43
0
  assert(w != NULL);
44
0
  assert(c != NULL);
45
46
0
  kc = round_up_po2(kc, 8 * sizeof(int8_t));
47
0
  const int8_t* a0 = a;
48
0
  int8_t* c0 = c;
49
50
0
  const __m256i vsign_mask = _mm256_set1_epi8(0x80);
51
0
  XNN_FORCE_REALIZATION(vsign_mask);
52
0
  const __m256 voutput_max_less_zero_point = _mm256_set1_ps((int32_t) params->fp32_scalar.output_max - (int32_t) params->fp32_scalar.output_zero_point);
53
0
  const __m256i voutput_zero_point = _mm256_set1_epi32(params->fp32_scalar.output_zero_point);
54
0
  const __m128i voutput_min = _mm_set1_epi8(params->fp32_scalar.output_min);
55
  // XNN_FORCE_REALIZATION(voutput_max_less_zero_point);
56
  // XNN_FORCE_REALIZATION(voutput_zero_point);
57
  // XNN_FORCE_REALIZATION(voutput_min);
58
0
  const __m256i vmask = _mm256_set1_epi8(0x03);
59
0
  do {
60
0
    __m256i vacc0x0123 = _mm256_cvtepu32_epi64(_mm_load_si128((const __m128i*) w));
61
0
    __m256i vacc0x4567 = _mm256_cvtepu32_epi64(_mm_load_si128((const __m128i*) ((const int32_t*) w + 4)));
62
0
    __m256i vacc1x0x0123 = _mm256_setzero_si256();
63
0
    __m256i vacc1x0x4567 = _mm256_setzero_si256();
64
0
    w = (const int32_t*) w + 8;
65
66
0
    size_t k = kc;
67
0
    while (k >= 32 * sizeof(int8_t)) {
68
0
      const __m256i va0x0 = _mm256_xor_si256(_mm256_set1_epi64x((int64_t) unaligned_load_u64(a0)), vsign_mask);
69
0
      const __m256i va0x1 = _mm256_xor_si256(_mm256_set1_epi64x((int64_t) unaligned_load_u64(a0 + 8)), vsign_mask);
70
0
      const __m256i va0x2 = _mm256_xor_si256(_mm256_set1_epi64x((int64_t) unaligned_load_u64(a0 + 16)), vsign_mask);
71
0
      const __m256i va0x3 = _mm256_xor_si256(_mm256_set1_epi64x((int64_t) unaligned_load_u64(a0 + 24)), vsign_mask);
72
0
      a0 += 32;
73
74
0
      const __m256i vbb01234567x0123456789ABCDEF = _mm256_load_si256(w);
75
0
      const __m256i vbb89ABCDEFx0123456789ABCDEF = _mm256_load_si256((const __m256i*) ((const int8_t*) w + 32));
76
0
      __m256i vb01234567x0123 = _mm256_and_si256(vbb01234567x0123456789ABCDEF, vmask);
77
0
      __m256i vb89ABCDEFx0123 = _mm256_and_si256(vbb89ABCDEFx0123456789ABCDEF, vmask);
78
0
      __m256i vbs01234567x4567 = _mm256_srli_epi32(vbb01234567x0123456789ABCDEF, 2);
79
0
      __m256i vbs89ABCDEFx4567 = _mm256_srli_epi32(vbb89ABCDEFx0123456789ABCDEF, 2);
80
0
      __m256i vb01234567x4567 = _mm256_and_si256(vbs01234567x4567, vmask);
81
0
      __m256i vb89ABCDEFx4567 = _mm256_and_si256(vbs89ABCDEFx4567, vmask);
82
0
      __m256i vbs01234567x89AB = _mm256_srli_epi32(vbb01234567x0123456789ABCDEF, 4);
83
0
      __m256i vbs89ABCDEFx89AB = _mm256_srli_epi32(vbb89ABCDEFx0123456789ABCDEF, 4);
84
0
      __m256i vb01234567x89AB = _mm256_and_si256(vbs01234567x89AB, vmask);
85
0
      __m256i vb89ABCDEFx89AB = _mm256_and_si256(vbs89ABCDEFx89AB, vmask);
86
0
      __m256i vbs01234567xCDEF = _mm256_srli_epi32(vbb01234567x0123456789ABCDEF, 6);
87
0
      __m256i vbs89ABCDEFxCDEF = _mm256_srli_epi32(vbb89ABCDEFx0123456789ABCDEF, 6);
88
0
      __m256i vb01234567xCDEF = _mm256_and_si256(vbs01234567xCDEF, vmask);
89
0
      __m256i vb89ABCDEFxCDEF = _mm256_and_si256(vbs89ABCDEFxCDEF, vmask);
90
91
0
      vacc0x0123 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x0123, va0x0, vb01234567x0123);
92
0
      vacc0x4567 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x4567, va0x0, vb89ABCDEFx0123);
93
0
      vacc1x0x0123 = _mm256_dpbusd_epi32_madd_kzp2(vacc1x0x0123, va0x1, vb01234567x4567);
94
0
      vacc1x0x4567 = _mm256_dpbusd_epi32_madd_kzp2(vacc1x0x4567, va0x1, vb89ABCDEFx4567);
95
0
      vacc0x0123 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x0123, va0x2, vb01234567x89AB);
96
0
      vacc0x4567 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x4567, va0x2, vb89ABCDEFx89AB);
97
0
      vacc1x0x0123 = _mm256_dpbusd_epi32_madd_kzp2(vacc1x0x0123, va0x3, vb01234567xCDEF);
98
0
      vacc1x0x4567 = _mm256_dpbusd_epi32_madd_kzp2(vacc1x0x4567, va0x3, vb89ABCDEFxCDEF);
99
0
      w = (const int8_t*) w + 64;
100
0
      k -= 32 * sizeof(int8_t);
101
0
    }
102
0
    while (k >= 16 * sizeof(int8_t)) {
103
0
      const __m256i va0x01234567 = _mm256_xor_si256(_mm256_set1_epi64x((int64_t) unaligned_load_u64(a0)), vsign_mask);
104
0
      const __m256i va0x89ABCDEF = _mm256_xor_si256(_mm256_set1_epi64x((int64_t) unaligned_load_u64(a0 + 8)), vsign_mask);
105
0
      a0 += 16;
106
107
      // 2 planes of 2 bit.  potentially 3rd plane handled later
108
0
      __m256i vbb01234567x01234567 = _mm256_load_si256(w);
109
0
      __m256i vbb89ABCDEFx01234567 = _mm256_load_si256((const __m256i*) ((const int8_t*) w + 32));
110
0
      __m256i vbs01234567x4567 = _mm256_srli_epi32(vbb01234567x01234567, 2);
111
0
      __m256i vbs89ABCDEFx4567 = _mm256_srli_epi32(vbb89ABCDEFx01234567, 2);
112
0
      __m256i vb01234567x0123 = _mm256_and_si256(vbb01234567x01234567, vmask);
113
0
      __m256i vb89ABCDEFx0123 = _mm256_and_si256(vbb89ABCDEFx01234567, vmask);
114
0
      __m256i vb01234567x4567 = _mm256_and_si256(vbs01234567x4567, vmask);
115
0
      __m256i vb89ABCDEFx4567 = _mm256_and_si256(vbs89ABCDEFx4567, vmask);
116
117
0
      vacc0x0123 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x0123, va0x01234567, vb01234567x0123);
118
0
      vacc0x4567 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x4567, va0x01234567, vb89ABCDEFx0123);
119
0
      vacc1x0x0123 = _mm256_dpbusd_epi32_madd_kzp2(vacc1x0x0123, va0x89ABCDEF, vb01234567x4567);
120
0
      vacc1x0x4567 = _mm256_dpbusd_epi32_madd_kzp2(vacc1x0x4567, va0x89ABCDEF, vb89ABCDEFx4567);
121
122
0
      w = (const int8_t*) w + 64;
123
0
      k -= 16 * sizeof(int8_t);
124
      // 3rd plane for 2 bit
125
0
      if (k != 0) {
126
0
        const __m256i va0x3 = _mm256_xor_si256(_mm256_set1_epi64x((int64_t) unaligned_load_u64(a0)), vsign_mask);
127
0
        a0 += 8;
128
129
        // mask 3rd plane of 2 bit.
130
0
        __m256i vbs01234567x89AB = _mm256_srli_epi32(vbb01234567x01234567, 4);
131
0
        __m256i vbs89ABCDEFx89AB = _mm256_srli_epi32(vbb89ABCDEFx01234567, 4);
132
0
        __m256i vb01234567x89AB = _mm256_and_si256(vbs01234567x89AB, vmask);
133
0
        __m256i vb89ABCDEFx89AB = _mm256_and_si256(vbs89ABCDEFx89AB, vmask);
134
0
        vacc0x0123 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x0123, va0x3, vb01234567x89AB);
135
0
        vacc0x4567 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x4567, va0x3, vb89ABCDEFx89AB);
136
0
        k -= 8 * sizeof(int8_t);
137
0
      }
138
0
    }
139
140
0
    if (k != 0) {
141
0
      const __m256i va0x01234567 = _mm256_xor_si256(_mm256_set1_epi64x((int64_t) unaligned_load_u64(a0)), vsign_mask);
142
0
      a0 += 8;
143
144
      // 1 plane of 2 bit.
145
0
      const __m256i vbb01234567x01234567 = _mm256_load_si256(w);
146
0
      const __m256i vbb89ABCDEFx01234567 = _mm256_load_si256((const __m256i*) ((const int8_t*) w + 32));
147
0
      __m256i vb01234567x0123 = _mm256_and_si256(vbb01234567x01234567, vmask);
148
0
      __m256i vb89ABCDEFx0123 = _mm256_and_si256(vbb89ABCDEFx01234567, vmask);
149
150
0
      vacc0x0123 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x0123, va0x01234567, vb01234567x0123);
151
0
      vacc0x4567 = _mm256_dpbusd_epi32_madd_kzp2(vacc0x4567, va0x01234567, vb89ABCDEFx0123);
152
153
0
      w = (const int8_t*) w + 64;
154
0
      k -= 8 * sizeof(int8_t);
155
0
    }
156
0
    vacc0x0123 = _mm256_add_epi32(vacc0x0123, vacc1x0x0123);
157
0
    vacc0x4567 = _mm256_add_epi32(vacc0x4567, vacc1x0x4567);
158
159
    // Add adjacent pairs
160
0
    const __m256i vsum0x02134657 = _mm256_hadd_epi32(vacc0x0123, vacc0x4567);
161
0
    __m256i vacc0x01234567 = _mm256_permute4x64_epi64(vsum0x02134657, _MM_SHUFFLE(3, 1, 2, 0));
162
163
0
    __m256 vout0x01234567 = _mm256_cvtepi32_ps(vacc0x01234567);
164
165
0
    const __m256 vscale01234567 = _mm256_load_ps(w);
166
0
    w = (const float*) w + 8;
167
0
    vout0x01234567 = _mm256_mul_ps(vout0x01234567, vscale01234567);
168
169
0
    vout0x01234567 = _mm256_min_ps(vout0x01234567, voutput_max_less_zero_point);
170
171
0
    vacc0x01234567 = _mm256_cvtps_epi32(vout0x01234567);
172
173
0
    vacc0x01234567 = _mm256_add_epi32(vacc0x01234567, voutput_zero_point);
174
175
0
    vacc0x01234567 = _mm256_packs_epi32(vacc0x01234567, _mm256_castsi128_si256(_mm256_extracti128_si256(vacc0x01234567, 1)));
176
0
    __m128i voutb0x01234567 = _mm256_castsi256_si128(_mm256_packs_epi16(vacc0x01234567, vacc0x01234567));
177
178
0
    voutb0x01234567 = _mm_max_epi8(voutb0x01234567, voutput_min);
179
180
0
    if (nc >= 8) {
181
0
      _mm_storel_epi64((__m128i*) c0, voutb0x01234567);
182
0
      c0 = (int8_t*) ((uintptr_t) c0 + cn_stride);
183
0
      a0 = (const int8_t*) ((uintptr_t) a0 - kc);
184
185
0
      nc -= 8;
186
0
    } else {
187
0
      if (nc & 4) {
188
0
        _mm_storeu_si32(c0, voutb0x01234567);
189
0
        c0 += 4;
190
0
        voutb0x01234567 = _mm_srli_epi64(voutb0x01234567, 32);
191
0
      }
192
0
      if (nc & 2) {
193
0
        unaligned_store_u16(c0, (uint16_t) _mm_extract_epi16(voutb0x01234567, 0));
194
0
        c0 += 2;
195
0
        voutb0x01234567 = _mm_srli_epi32(voutb0x01234567, 16);
196
0
      }
197
0
      if (nc & 1) {
198
0
        *c0 = (int8_t) _mm_extract_epi8(voutb0x01234567, 0);
199
0
      }
200
0
      nc = 0;
201
0
    }
202
0
  } while (nc != 0);
203
0
}