@@ -2148,20 +2148,19 @@ compress_encode11_neon_loop:
21482148// For each coefficient x in [ 0 , q):
21492149// compress(x , 1 ) = 1 if 833 <= x <= 2496 , else 0 .
21502150//
2151- // Vector strategy ( 8 coefficients - > 1 byte per iteration):
2152- // 1 ) Load 8 x uint16 coefficients into V0.H8.
2153- // 2 ) CMHS twice (cmgt_u_eq_8h_opcode = unsigned >=) to identify compress= 1 range.
2154- // Lower: V0 >= 833 - > compress= 1 candidate.
2155- // Upper: V0 >= 2497 - > compress= 0 (excluded).
2156- // 3 ) BIC to combine: 0xFFFF where 833 <= x <= 2496 .
2157- // 4 ) VUSHR $ 15 to reduce each lane to 0x0001 or 0x0000 .
2151+ // Vector strategy ( 32 coefficients - > 4 bytes per iteration , 8 iterations total):
2152+ // 1 ) Load 4 x 8 coefficients into V0 - V3.H8 ( 64 bytes).
2153+ // 2 ) CMHS twice per register (cmgt_u_eq_8h_opcode = unsigned >=) to identify range.
2154+ // 3 ) BIC per register: V20..V23 = 0xFFFF where 833 <= x <= 2496 .
2155+ // 4 ) VUSHR $ 15 : convert to 0x0001 / 0x0000 per lane.
21582156// 5 ) MUL by bit - position weights { 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 }.
2159- // 6 ) ADDV to sum all 8 weighted bits into one halfword = output byte.
2157+ // 6 ) ADDV: sum all 8 lanes into H20..H23 (four output bytes).
2158+ // 7 ) Extract byte 0 from each , pack into 32 - bit word , store 4 bytes.
21602159//
21612160// Register allocation (setup once , outside loop ):
21622161// V27.H8 = { 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 } bit - position weights
2163- // V28.H8 = broadcast( 833 ) lower threshold (CMHS: x >= 833 )
2164- // V29.H8 = broadcast( 2497 ) upper threshold (CMHS: x >= 2497 means x not in range)
2162+ // V28.H8 = broadcast( 833 ) lower threshold (CMHS: x >= 833 )
2163+ // V29.H8 = broadcast( 2497 ) upper threshold (CMHS: x >= 2497 means x out of range)
21652164//
21662165// func ringCompressAndEncode1NEON( out [] byte , f * ringElement)
21672166TEXT ·ringCompressAndEncode1NEON(SB) , NOSPLIT , $ 0 - 32
@@ -2178,41 +2177,68 @@ TEXT ·ringCompressAndEncode1NEON(SB), NOSPLIT, $0-32
21782177
21792178 // V27 = { 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 }: bit - position weights for packing.
21802179 // Low 64 bits (lanes 0 - 3 ): 0x0008_0004_0002_0001 (little - endian halfwords)
2181- // High 64 bits (lanes 4 - 7 ): 0x0080_0040_0020_0010
2180+ // High 64 bits (lanes 4 - 7 ): low << 4 = 0x0080_0040_0020_0010
21822181 MOVD $ 0x0008000400020001 , R2
21832182 VMOV R2 , V27.D [ 0 ]
2184- MOVD $ 0x0080004000200010 , R2
2183+ LSL $ 4 , R2 , R2
21852184 VMOV R2 , V27.D [ 1 ]
21862185
2187- MOVD $ 32 , R2 // 32 iterations: 8 coefficients each - > 256 total - > 32 bytes
2186+ MOVD $ 8 , R2 // 8 iterations: 32 coefficients each - > 256 total - > 32 bytes
21882187
21892188compress_encode1_neon_loop:
2190- VLD1.P 16 (R1) , [ V0.H8 ] // Load 8 coefficients ( 16 bytes)
2191-
2192- // V20 = 0xFFFF where V0 >= 833 (coefficient in compress= 1 range , lower bound )
2193- WORD $ 0x6E7C3C14 // CMHS V20.H8 , V0.H8 , V28.H8
2194-
2195- // V21 = 0xFFFF where V0 >= 2497 (coefficient above compress= 1 range , upper bound )
2196- WORD $ 0x6E7D3C15 // CMHS V21.H8 , V0.H8 , V29.H8
2197-
2198- // V20 = 0xFFFF where 833 <= coefficient <= 2496 (compress= 1 )
2199- // BIC V20.B16 , V20.B16 , V21.B16 => V20 = V20 AND NOT (V21)
2200- WORD $ 0x4E751E94 // BIC V20.B16 , V20.B16 , V21.B16
2201-
2202- // V20 = 0x0001 or 0x0000 per lane ( 1 = compress bit)
2189+ // Load 32 coefficients as 4 x 8 halfwords ( 64 bytes)
2190+ VLD1.P 64 (R1) , [ V0.H8 , V1.H8 , V2.H8 , V3.H8 ]
2191+
2192+ // V20 = (V0 >= 833 ) AND NOT (V0 >= 2497 ) = 0xFFFF where compress(coeff)= 1
2193+ WORD $ 0x6E7C3C14 // CMHS V20.H8 , V0.H8 , V28.H8 (vd= 20 , vn= 0 , vm= 28 )
2194+ WORD $ 0x6E7D3C15 // CMHS V21.H8 , V0.H8 , V29.H8 (vd= 21 , vn= 0 , vm= 29 )
2195+ WORD $ 0x4E751E94 // BIC V20.B16 , V20.B16 , V21.B16
2196+
2197+ // V21 = (V1 >= 833 ) AND NOT (V1 >= 2497 )
2198+ WORD $ 0x6E7C3C35 // CMHS V21.H8 , V1.H8 , V28.H8 (vd= 21 , vn= 1 , vm= 28 )
2199+ WORD $ 0x6E7D3C36 // CMHS V22.H8 , V1.H8 , V29.H8 (vd= 22 , vn= 1 , vm= 29 )
2200+ WORD $ 0x4E761EB5 // BIC V21.B16 , V21.B16 , V22.B16
2201+
2202+ // V22 = (V2 >= 833 ) AND NOT (V2 >= 2497 )
2203+ WORD $ 0x6E7C3C56 // CMHS V22.H8 , V2.H8 , V28.H8 (vd= 22 , vn= 2 , vm= 28 )
2204+ WORD $ 0x6E7D3C57 // CMHS V23.H8 , V2.H8 , V29.H8 (vd= 23 , vn= 2 , vm= 29 )
2205+ WORD $ 0x4E771ED6 // BIC V22.B16 , V22.B16 , V23.B16
2206+
2207+ // V23 = (V3 >= 833 ) AND NOT (V3 >= 2497 )
2208+ WORD $ 0x6E7C3C77 // CMHS V23.H8 , V3.H8 , V28.H8 (vd= 23 , vn= 3 , vm= 28 )
2209+ WORD $ 0x6E7D3C78 // CMHS V24.H8 , V3.H8 , V29.H8 (vd= 24 , vn= 3 , vm= 29 )
2210+ WORD $ 0x4E781EF7 // BIC V23.B16 , V23.B16 , V24.B16
2211+
2212+ // Convert 0xFFFF / 0x0000 to 0x0001 / 0x0000 in all four registers
22032213 VUSHR $ 15 , V20.H8 , V20.H8
2204-
2205- // V20 = {weight * bit} per lane , where weights are { 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 }
2206- WORD $ 0x4E7B9E94 // MUL V20.H8 , V20.H8 , V27.H8
2207-
2208- // H20 = sum of all 8 weighted lanes = packed output byte
2209- WORD $ 0x4E71BA94 // ADDV H20 , V20. 8H
2210-
2211- // Extract the 64 - bit value from V20 and store the low byte.
2212- // After ADDV , V20 [ 15 : 0 ] holds the sum ( 0 - 255 ) ; V20 upper bits are MUL leftovers.
2213- VMOV V20.D [ 0 ], R10
2214- MOVB R10 , (R0)
2215- ADD $ 1 , R0
2214+ VUSHR $ 15 , V21.H8 , V21.H8
2215+ VUSHR $ 15 , V22.H8 , V22.H8
2216+ VUSHR $ 15 , V23.H8 , V23.H8
2217+
2218+ // Multiply by bit - position weights { 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 }
2219+ WORD $ 0x4E7B9E94 // MUL V20.H8 , V20.H8 , V27.H8 (vd= 20 , vn= 20 , vm= 27 )
2220+ WORD $ 0x4E7B9EB5 // MUL V21.H8 , V21.H8 , V27.H8 (vd= 21 , vn= 21 , vm= 27 )
2221+ WORD $ 0x4E7B9ED6 // MUL V22.H8 , V22.H8 , V27.H8 (vd= 22 , vn= 22 , vm= 27 )
2222+ WORD $ 0x4E7B9EF7 // MUL V23.H8 , V23.H8 , V27.H8 (vd= 23 , vn= 23 , vm= 27 )
2223+
2224+ // Sum all 8 weighted lanes: output byte in H20..H23 (= byte [ 0 ] of V20..V23)
2225+ WORD $ 0x4E71BA94 // ADDV H20 , V20. 8H (vd= 20 , vn= 20 )
2226+ WORD $ 0x4E71BAB5 // ADDV H21 , V21. 8H (vd= 21 , vn= 21 )
2227+ WORD $ 0x4E71BAD6 // ADDV H22 , V22. 8H (vd= 22 , vn= 22 )
2228+ WORD $ 0x4E71BAF7 // ADDV H23 , V23. 8H (vd= 23 , vn= 23 )
2229+
2230+ // Extract byte 0 from each halfword result (sum <= 255 , so byte [ 0 ] is the full result)
2231+ VMOV V20.B [ 0 ], R10
2232+ VMOV V21.B [ 0 ], R11
2233+ VMOV V22.B [ 0 ], R12
2234+ VMOV V23.B [ 0 ], R13
2235+
2236+ // Pack 4 bytes into a 32 - bit word and store
2237+ ORR R11 << 8 , R10 , R10
2238+ ORR R12 << 16 , R10 , R10
2239+ ORR R13 << 24 , R10 , R10
2240+ MOVW R10 , (R0)
2241+ ADD $ 4 , R0
22162242
22172243 SUB $ 1 , R2 , R2
22182244 CBNZ R2 , compress_encode1_neon_loop
0 commit comments