xref: /aosp_15_r20/external/skia/experimental/lowp-basic/lowp_experiments.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2021 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include <cassert>
9*c8dee2aaSAndroid Build Coastguard Worker #include <cstdio>
10*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
11*c8dee2aaSAndroid Build Coastguard Worker #include "experimental/lowp-basic/QMath.h"
12*c8dee2aaSAndroid Build Coastguard Worker 
13*c8dee2aaSAndroid Build Coastguard Worker // Compile for x86_64 + ssse3 with:
14*c8dee2aaSAndroid Build Coastguard Worker //     c++ -O3 --std=c++17 -mssse3 experimental/lowp-basic/lowp_experiments.cpp -o lowp
15*c8dee2aaSAndroid Build Coastguard Worker //
16*c8dee2aaSAndroid Build Coastguard Worker // Compile for aarch64 with (Mac os):
17*c8dee2aaSAndroid Build Coastguard Worker //    c++ -O3 --std=c++17 -arch arm64 experimental/lowp-basic/lowp_experiments.cpp  -o lowp
18*c8dee2aaSAndroid Build Coastguard Worker //
19*c8dee2aaSAndroid Build Coastguard Worker // View assembly:
20*c8dee2aaSAndroid Build Coastguard Worker //    dumpobj -d lowp | less
21*c8dee2aaSAndroid Build Coastguard Worker 
22*c8dee2aaSAndroid Build Coastguard Worker template <int N, typename T> using V = T __attribute__((ext_vector_type(N)));
23*c8dee2aaSAndroid Build Coastguard Worker 
24*c8dee2aaSAndroid Build Coastguard Worker #if !defined(__clang__)
25*c8dee2aaSAndroid Build Coastguard Worker     static_assert(false, "This only works on clang.");
26*c8dee2aaSAndroid Build Coastguard Worker #endif
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker #if defined(__SSSE3__)
29*c8dee2aaSAndroid Build Coastguard Worker     #include <immintrin.h>
30*c8dee2aaSAndroid Build Coastguard Worker #endif
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker #if defined(__ARM_NEON)
33*c8dee2aaSAndroid Build Coastguard Worker     // From section 5.5.5 of the ARM C Language Extensions (ACLE)
34*c8dee2aaSAndroid Build Coastguard Worker     #include <arm_neon.h>
35*c8dee2aaSAndroid Build Coastguard Worker #endif
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker using Q15 = V<8, uint16_t>;
38*c8dee2aaSAndroid Build Coastguard Worker 
39*c8dee2aaSAndroid Build Coastguard Worker #if defined(__SSSE3__)
test_mm_mulhrs_epi16_simulation()40*c8dee2aaSAndroid Build Coastguard Worker static void test_mm_mulhrs_epi16_simulation() {
41*c8dee2aaSAndroid Build Coastguard Worker     for (int i = -32768; i < 32768; i++) {
42*c8dee2aaSAndroid Build Coastguard Worker         for (int j = -32768; j < 32768; j++) {
43*c8dee2aaSAndroid Build Coastguard Worker             Q15 a(i);
44*c8dee2aaSAndroid Build Coastguard Worker             Q15 b(j);
45*c8dee2aaSAndroid Build Coastguard Worker             Q15 simResult = simulate_ssse3_mm_mulhrs_epi16(a, b);
46*c8dee2aaSAndroid Build Coastguard Worker             Q15 intrinsicResult = _mm_mulhrs_epi16(a, b);
47*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
48*c8dee2aaSAndroid Build Coastguard Worker                 if (simResult[i] != intrinsicResult[i]) {
49*c8dee2aaSAndroid Build Coastguard Worker                     printf("simulate_ssse3_mm_mulhrs_epi16 broken\n");
50*c8dee2aaSAndroid Build Coastguard Worker                     printf("i: %d, a: %hx b: %hx, intrinsic: %hx, sim: %hx\n",
51*c8dee2aaSAndroid Build Coastguard Worker                            i, a[i], b[i], intrinsicResult[i], simResult[i]);
52*c8dee2aaSAndroid Build Coastguard Worker                     exit(1);
53*c8dee2aaSAndroid Build Coastguard Worker                 }
54*c8dee2aaSAndroid Build Coastguard Worker             }
55*c8dee2aaSAndroid Build Coastguard Worker         }
56*c8dee2aaSAndroid Build Coastguard Worker     }
57*c8dee2aaSAndroid Build Coastguard Worker }
58*c8dee2aaSAndroid Build Coastguard Worker 
59*c8dee2aaSAndroid Build Coastguard Worker // Use ssse3 to simulate saturating multiply on arm.
ssse3_vqrdmulhq_s16(Q15 a,Q15 b)60*c8dee2aaSAndroid Build Coastguard Worker static Q15 ssse3_vqrdmulhq_s16(Q15 a, Q15 b) {
61*c8dee2aaSAndroid Build Coastguard Worker     constexpr Q15 limit(0x8000);
62*c8dee2aaSAndroid Build Coastguard Worker     const Q15 product = _mm_mulhrs_epi16(a, b);
63*c8dee2aaSAndroid Build Coastguard Worker     const Q15 eq = _mm_cmpeq_epi16(product, limit);
64*c8dee2aaSAndroid Build Coastguard Worker     return _mm_xor_si128(eq, product);
65*c8dee2aaSAndroid Build Coastguard Worker }
66*c8dee2aaSAndroid Build Coastguard Worker 
test_ssse3_vqrdmulhq_s16()67*c8dee2aaSAndroid Build Coastguard Worker static void test_ssse3_vqrdmulhq_s16() {
68*c8dee2aaSAndroid Build Coastguard Worker     for (int i = -32768; i < 32768; i++) {
69*c8dee2aaSAndroid Build Coastguard Worker         for (int j = -32768; j < 32768; j++) {
70*c8dee2aaSAndroid Build Coastguard Worker             Q15 a(i);
71*c8dee2aaSAndroid Build Coastguard Worker             Q15 b(j);
72*c8dee2aaSAndroid Build Coastguard Worker             Q15 simResult = ssse3_vqrdmulhq_s16(a, b);
73*c8dee2aaSAndroid Build Coastguard Worker             Q15 realVqrdmulhqS16 = simulate_neon_vqrdmulhq_s16(a, b);
74*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
75*c8dee2aaSAndroid Build Coastguard Worker                 if (simResult[i] != realVqrdmulhqS16[i]) {
76*c8dee2aaSAndroid Build Coastguard Worker                     printf("simulating vqrdmulhq_s16 with ssse3 broken\n");
77*c8dee2aaSAndroid Build Coastguard Worker                     printf("i: %d, a: %hx b: %hx, intrinsic: %hx, sim: %hx\n",
78*c8dee2aaSAndroid Build Coastguard Worker                            i, a[i], b[i], realVqrdmulhqS16[i], simResult[i]);
79*c8dee2aaSAndroid Build Coastguard Worker                     exit(1);
80*c8dee2aaSAndroid Build Coastguard Worker                 }
81*c8dee2aaSAndroid Build Coastguard Worker             }
82*c8dee2aaSAndroid Build Coastguard Worker         }
83*c8dee2aaSAndroid Build Coastguard Worker     }
84*c8dee2aaSAndroid Build Coastguard Worker }
85*c8dee2aaSAndroid Build Coastguard Worker 
86*c8dee2aaSAndroid Build Coastguard Worker #endif
87*c8dee2aaSAndroid Build Coastguard Worker 
88*c8dee2aaSAndroid Build Coastguard Worker #if defined(__ARM_NEON)
test_neon_vqrdmulhq_s16_simulation()89*c8dee2aaSAndroid Build Coastguard Worker static void test_neon_vqrdmulhq_s16_simulation() {
90*c8dee2aaSAndroid Build Coastguard Worker     for (int i = -32768; i < 32768; i++) {
91*c8dee2aaSAndroid Build Coastguard Worker         for (int j = -32768; j < 32768; j++) {
92*c8dee2aaSAndroid Build Coastguard Worker             Q15 a(i);
93*c8dee2aaSAndroid Build Coastguard Worker             Q15 b(j);
94*c8dee2aaSAndroid Build Coastguard Worker             Q15 simResult = simulate_neon_vqrdmulhq_s16(a, b);
95*c8dee2aaSAndroid Build Coastguard Worker             Q15 intrinsicResult = vqrdmulhq_s16(a, b);
96*c8dee2aaSAndroid Build Coastguard Worker             for (int i = 0; i < 8; i++) {
97*c8dee2aaSAndroid Build Coastguard Worker                 if (simResult[i] != intrinsicResult[i]) {
98*c8dee2aaSAndroid Build Coastguard Worker                     printf("simulate_neon_vqrdmulhq_s16 broken\n");
99*c8dee2aaSAndroid Build Coastguard Worker                     printf("i: %d, a: %hx b: %hx, intrinsic: %hx, sim: %hx\n",
100*c8dee2aaSAndroid Build Coastguard Worker                            i, a[i], b[i], intrinsicResult[i], simResult[i]);
101*c8dee2aaSAndroid Build Coastguard Worker                     exit(1);
102*c8dee2aaSAndroid Build Coastguard Worker                 }
103*c8dee2aaSAndroid Build Coastguard Worker             }
104*c8dee2aaSAndroid Build Coastguard Worker         }
105*c8dee2aaSAndroid Build Coastguard Worker     }
106*c8dee2aaSAndroid Build Coastguard Worker }
107*c8dee2aaSAndroid Build Coastguard Worker #endif
108*c8dee2aaSAndroid Build Coastguard Worker 
main()109*c8dee2aaSAndroid Build Coastguard Worker int main() {
110*c8dee2aaSAndroid Build Coastguard Worker     #if defined(__SSSE3__)
111*c8dee2aaSAndroid Build Coastguard Worker         //test_mm_mulhrs_epi16_simulation();
112*c8dee2aaSAndroid Build Coastguard Worker         test_ssse3_vqrdmulhq_s16();
113*c8dee2aaSAndroid Build Coastguard Worker     #endif
114*c8dee2aaSAndroid Build Coastguard Worker     #if defined(__ARM_NEON)
115*c8dee2aaSAndroid Build Coastguard Worker         test_neon_vqrdmulhq_s16_simulation();
116*c8dee2aaSAndroid Build Coastguard Worker     #endif
117*c8dee2aaSAndroid Build Coastguard Worker     printf("Done.\n");
118*c8dee2aaSAndroid Build Coastguard Worker     return 0;
119*c8dee2aaSAndroid Build Coastguard Worker }
120