3737 VZIP1 V5.H8 , V4.H8 , V2.H8 \
3838 VZIP2 V5.H8 , V4.H8 , V0.H8
3939
40- // Store the lanes of V2 th at differ from their predecessor (previous lane ,
40+ // Store the lanes of Vin th at differ from their predecessor (previous lane ,
4141// or last lane of V1 for lane 0 ) at (Rout) , advancing Rout by 2 bytes per
4242// lane kept. Writes a full 16 bytes ; the caller guarantees slack.
4343// Rcnt receives the number of lanes kept. Clobbers V3 - V5 , R14 , R15 , R16.
44- #define STOREUNIQ(Rout , Rcnt) \
45- VEXT $ 14 , V2 .B16 , V1.B16 , V3.B16 \
46- VCMEQ V3.H8 , V2 .H8 , V4.H8 \
44+ #define STOREUNIQ(Vin , Rout, Rcnt) \
45+ VEXT $ 14 , Vin .B16 , V1.B16 , V3.B16 \
46+ VCMEQ V3.H8 , Vin .H8 , V4.H8 \
4747 VUZP1 V4.B16 , V4.B16 , V4.B16 \
4848 VMOV V4.D [ 0 ], R14 \
4949 AND R12 , R14 , R14 \
5454 SUB R14 , R19 , Rcnt \
5555 ADD R15 << 4 , R6 , R16 \
5656 VLD1 (R16) , [ V5.B16 ] \
57- VTBL V5.B16 , [ V2 .B16], V3.B16 \
57+ VTBL V5.B16 , [ Vin .B16], V3.B16 \
5858 VST1 [ V3.B16 ], (Rout) \
5959 ADD Rcnt<< 1 , Rout , Rout
6060
@@ -86,7 +86,7 @@ TEXT ·unionKernelNEON(SB), NOSPLIT, $0-120
8686 MERGE
8787 // laststore = all ones (never equal to a first stored lane)
8888 VCMEQ V0.H8 , V0.H8 , V1.H8
89- STOREUNIQ(R2 , R17)
89+ STOREUNIQ(V2 , R2, R17)
9090 VORR V2.B16 , V2.B16 , V1.B16
9191
9292loop :
@@ -111,22 +111,52 @@ loop:
111111 CMP R21 , R20
112112 BHS disjoint
113113 MERGE
114- STOREUNIQ(R2 , R17)
114+ STOREUNIQ(V2 , R2, R17)
115115 VORR V2.B16 , V2.B16 , V1.B16
116116 B loop
117117
118+ // Fast - forward loop for consecutive disjoint blocks. The head select is a
119+ // plain branch: on run - structured data it predicts , keeping the untaken
120+ // cursor off the loop - carried chain th at the main loop 's CSEL select
121+ // serializes. Interleaving input rejoins the main loop after one merge.
118122disjoint:
119- VORR V2.B16 , V2.B16 , V22.B16 // stash fresh
120- VORR V0.B16 , V0.B16 , V2.B16 // emit old carry as this round's minimum
121- STOREUNIQ(R2 , R17)
122- VORR V2.B16 , V2.B16 , V1.B16 // laststore = old carry
123- VORR V22.B16 , V22.B16 , V0.B16 // carry = fresh
123+ STOREUNIQ(V0 , R2 , R17)
124+ VORR V0.B16 , V0.B16 , V1.B16 // laststore = old carry
125+ VORR V2.B16 , V2.B16 , V0.B16 // carry = fresh
126+
127+ ffloop:
128+ CMP R3 , R0
129+ BHS done
130+ CMP R4 , R1
131+ BHS done
132+ MOVHU (R0) , R8
133+ MOVHU (R1) , R9
134+ CMP R9 , R8
135+ BHI fftake2
136+ VLD1.P 16 (R0) , [ V2.H8 ] // take set1's block on tie/less
137+ MOVD R8 , R20
138+ B ffcheck
139+ fftake2:
140+ VLD1.P 16 (R1) , [ V2.H8 ]
141+ MOVD R9 , R20
142+ ffcheck:
143+ VMOV V0.H [ 7 ], R21
144+ CMP R21 , R20
145+ BLO ffmerge
146+ STOREUNIQ(V0 , R2 , R17)
147+ VORR V0.B16 , V0.B16 , V1.B16 // laststore = old carry
148+ VORR V2.B16 , V2.B16 , V0.B16 // carry = fresh
149+ B ffloop
150+
151+ ffmerge:
152+ MERGE
153+ STOREUNIQ(V2 , R2 , R17)
154+ VORR V2.B16 , V2.B16 , V1.B16
124155 B loop
125156
126157done:
127158 // flush carry through the dedup into the leftover buffer
128- VORR V0.B16 , V0.B16 , V2.B16
129- STOREUNIQ(R7 , R17)
159+ STOREUNIQ(V0 , R7 , R17)
130160 MOVD R17 , leftoverLen + 112 (FP)
131161
132162 // outLen = ( out - outBase) / 2
0 commit comments