inline __m256i avx2_uv_to_hexid_cw(__m256i u, __m256i v) { // u += v; // v = -v; // return uv_to_hexid_ccw(u, v); u = _mm256_add_epi32(u, v); v = _mm256_sign_epi32(v, _mm256_cmpeq_epi32(v, v)); return avx2_uv_to_hexid_ccw(u, v); }
static INLINE void quantize(const __m256i *qp, __m256i *c, const int16_t *iscan_ptr, int log_scale, tran_low_t *qcoeff, tran_low_t *dqcoeff, __m256i *eob) { const __m256i abs_coeff = _mm256_abs_epi32(*c); __m256i q = _mm256_add_epi32(abs_coeff, qp[0]); __m256i q_lo = _mm256_mul_epi32(q, qp[1]); __m256i q_hi = _mm256_srli_epi64(q, 32); const __m256i qp_hi = _mm256_srli_epi64(qp[1], 32); q_hi = _mm256_mul_epi32(q_hi, qp_hi); q_lo = _mm256_srli_epi64(q_lo, 16 - log_scale); q_hi = _mm256_srli_epi64(q_hi, 16 - log_scale); q_hi = _mm256_slli_epi64(q_hi, 32); q = _mm256_or_si256(q_lo, q_hi); const __m256i abs_s = _mm256_slli_epi32(abs_coeff, 1 + log_scale); const __m256i mask = _mm256_cmpgt_epi32(qp[2], abs_s); q = _mm256_andnot_si256(mask, q); __m256i dq = _mm256_mullo_epi32(q, qp[2]); dq = _mm256_srai_epi32(dq, log_scale); q = _mm256_sign_epi32(q, *c); dq = _mm256_sign_epi32(dq, *c); _mm256_storeu_si256((__m256i *)qcoeff, q); _mm256_storeu_si256((__m256i *)dqcoeff, dq); const __m128i isc = _mm_loadu_si128((const __m128i *)iscan_ptr); const __m128i zr = _mm_setzero_si128(); const __m128i lo = _mm_unpacklo_epi16(isc, zr); const __m128i hi = _mm_unpackhi_epi16(isc, zr); const __m256i iscan = _mm256_insertf128_si256(_mm256_castsi128_si256(lo), hi, 1); const __m256i zero = _mm256_setzero_si256(); const __m256i zc = _mm256_cmpeq_epi32(dq, zero); const __m256i nz = _mm256_cmpeq_epi32(zc, zero); __m256i cur_eob = _mm256_sub_epi32(iscan, nz); cur_eob = _mm256_and_si256(cur_eob, nz); *eob = _mm256_max_epi32(cur_eob, *eob); }
inline void avx2_hexid_to_uv_cw(const __m256i hexid, __m256i& u, __m256i& v) { #if 0 // This code is correct but it's not worth maintaining two versions const __m256i one = _mm256_set1_epi32(1); __m256i ringid = avx2_positive_hexid_to_ringid(hexid); __m256i iring = _mm256_sub_epi32(hexid, avx2_ringid_to_nsites_contained(_mm256_sub_epi32(ringid,one))); u = ringid; v = _mm256_setzero_si256(); __m256i irun = _mm256_min_epu32(iring, ringid); v = _mm256_sub_epi32(v, irun); iring = _mm256_sub_epi32(iring, irun); irun = _mm256_min_epu32(iring, ringid); u = _mm256_sub_epi32(u, irun); iring = _mm256_sub_epi32(iring, irun); irun = _mm256_min_epu32(iring, ringid); u = _mm256_sub_epi32(u, irun); v = _mm256_add_epi32(v, irun); iring = _mm256_sub_epi32(iring, irun); irun = _mm256_min_epu32(iring, ringid); v = _mm256_add_epi32(v, irun); iring = _mm256_sub_epi32(iring, irun); irun = _mm256_min_epu32(iring, ringid); u = _mm256_add_epi32(u, irun); iring = _mm256_sub_epi32(iring, irun); u = _mm256_add_epi32(u, irun); v = _mm256_add_epi32(v, iring); const __m256i mask = _mm256_cmpeq_epi32(hexid, _mm256_setzero_si256()); u = _mm256_andnot_si256(mask, u); v = _mm256_andnot_si256(mask, v); #else // hexid_to_uv_ccw(hexid, u, v); // u += v; // v = -v; avx2_hexid_to_uv_ccw(hexid, u, v); u = _mm256_add_epi32(u, v); v = _mm256_sign_epi32(v, _mm256_cmpeq_epi32(v, v)); #endif }
__m256i test_mm256_sign_epi32(__m256i a, __m256i b) { // CHECK: @llvm.x86.avx2.psign.d return _mm256_sign_epi32(a, b); }
__m256i test_mm256_sign_epi32(__m256i a, __m256i b) { // CHECK-LABEL: test_mm256_sign_epi32 // CHECK: call <8 x i32> @llvm.x86.avx2.psign.d(<8 x i32> %{{.*}}, <8 x i32> %{{.*}}) return _mm256_sign_epi32(a, b); }
void extern avx2_test (void) { x = _mm256_sign_epi32 (x, x); }
inline __m256i avx2_uv_to_hexid_ccw(const __m256i u, const __m256i v) { // if(u==0 and v==0)return 0; // int ringid = uv_to_ringid(u,v); // unsigned segid; // int runid; // int upv = u+v; // if(upv==ringid and v!=ringid) { segid=0; runid=v; } // else if(v==ringid and u!=-ringid) { segid=1; runid=-u; } // else if(u==-ringid and upv!=-ringid) { segid=2; runid=ringid-v; } // else if(u+v==-ringid and v!=-ringid) { segid=3; runid=-v; } // else if(v==-ringid and u!=ringid) { segid=4; runid=u; } // else /*if(u==ringid and upv!=ringid)*/{ segid=5; runid=ringid+v; } // return positive_ringid_segid_runid_to_hexid(ringid, segid, runid); const __m256i one = _mm256_set1_epi32(1); const __m256i minus_one = _mm256_set1_epi32(-1); const __m256i ringid = avx2_uv_to_ringid(u,v); const __m256i minus_ringid = _mm256_sign_epi32(ringid, minus_one); const __m256i upv = _mm256_add_epi32(u, v); __m256i not_found_mask = minus_one; __m256i hexid = avx2_ringid_to_nsites_contained(_mm256_sub_epi32(ringid, one)); // Seg ID = 0 // if(upv==ringid and v!=ringid) { segid=0; runid=v; } __m256i here_mask = _mm256_cmpeq_epi32(upv, ringid); hexid = _mm256_add_epi32(hexid, _mm256_and_si256(not_found_mask, _mm256_blendv_epi8(ringid, v, here_mask))); not_found_mask = _mm256_andnot_si256(here_mask, not_found_mask); // hexid = _mm256_add_epi32(hexid, _mm256_or_si256( // _mm256_and_si256(here_mask, v), // _mm256_and_si256(not_found_mask, ringid))); // Seg ID = 1 // else if(v==ringid and u!=-ringid) { segid=1; runid=-u; } here_mask = _mm256_cmpeq_epi32(v, ringid); hexid = _mm256_sub_epi32(hexid, _mm256_and_si256(not_found_mask, _mm256_blendv_epi8(minus_ringid, u, here_mask))); not_found_mask = _mm256_andnot_si256(here_mask, not_found_mask); // hexid = _mm256_sub_epi32(hexid, _mm256_or_si256( // _mm256_and_si256(here_mask, u), // _mm256_and_si256(not_found_mask, minus_ringid))); // Seg ID = 2 // else if(u==-ringid and upv!=-ringid) { segid=2; runid=ringid-v; } here_mask = _mm256_cmpeq_epi32(u, minus_ringid); hexid = _mm256_sub_epi32(hexid, _mm256_and_si256(not_found_mask, _mm256_blendv_epi8(minus_ringid, upv, here_mask))); not_found_mask = _mm256_andnot_si256(here_mask, not_found_mask); // hexid = _mm256_sub_epi32(hexid, _mm256_or_si256( // _mm256_and_si256(here_mask, upv), // _mm256_and_si256(not_found_mask, minus_ringid))); // Seg ID = 3 // else if(u+v==-ringid and v!=-ringid) { segid=3; runid=-v; } here_mask = _mm256_cmpeq_epi32(upv, minus_ringid); hexid = _mm256_sub_epi32(hexid, _mm256_and_si256(not_found_mask, _mm256_blendv_epi8(minus_ringid, v, here_mask))); not_found_mask = _mm256_andnot_si256(here_mask, not_found_mask); // hexid = _mm256_sub_epi32(hexid, _mm256_or_si256( // _mm256_and_si256(here_mask, v), // _mm256_and_si256(not_found_mask, minus_ringid))); // Seg ID = 4 // else if(v==-ringid and u!=ringid) { segid=4; runid=u; } here_mask = _mm256_cmpeq_epi32(v, minus_ringid); hexid = _mm256_add_epi32(hexid, _mm256_and_si256(not_found_mask, _mm256_blendv_epi8(ringid, u, here_mask))); not_found_mask = _mm256_andnot_si256(here_mask, not_found_mask); // hexid = _mm256_add_epi32(hexid, _mm256_or_si256( // _mm256_and_si256(here_mask, u), // _mm256_and_si256(not_found_mask, ringid))); // Seg ID = 5 // else /*if(u==ringid and upv!=ringid)*/{ segid=5; runid=ringid+v; } hexid = _mm256_add_epi32(hexid, _mm256_and_si256(not_found_mask, upv)); const __m256i mask = _mm256_cmpeq_epi32(ringid, _mm256_setzero_si256()); hexid = _mm256_andnot_si256(mask, hexid); return hexid; }