inline int v_signmask(const v_uint8x16& a) { int8x8_t m0 = vcreate_s8(CV_BIG_UINT(0x0706050403020100)); uint8x16_t v0 = vshlq_u8(vshrq_n_u8(a.val, 7), vcombine_s8(m0, m0)); uint64x2_t v1 = vpaddlq_u32(vpaddlq_u16(vpaddlq_u8(v0))); return (int)vgetq_lane_u64(v1, 0) + ((int)vgetq_lane_u64(v1, 1) << 8); }
void test_vcombines8 (void) { int8x16_t out_int8x16_t; int8x8_t arg0_int8x8_t; int8x8_t arg1_int8x8_t; out_int8x16_t = vcombine_s8 (arg0_int8x8_t, arg1_int8x8_t); }
static INLINE void vp8_loop_filter_simple_vertical_edge_neon( unsigned char *s, int p, const unsigned char *blimit) { unsigned char *src1; uint8x16_t qblimit, q0u8; uint8x16_t q3u8, q4u8, q5u8, q6u8, q7u8, q11u8, q12u8, q14u8, q15u8; int16x8_t q2s16, q13s16, q11s16; int8x8_t d28s8, d29s8; int8x16_t q2s8, q3s8, q10s8, q11s8, q14s8; uint8x8x4_t d0u8x4; // d6, d7, d8, d9 uint8x8x4_t d1u8x4; // d10, d11, d12, d13 uint8x8x2_t d2u8x2; // d12, d13 uint8x8x2_t d3u8x2; // d14, d15 qblimit = vdupq_n_u8(*blimit); src1 = s - 2; d0u8x4 = read_4x8(src1, p); src1 += p * 8; d1u8x4 = read_4x8(src1, p); q3u8 = vcombine_u8(d0u8x4.val[0], d1u8x4.val[0]); // d6 d10 q4u8 = vcombine_u8(d0u8x4.val[2], d1u8x4.val[2]); // d8 d12 q5u8 = vcombine_u8(d0u8x4.val[1], d1u8x4.val[1]); // d7 d11 q6u8 = vcombine_u8(d0u8x4.val[3], d1u8x4.val[3]); // d9 d13 q15u8 = vabdq_u8(q5u8, q4u8); q14u8 = vabdq_u8(q3u8, q6u8); q15u8 = vqaddq_u8(q15u8, q15u8); q14u8 = vshrq_n_u8(q14u8, 1); q0u8 = vdupq_n_u8(0x80); q11s16 = vdupq_n_s16(3); q15u8 = vqaddq_u8(q15u8, q14u8); q3u8 = veorq_u8(q3u8, q0u8); q4u8 = veorq_u8(q4u8, q0u8); q5u8 = veorq_u8(q5u8, q0u8); q6u8 = veorq_u8(q6u8, q0u8); q15u8 = vcgeq_u8(qblimit, q15u8); q2s16 = vsubl_s8(vget_low_s8(vreinterpretq_s8_u8(q4u8)), vget_low_s8(vreinterpretq_s8_u8(q5u8))); q13s16 = vsubl_s8(vget_high_s8(vreinterpretq_s8_u8(q4u8)), vget_high_s8(vreinterpretq_s8_u8(q5u8))); q14s8 = vqsubq_s8(vreinterpretq_s8_u8(q3u8), vreinterpretq_s8_u8(q6u8)); q2s16 = vmulq_s16(q2s16, q11s16); q13s16 = vmulq_s16(q13s16, q11s16); q11u8 = vdupq_n_u8(3); q12u8 = vdupq_n_u8(4); q2s16 = vaddw_s8(q2s16, vget_low_s8(q14s8)); q13s16 = vaddw_s8(q13s16, vget_high_s8(q14s8)); d28s8 = vqmovn_s16(q2s16); d29s8 = vqmovn_s16(q13s16); q14s8 = vcombine_s8(d28s8, d29s8); q14s8 = vandq_s8(q14s8, vreinterpretq_s8_u8(q15u8)); q2s8 = vqaddq_s8(q14s8, vreinterpretq_s8_u8(q11u8)); q3s8 = vqaddq_s8(q14s8, vreinterpretq_s8_u8(q12u8)); q2s8 = vshrq_n_s8(q2s8, 3); q14s8 = vshrq_n_s8(q3s8, 3); q11s8 = vqaddq_s8(vreinterpretq_s8_u8(q5u8), q2s8); q10s8 = vqsubq_s8(vreinterpretq_s8_u8(q4u8), q14s8); q6u8 = veorq_u8(vreinterpretq_u8_s8(q11s8), q0u8); q7u8 = veorq_u8(vreinterpretq_u8_s8(q10s8), q0u8); d2u8x2.val[0] = vget_low_u8(q6u8); // d12 d2u8x2.val[1] = vget_low_u8(q7u8); // d14 d3u8x2.val[0] = vget_high_u8(q6u8); // d13 d3u8x2.val[1] = vget_high_u8(q7u8); // d15 src1 = s - 1; write_2x8(src1, p, d2u8x2, d3u8x2); }
// CHECK-LABEL: define <16 x i8> @test_vcombine_s8(<8 x i8> %low, <8 x i8> %high) #0 { // CHECK: [[SHUFFLE_I:%.*]] = shufflevector <8 x i8> %low, <8 x i8> %high, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15> // CHECK: ret <16 x i8> [[SHUFFLE_I]] int8x16_t test_vcombine_s8(int8x8_t low, int8x8_t high) { return vcombine_s8(low, high); }
static INLINE void vp8_loop_filter_simple_horizontal_edge_neon( unsigned char *s, int p, const unsigned char *blimit) { uint8_t *sp; uint8x16_t qblimit, q0u8; uint8x16_t q5u8, q6u8, q7u8, q8u8, q9u8, q10u8, q14u8, q15u8; int16x8_t q2s16, q3s16, q13s16; int8x8_t d8s8, d9s8; int8x16_t q2s8, q3s8, q4s8, q10s8, q11s8, q14s8; qblimit = vdupq_n_u8(*blimit); sp = s - (p << 1); q5u8 = vld1q_u8(sp); sp += p; q6u8 = vld1q_u8(sp); sp += p; q7u8 = vld1q_u8(sp); sp += p; q8u8 = vld1q_u8(sp); q15u8 = vabdq_u8(q6u8, q7u8); q14u8 = vabdq_u8(q5u8, q8u8); q15u8 = vqaddq_u8(q15u8, q15u8); q14u8 = vshrq_n_u8(q14u8, 1); q0u8 = vdupq_n_u8(0x80); q13s16 = vdupq_n_s16(3); q15u8 = vqaddq_u8(q15u8, q14u8); q5u8 = veorq_u8(q5u8, q0u8); q6u8 = veorq_u8(q6u8, q0u8); q7u8 = veorq_u8(q7u8, q0u8); q8u8 = veorq_u8(q8u8, q0u8); q15u8 = vcgeq_u8(qblimit, q15u8); q2s16 = vsubl_s8(vget_low_s8(vreinterpretq_s8_u8(q7u8)), vget_low_s8(vreinterpretq_s8_u8(q6u8))); q3s16 = vsubl_s8(vget_high_s8(vreinterpretq_s8_u8(q7u8)), vget_high_s8(vreinterpretq_s8_u8(q6u8))); q4s8 = vqsubq_s8(vreinterpretq_s8_u8(q5u8), vreinterpretq_s8_u8(q8u8)); q2s16 = vmulq_s16(q2s16, q13s16); q3s16 = vmulq_s16(q3s16, q13s16); q10u8 = vdupq_n_u8(3); q9u8 = vdupq_n_u8(4); q2s16 = vaddw_s8(q2s16, vget_low_s8(q4s8)); q3s16 = vaddw_s8(q3s16, vget_high_s8(q4s8)); d8s8 = vqmovn_s16(q2s16); d9s8 = vqmovn_s16(q3s16); q4s8 = vcombine_s8(d8s8, d9s8); q14s8 = vandq_s8(q4s8, vreinterpretq_s8_u8(q15u8)); q2s8 = vqaddq_s8(q14s8, vreinterpretq_s8_u8(q10u8)); q3s8 = vqaddq_s8(q14s8, vreinterpretq_s8_u8(q9u8)); q2s8 = vshrq_n_s8(q2s8, 3); q3s8 = vshrq_n_s8(q3s8, 3); q11s8 = vqaddq_s8(vreinterpretq_s8_u8(q6u8), q2s8); q10s8 = vqsubq_s8(vreinterpretq_s8_u8(q7u8), q3s8); q6u8 = veorq_u8(vreinterpretq_u8_s8(q11s8), q0u8); q7u8 = veorq_u8(vreinterpretq_u8_s8(q10s8), q0u8); vst1q_u8(s, q7u8); s -= p; vst1q_u8(s, q6u8); return; }
inline int8x16_t vcombine(const int8x8_t & v0, const int8x8_t & v1) { return vcombine_s8 (v0, v1); }
static INLINE void loop_filter_neon_16(uint8x16_t qblimit, // blimit uint8x16_t qlimit, // limit uint8x16_t qthresh, // thresh uint8x16_t q3, // p3 uint8x16_t q4, // p2 uint8x16_t q5, // p1 uint8x16_t q6, // p0 uint8x16_t q7, // q0 uint8x16_t q8, // q1 uint8x16_t q9, // q2 uint8x16_t q10, // q3 uint8x16_t *q5r, // p1 uint8x16_t *q6r, // p0 uint8x16_t *q7r, // q0 uint8x16_t *q8r) { // q1 uint8x16_t q1u8, q2u8, q11u8, q12u8, q13u8, q14u8, q15u8; int16x8_t q2s16, q11s16; uint16x8_t q4u16; int8x16_t q0s8, q1s8, q2s8, q11s8, q12s8, q13s8; int8x8_t d2s8, d3s8; q11u8 = vabdq_u8(q3, q4); q12u8 = vabdq_u8(q4, q5); q13u8 = vabdq_u8(q5, q6); q14u8 = vabdq_u8(q8, q7); q3 = vabdq_u8(q9, q8); q4 = vabdq_u8(q10, q9); q11u8 = vmaxq_u8(q11u8, q12u8); q12u8 = vmaxq_u8(q13u8, q14u8); q3 = vmaxq_u8(q3, q4); q15u8 = vmaxq_u8(q11u8, q12u8); q9 = vabdq_u8(q6, q7); // vp8_hevmask q13u8 = vcgtq_u8(q13u8, qthresh); q14u8 = vcgtq_u8(q14u8, qthresh); q15u8 = vmaxq_u8(q15u8, q3); q2u8 = vabdq_u8(q5, q8); q9 = vqaddq_u8(q9, q9); q15u8 = vcgeq_u8(qlimit, q15u8); // vp8_filter() function // convert to signed q10 = vdupq_n_u8(0x80); q8 = veorq_u8(q8, q10); q7 = veorq_u8(q7, q10); q6 = veorq_u8(q6, q10); q5 = veorq_u8(q5, q10); q2u8 = vshrq_n_u8(q2u8, 1); q9 = vqaddq_u8(q9, q2u8); q2s16 = vsubl_s8(vget_low_s8(vreinterpretq_s8_u8(q7)), vget_low_s8(vreinterpretq_s8_u8(q6))); q11s16 = vsubl_s8(vget_high_s8(vreinterpretq_s8_u8(q7)), vget_high_s8(vreinterpretq_s8_u8(q6))); q9 = vcgeq_u8(qblimit, q9); q1s8 = vqsubq_s8(vreinterpretq_s8_u8(q5), vreinterpretq_s8_u8(q8)); q14u8 = vorrq_u8(q13u8, q14u8); q4u16 = vdupq_n_u16(3); q2s16 = vmulq_s16(q2s16, vreinterpretq_s16_u16(q4u16)); q11s16 = vmulq_s16(q11s16, vreinterpretq_s16_u16(q4u16)); q1u8 = vandq_u8(vreinterpretq_u8_s8(q1s8), q14u8); q15u8 = vandq_u8(q15u8, q9); q1s8 = vreinterpretq_s8_u8(q1u8); q2s16 = vaddw_s8(q2s16, vget_low_s8(q1s8)); q11s16 = vaddw_s8(q11s16, vget_high_s8(q1s8)); q4 = vdupq_n_u8(3); q9 = vdupq_n_u8(4); // vp8_filter = clamp(vp8_filter + 3 * ( qs0 - ps0)) d2s8 = vqmovn_s16(q2s16); d3s8 = vqmovn_s16(q11s16); q1s8 = vcombine_s8(d2s8, d3s8); q1u8 = vandq_u8(vreinterpretq_u8_s8(q1s8), q15u8); q1s8 = vreinterpretq_s8_u8(q1u8); q2s8 = vqaddq_s8(q1s8, vreinterpretq_s8_u8(q4)); q1s8 = vqaddq_s8(q1s8, vreinterpretq_s8_u8(q9)); q2s8 = vshrq_n_s8(q2s8, 3); q1s8 = vshrq_n_s8(q1s8, 3); q11s8 = vqaddq_s8(vreinterpretq_s8_u8(q6), q2s8); q0s8 = vqsubq_s8(vreinterpretq_s8_u8(q7), q1s8); q1s8 = vrshrq_n_s8(q1s8, 1); q1s8 = vbicq_s8(q1s8, vreinterpretq_s8_u8(q14u8)); q13s8 = vqaddq_s8(vreinterpretq_s8_u8(q5), q1s8); q12s8 = vqsubq_s8(vreinterpretq_s8_u8(q8), q1s8); *q8r = veorq_u8(vreinterpretq_u8_s8(q12s8), q10); *q7r = veorq_u8(vreinterpretq_u8_s8(q0s8), q10); *q6r = veorq_u8(vreinterpretq_u8_s8(q11s8), q10); *q5r = veorq_u8(vreinterpretq_u8_s8(q13s8), q10); return; }
static INLINE void vp8_mbloop_filter_neon( uint8x16_t qblimit, // mblimit uint8x16_t qlimit, // limit uint8x16_t qthresh, // thresh uint8x16_t q3, // p2 uint8x16_t q4, // p2 uint8x16_t q5, // p1 uint8x16_t q6, // p0 uint8x16_t q7, // q0 uint8x16_t q8, // q1 uint8x16_t q9, // q2 uint8x16_t q10, // q3 uint8x16_t *q4r, // p1 uint8x16_t *q5r, // p1 uint8x16_t *q6r, // p0 uint8x16_t *q7r, // q0 uint8x16_t *q8r, // q1 uint8x16_t *q9r) { // q1 uint8x16_t q0u8, q1u8, q11u8, q12u8, q13u8, q14u8, q15u8; int16x8_t q0s16, q2s16, q11s16, q12s16, q13s16, q14s16, q15s16; int8x16_t q1s8, q6s8, q7s8, q2s8, q11s8, q13s8; uint16x8_t q0u16, q11u16, q12u16, q13u16, q14u16, q15u16; int8x16_t q0s8, q12s8, q14s8, q15s8; int8x8_t d0, d1, d2, d3, d4, d5, d24, d25, d28, d29; q11u8 = vabdq_u8(q3, q4); q12u8 = vabdq_u8(q4, q5); q13u8 = vabdq_u8(q5, q6); q14u8 = vabdq_u8(q8, q7); q1u8 = vabdq_u8(q9, q8); q0u8 = vabdq_u8(q10, q9); q11u8 = vmaxq_u8(q11u8, q12u8); q12u8 = vmaxq_u8(q13u8, q14u8); q1u8 = vmaxq_u8(q1u8, q0u8); q15u8 = vmaxq_u8(q11u8, q12u8); q12u8 = vabdq_u8(q6, q7); // vp8_hevmask q13u8 = vcgtq_u8(q13u8, qthresh); q14u8 = vcgtq_u8(q14u8, qthresh); q15u8 = vmaxq_u8(q15u8, q1u8); q15u8 = vcgeq_u8(qlimit, q15u8); q1u8 = vabdq_u8(q5, q8); q12u8 = vqaddq_u8(q12u8, q12u8); // vp8_filter() function // convert to signed q0u8 = vdupq_n_u8(0x80); q9 = veorq_u8(q9, q0u8); q8 = veorq_u8(q8, q0u8); q7 = veorq_u8(q7, q0u8); q6 = veorq_u8(q6, q0u8); q5 = veorq_u8(q5, q0u8); q4 = veorq_u8(q4, q0u8); q1u8 = vshrq_n_u8(q1u8, 1); q12u8 = vqaddq_u8(q12u8, q1u8); q14u8 = vorrq_u8(q13u8, q14u8); q12u8 = vcgeq_u8(qblimit, q12u8); q2s16 = vsubl_s8(vget_low_s8(vreinterpretq_s8_u8(q7)), vget_low_s8(vreinterpretq_s8_u8(q6))); q13s16 = vsubl_s8(vget_high_s8(vreinterpretq_s8_u8(q7)), vget_high_s8(vreinterpretq_s8_u8(q6))); q1s8 = vqsubq_s8(vreinterpretq_s8_u8(q5), vreinterpretq_s8_u8(q8)); q11s16 = vdupq_n_s16(3); q2s16 = vmulq_s16(q2s16, q11s16); q13s16 = vmulq_s16(q13s16, q11s16); q15u8 = vandq_u8(q15u8, q12u8); q2s16 = vaddw_s8(q2s16, vget_low_s8(q1s8)); q13s16 = vaddw_s8(q13s16, vget_high_s8(q1s8)); q12u8 = vdupq_n_u8(3); q11u8 = vdupq_n_u8(4); // vp8_filter = clamp(vp8_filter + 3 * ( qs0 - ps0)) d2 = vqmovn_s16(q2s16); d3 = vqmovn_s16(q13s16); q1s8 = vcombine_s8(d2, d3); q1s8 = vandq_s8(q1s8, vreinterpretq_s8_u8(q15u8)); q13s8 = vandq_s8(q1s8, vreinterpretq_s8_u8(q14u8)); q2s8 = vqaddq_s8(q13s8, vreinterpretq_s8_u8(q11u8)); q13s8 = vqaddq_s8(q13s8, vreinterpretq_s8_u8(q12u8)); q2s8 = vshrq_n_s8(q2s8, 3); q13s8 = vshrq_n_s8(q13s8, 3); q7s8 = vqsubq_s8(vreinterpretq_s8_u8(q7), q2s8); q6s8 = vqaddq_s8(vreinterpretq_s8_u8(q6), q13s8); q1s8 = vbicq_s8(q1s8, vreinterpretq_s8_u8(q14u8)); q0u16 = q11u16 = q12u16 = q13u16 = q14u16 = q15u16 = vdupq_n_u16(63); d5 = vdup_n_s8(9); d4 = vdup_n_s8(18); q0s16 = vmlal_s8(vreinterpretq_s16_u16(q0u16), vget_low_s8(q1s8), d5); q11s16 = vmlal_s8(vreinterpretq_s16_u16(q11u16), vget_high_s8(q1s8), d5); d5 = vdup_n_s8(27); q12s16 = vmlal_s8(vreinterpretq_s16_u16(q12u16), vget_low_s8(q1s8), d4); q13s16 = vmlal_s8(vreinterpretq_s16_u16(q13u16), vget_high_s8(q1s8), d4); q14s16 = vmlal_s8(vreinterpretq_s16_u16(q14u16), vget_low_s8(q1s8), d5); q15s16 = vmlal_s8(vreinterpretq_s16_u16(q15u16), vget_high_s8(q1s8), d5); d0 = vqshrn_n_s16(q0s16 , 7); d1 = vqshrn_n_s16(q11s16, 7); d24 = vqshrn_n_s16(q12s16, 7); d25 = vqshrn_n_s16(q13s16, 7); d28 = vqshrn_n_s16(q14s16, 7); d29 = vqshrn_n_s16(q15s16, 7); q0s8 = vcombine_s8(d0, d1); q12s8 = vcombine_s8(d24, d25); q14s8 = vcombine_s8(d28, d29); q11s8 = vqsubq_s8(vreinterpretq_s8_u8(q9), q0s8); q0s8 = vqaddq_s8(vreinterpretq_s8_u8(q4), q0s8); q13s8 = vqsubq_s8(vreinterpretq_s8_u8(q8), q12s8); q12s8 = vqaddq_s8(vreinterpretq_s8_u8(q5), q12s8); q15s8 = vqsubq_s8((q7s8), q14s8); q14s8 = vqaddq_s8((q6s8), q14s8); q1u8 = vdupq_n_u8(0x80); *q9r = veorq_u8(vreinterpretq_u8_s8(q11s8), q1u8); *q8r = veorq_u8(vreinterpretq_u8_s8(q13s8), q1u8); *q7r = veorq_u8(vreinterpretq_u8_s8(q15s8), q1u8); *q6r = veorq_u8(vreinterpretq_u8_s8(q14s8), q1u8); *q5r = veorq_u8(vreinterpretq_u8_s8(q12s8), q1u8); *q4r = veorq_u8(vreinterpretq_u8_s8(q0s8), q1u8); return; }