This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-go.git
The following commit(s) were added to refs/heads/main by this push:
new 89448e69 perf(compute): add ARM64 NEON comparisons for 8- and 16-bit
integers (#1288)
89448e69 is described below
commit 89448e691dcf4930492d83ebad760f54d8bea6fc
Author: Minh Vu <[email protected]>
AuthorDate: Fri Sep 4 18:28:26 2026 +0200
perf(compute): add ARM64 NEON comparisons for 8- and 16-bit integers (#1288)
## Summary
- Add ARM64 NEON comparisons for `int8`, `uint8`, `int16`, and `uint16`.
- Cover array-array, array-scalar, and scalar-array inputs.
- Keep the existing generic fallback for tails and bitmap offsets.
- Add correctness coverage for signed and unsigned boundaries and bit
packing.
- Add native benchmarks for the narrow integer types.
## Benchmark
Apple M1 Pro, Go 1.26.3. `-benchtime=50ms -count=3`. Baseline is `-tags
noasm`.
| Case | NEON | Generic | Speedup |
| --- | ---: | ---: | ---: |
| int8 array-array 64K alternating | 5.01 us | 75.7 us | 15.1x |
| uint8 array-scalar 1M random50 | 68.9 us | 1.00 ms | 14.5x |
| int16 scalar-array 64K clustered50 | 4.31 us | 59.1 us | 13.7x |
| uint16 array-array 1M all | 79.7 us | 1.02 ms | 12.8x |
The benchmark matrix also covers 1K, 64K, and 1M elements, all three
operand shapes, alternating, random 25/50/75%, clustered 50%, all, and
none patterns.
## Tests
- `go test ./arrow/compute/internal/kernels ./arrow/compute`
- `go test -race ./arrow/compute/internal/kernels ./arrow/compute`
- `go test -tags noasm ./arrow/compute/internal/kernels ./arrow/compute`
- Darwin/amd64 and Linux/amd64 compile checks
---
.../internal/kernels/scalar_comparison_arm64.go | 15 +-
.../kernels/scalar_comparison_arm64_test.go | 52 +
.../kernels/scalar_comparison_narrow_arm64.s | 1068 ++++++++++++++++++++
.../kernels/scalar_comparison_narrow_bench_test.go | 105 ++
4 files changed, 1237 insertions(+), 3 deletions(-)
diff --git a/arrow/compute/internal/kernels/scalar_comparison_arm64.go
b/arrow/compute/internal/kernels/scalar_comparison_arm64.go
index f5d99611..f5af8701 100644
--- a/arrow/compute/internal/kernels/scalar_comparison_arm64.go
+++ b/arrow/compute/internal/kernels/scalar_comparison_arm64.go
@@ -34,9 +34,13 @@ const (
//go:noescape
func _comparison_neon(typ int, op int, shape int, left, right, out
unsafe.Pointer, groups int64)
+//go:noescape
+func _comparison_narrow_neon(typ int, op int, shape int, left, right, out
unsafe.Pointer, groups int64)
+
func neonComparisonSupported(typ arrow.Type) bool {
switch typ {
- case arrow.INT32, arrow.UINT32, arrow.INT64, arrow.UINT64,
+ case arrow.INT8, arrow.UINT8, arrow.INT16, arrow.UINT16,
+ arrow.INT32, arrow.UINT32, arrow.INT64, arrow.UINT64,
arrow.FLOAT32, arrow.FLOAT64:
return true
default:
@@ -92,8 +96,13 @@ func compareNeon(typ arrow.Type, op CompareOperator, width,
shape int, left, rig
case neonCompareScalarArray:
assemblyRight = right[:bulk*width]
}
- _comparison_neon(int(typ), int(op), shape,
- unsafe.Pointer(&assemblyLeft[0]),
unsafe.Pointer(&assemblyRight[0]), unsafe.Pointer(&out[0]), int64(bulk/8))
+ if width <= 2 {
+ _comparison_narrow_neon(int(typ), int(op), shape,
+ unsafe.Pointer(&assemblyLeft[0]),
unsafe.Pointer(&assemblyRight[0]), unsafe.Pointer(&out[0]), int64(bulk/8))
+ } else {
+ _comparison_neon(int(typ), int(op), shape,
+ unsafe.Pointer(&assemblyLeft[0]),
unsafe.Pointer(&assemblyRight[0]), unsafe.Pointer(&out[0]), int64(bulk/8))
+ }
}
if tail := n - bulk; tail != 0 {
diff --git a/arrow/compute/internal/kernels/scalar_comparison_arm64_test.go
b/arrow/compute/internal/kernels/scalar_comparison_arm64_test.go
index 460d8aca..4e92d475 100644
--- a/arrow/compute/internal/kernels/scalar_comparison_arm64_test.go
+++ b/arrow/compute/internal/kernels/scalar_comparison_arm64_test.go
@@ -118,6 +118,54 @@ func TestNeonComparisons(t *testing.T) {
testNeonComparison(t, left, right, uint32(1<<31), uint32(7))
})
+ t.Run("int8", func(t *testing.T) {
+ leftPattern := []int8{-1 << 7, -17, -1, 0, 1, 17, 1<<7 - 1, 42,
-42, 3, 9, -9, 5, -5, 2, -2}
+ rightPattern := []int8{1<<7 - 1, -17, 0, 1, -1, -42, -1 << 7,
42, 4, -3, 9, -10, -5, 5, -2, 2}
+ left := make([]int8, neonComparisonTestLength)
+ right := make([]int8, neonComparisonTestLength)
+ for i := range left {
+ left[i] = leftPattern[i%len(leftPattern)]
+ right[i] = rightPattern[i%len(rightPattern)]
+ }
+ testNeonComparison(t, left, right, int8(-3), int8(4))
+ })
+
+ t.Run("uint8", func(t *testing.T) {
+ leftPattern := []uint8{0, 1, 2, 1<<7 - 1, 1 << 7, ^uint8(0),
42, 7, 100, 3, 19, 5, 77, 11, 12, 13}
+ rightPattern := []uint8{^uint8(0), 1, 3, 1 << 7, 1<<7 - 1, 0,
42, 8, 99, 4, 19, 6, 78, 10, 13, 12}
+ left := make([]uint8, neonComparisonTestLength)
+ right := make([]uint8, neonComparisonTestLength)
+ for i := range left {
+ left[i] = leftPattern[i%len(leftPattern)]
+ right[i] = rightPattern[i%len(rightPattern)]
+ }
+ testNeonComparison(t, left, right, uint8(1<<7), uint8(7))
+ })
+
+ t.Run("int16", func(t *testing.T) {
+ leftPattern := []int16{-1 << 15, -17, -1, 0, 1, 17, 1<<15 - 1,
42, -42, 3, 9, -9, 5, -5, 2, -2}
+ rightPattern := []int16{1<<15 - 1, -17, 0, 1, -1, -42, -1 <<
15, 42, 4, -3, 9, -10, -5, 5, -2, 2}
+ left := make([]int16, neonComparisonTestLength)
+ right := make([]int16, neonComparisonTestLength)
+ for i := range left {
+ left[i] = leftPattern[i%len(leftPattern)]
+ right[i] = rightPattern[i%len(rightPattern)]
+ }
+ testNeonComparison(t, left, right, int16(-3), int16(4))
+ })
+
+ t.Run("uint16", func(t *testing.T) {
+ leftPattern := []uint16{0, 1, 2, 1<<15 - 1, 1 << 15,
^uint16(0), 42, 7, 100, 3, 19, 5, 77, 11, 12, 13}
+ rightPattern := []uint16{^uint16(0), 1, 3, 1 << 15, 1<<15 - 1,
0, 42, 8, 99, 4, 19, 6, 78, 10, 13, 12}
+ left := make([]uint16, neonComparisonTestLength)
+ right := make([]uint16, neonComparisonTestLength)
+ for i := range left {
+ left[i] = leftPattern[i%len(leftPattern)]
+ right[i] = rightPattern[i%len(rightPattern)]
+ }
+ testNeonComparison(t, left, right, uint16(1<<15), uint16(7))
+ })
+
t.Run("int64", func(t *testing.T) {
leftPattern := []int64{-1 << 63, -17, -1, 0, 1, 17, 1<<63 - 1,
42, -42, 3, 9, -9, 5, -5, 2, -2}
rightPattern := []int64{1<<63 - 1, -17, 0, 1, -1, -42, -1 <<
63, 42, 4, -3, 9, -10, -5, 5, -2, 2}
@@ -168,6 +216,10 @@ func TestNeonComparisons(t *testing.T) {
}
func TestNeonComparisonBitPacking(t *testing.T) {
+ t.Run("int8", testNeonComparisonBitPacking[int8])
+ t.Run("uint8", testNeonComparisonBitPacking[uint8])
+ t.Run("int16", testNeonComparisonBitPacking[int16])
+ t.Run("uint16", testNeonComparisonBitPacking[uint16])
t.Run("int32", testNeonComparisonBitPacking[int32])
t.Run("uint32", testNeonComparisonBitPacking[uint32])
t.Run("int64", testNeonComparisonBitPacking[int64])
diff --git a/arrow/compute/internal/kernels/scalar_comparison_narrow_arm64.s
b/arrow/compute/internal/kernels/scalar_comparison_narrow_arm64.s
new file mode 100644
index 00000000..c52be4b7
--- /dev/null
+++ b/arrow/compute/internal/kernels/scalar_comparison_narrow_arm64.s
@@ -0,0 +1,1068 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:build go1.18 && arm64 && !noasm && !appengine
+
+#include "textflag.h"
+
+DATA LCMPNEON_NARROW_WEIGHTS<>+0(SB)/8, $0x0706050403020100
+DATA LCMPNEON_NARROW_WEIGHTS<>+8(SB)/8, $0x0003000200010000
+DATA LCMPNEON_NARROW_WEIGHTS<>+16(SB)/8, $0x0007000600050004
+GLOBL LCMPNEON_NARROW_WEIGHTS<>(SB), (NOPTR+RODATA), $24
+
+TEXT ยท_comparison_narrow_neon(SB), NOSPLIT|NOFRAME, $0-56
+ MOVD typ+0(FP), R0
+ MOVD op+8(FP), R1
+ MOVD shape+16(FP), R2
+ MOVD left+24(FP), R3
+ MOVD right+32(FP), R4
+ MOVD out+40(FP), R5
+ MOVD groups+48(FP), R6
+
+ CMP $2, R0
+ BEQ Lnarrow8Unsigned
+ CMP $3, R0
+ BEQ Lnarrow8Signed
+ CMP $4, R0
+ BEQ Lnarrow16Unsigned
+ CMP $5, R0
+ BEQ Lnarrow16Signed
+ JMP LnarrowReturn
+
+Lnarrow8Signed:
+ MOVD $LCMPNEON_NARROW_WEIGHTS<>(SB), R10
+ VLD1 (R10), [V20.B8]
+ CMP $0, R2
+ BEQ Lnarrow8SignedAASelect
+ CMP $1, R2
+ BEQ Lnarrow8SignedASSelect
+ CMP $2, R2
+ BEQ Lnarrow8SignedSASelect
+ JMP LnarrowReturn
+
+Lnarrow8SignedAASelect:
+ CMP $0, R1
+ BEQ Lnarrow8SignedAAEQ
+ CMP $1, R1
+ BEQ Lnarrow8SignedAANE
+ CMP $2, R1
+ BEQ Lnarrow8SignedAAGT
+ CMP $3, R1
+ BEQ Lnarrow8SignedAAGE
+ JMP LnarrowReturn
+
+Lnarrow8SignedASSelect:
+ CMP $0, R1
+ BEQ Lnarrow8SignedASEQ
+ CMP $1, R1
+ BEQ Lnarrow8SignedASNE
+ CMP $2, R1
+ BEQ Lnarrow8SignedASGT
+ CMP $3, R1
+ BEQ Lnarrow8SignedASGE
+ JMP LnarrowReturn
+
+Lnarrow8SignedSASelect:
+ CMP $0, R1
+ BEQ Lnarrow8SignedSAEQ
+ CMP $1, R1
+ BEQ Lnarrow8SignedSANE
+ CMP $2, R1
+ BEQ Lnarrow8SignedSAGT
+ CMP $3, R1
+ BEQ Lnarrow8SignedSAGE
+ JMP LnarrowReturn
+
+Lnarrow8SignedAAEQ:
+Lnarrow8SignedAAEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e218c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedAAEQLoop
+
+Lnarrow8SignedAANE:
+Lnarrow8SignedAANELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e218c02
+ WORD $0x2e205842
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedAANELoop
+
+Lnarrow8SignedAAGT:
+Lnarrow8SignedAAGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ VLD1 (R4), [V1.B8]
+ WORD $0x0e213402
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedAAGTLoop
+
+Lnarrow8SignedAAGE:
+Lnarrow8SignedAAGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ VLD1 (R4), [V1.B8]
+ WORD $0x0e213c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedAAGELoop
+
+Lnarrow8SignedASEQ:
+VLD1R (R4), [V1.B8]
+Lnarrow8SignedASEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ WORD $0x2e218c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedASEQLoop
+
+Lnarrow8SignedASNE:
+VLD1R (R4), [V1.B8]
+Lnarrow8SignedASNELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ WORD $0x2e218c02
+ WORD $0x2e205842
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedASNELoop
+
+Lnarrow8SignedASGT:
+VLD1R (R4), [V1.B8]
+Lnarrow8SignedASGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ WORD $0x0e213402
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedASGTLoop
+
+Lnarrow8SignedASGE:
+VLD1R (R4), [V1.B8]
+Lnarrow8SignedASGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ WORD $0x0e213c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedASGELoop
+
+Lnarrow8SignedSAEQ:
+VLD1R (R3), [V0.B8]
+Lnarrow8SignedSAEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e218c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedSAEQLoop
+
+Lnarrow8SignedSANE:
+VLD1R (R3), [V0.B8]
+Lnarrow8SignedSANELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e218c02
+ WORD $0x2e205842
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedSANELoop
+
+Lnarrow8SignedSAGT:
+VLD1R (R3), [V0.B8]
+Lnarrow8SignedSAGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.B8]
+ WORD $0x0e213402
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedSAGTLoop
+
+Lnarrow8SignedSAGE:
+VLD1R (R3), [V0.B8]
+Lnarrow8SignedSAGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.B8]
+ WORD $0x0e213c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8SignedSAGELoop
+
+Lnarrow8Unsigned:
+ MOVD $LCMPNEON_NARROW_WEIGHTS<>(SB), R10
+ VLD1 (R10), [V20.B8]
+ CMP $0, R2
+ BEQ Lnarrow8UnsignedAASelect
+ CMP $1, R2
+ BEQ Lnarrow8UnsignedASSelect
+ CMP $2, R2
+ BEQ Lnarrow8UnsignedSASelect
+ JMP LnarrowReturn
+
+Lnarrow8UnsignedAASelect:
+ CMP $0, R1
+ BEQ Lnarrow8UnsignedAAEQ
+ CMP $1, R1
+ BEQ Lnarrow8UnsignedAANE
+ CMP $2, R1
+ BEQ Lnarrow8UnsignedAAGT
+ CMP $3, R1
+ BEQ Lnarrow8UnsignedAAGE
+ JMP LnarrowReturn
+
+Lnarrow8UnsignedASSelect:
+ CMP $0, R1
+ BEQ Lnarrow8UnsignedASEQ
+ CMP $1, R1
+ BEQ Lnarrow8UnsignedASNE
+ CMP $2, R1
+ BEQ Lnarrow8UnsignedASGT
+ CMP $3, R1
+ BEQ Lnarrow8UnsignedASGE
+ JMP LnarrowReturn
+
+Lnarrow8UnsignedSASelect:
+ CMP $0, R1
+ BEQ Lnarrow8UnsignedSAEQ
+ CMP $1, R1
+ BEQ Lnarrow8UnsignedSANE
+ CMP $2, R1
+ BEQ Lnarrow8UnsignedSAGT
+ CMP $3, R1
+ BEQ Lnarrow8UnsignedSAGE
+ JMP LnarrowReturn
+
+Lnarrow8UnsignedAAEQ:
+Lnarrow8UnsignedAAEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e218c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedAAEQLoop
+
+Lnarrow8UnsignedAANE:
+Lnarrow8UnsignedAANELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e218c02
+ WORD $0x2e205842
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedAANELoop
+
+Lnarrow8UnsignedAAGT:
+Lnarrow8UnsignedAAGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e213402
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedAAGTLoop
+
+Lnarrow8UnsignedAAGE:
+Lnarrow8UnsignedAAGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e213c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedAAGELoop
+
+Lnarrow8UnsignedASEQ:
+VLD1R (R4), [V1.B8]
+Lnarrow8UnsignedASEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ WORD $0x2e218c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedASEQLoop
+
+Lnarrow8UnsignedASNE:
+VLD1R (R4), [V1.B8]
+Lnarrow8UnsignedASNELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ WORD $0x2e218c02
+ WORD $0x2e205842
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedASNELoop
+
+Lnarrow8UnsignedASGT:
+VLD1R (R4), [V1.B8]
+Lnarrow8UnsignedASGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ WORD $0x2e213402
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedASGTLoop
+
+Lnarrow8UnsignedASGE:
+VLD1R (R4), [V1.B8]
+Lnarrow8UnsignedASGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.B8]
+ WORD $0x2e213c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedASGELoop
+
+Lnarrow8UnsignedSAEQ:
+VLD1R (R3), [V0.B8]
+Lnarrow8UnsignedSAEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e218c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedSAEQLoop
+
+Lnarrow8UnsignedSANE:
+VLD1R (R3), [V0.B8]
+Lnarrow8UnsignedSANELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e218c02
+ WORD $0x2e205842
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedSANELoop
+
+Lnarrow8UnsignedSAGT:
+VLD1R (R3), [V0.B8]
+Lnarrow8UnsignedSAGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e213402
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedSAGTLoop
+
+Lnarrow8UnsignedSAGE:
+VLD1R (R3), [V0.B8]
+Lnarrow8UnsignedSAGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.B8]
+ WORD $0x2e213c02
+ VUSHR $7, V2.B8, V2.B8
+ WORD $0x2e344442
+ VADDV V2.B8, V2
+ VMOV V2.B[0], R7
+ MOVB R7, (R5)
+ ADD $8, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow8UnsignedSAGELoop
+
+Lnarrow16Signed:
+ MOVD $LCMPNEON_NARROW_WEIGHTS<>(SB), R10
+ ADD $8, R10, R10
+ VLD1 (R10), [V20.H8]
+ CMP $0, R2
+ BEQ Lnarrow16SignedAASelect
+ CMP $1, R2
+ BEQ Lnarrow16SignedASSelect
+ CMP $2, R2
+ BEQ Lnarrow16SignedSASelect
+ JMP LnarrowReturn
+
+Lnarrow16SignedAASelect:
+ CMP $0, R1
+ BEQ Lnarrow16SignedAAEQ
+ CMP $1, R1
+ BEQ Lnarrow16SignedAANE
+ CMP $2, R1
+ BEQ Lnarrow16SignedAAGT
+ CMP $3, R1
+ BEQ Lnarrow16SignedAAGE
+ JMP LnarrowReturn
+
+Lnarrow16SignedASSelect:
+ CMP $0, R1
+ BEQ Lnarrow16SignedASEQ
+ CMP $1, R1
+ BEQ Lnarrow16SignedASNE
+ CMP $2, R1
+ BEQ Lnarrow16SignedASGT
+ CMP $3, R1
+ BEQ Lnarrow16SignedASGE
+ JMP LnarrowReturn
+
+Lnarrow16SignedSASelect:
+ CMP $0, R1
+ BEQ Lnarrow16SignedSAEQ
+ CMP $1, R1
+ BEQ Lnarrow16SignedSANE
+ CMP $2, R1
+ BEQ Lnarrow16SignedSAGT
+ CMP $3, R1
+ BEQ Lnarrow16SignedSAGE
+ JMP LnarrowReturn
+
+Lnarrow16SignedAAEQ:
+Lnarrow16SignedAAEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e618c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedAAEQLoop
+
+Lnarrow16SignedAANE:
+Lnarrow16SignedAANELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e618c02
+ WORD $0x6e205842
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedAANELoop
+
+Lnarrow16SignedAAGT:
+Lnarrow16SignedAAGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ VLD1 (R4), [V1.H8]
+ WORD $0x4e613402
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedAAGTLoop
+
+Lnarrow16SignedAAGE:
+Lnarrow16SignedAAGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ VLD1 (R4), [V1.H8]
+ WORD $0x4e613c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedAAGELoop
+
+Lnarrow16SignedASEQ:
+VLD1R (R4), [V1.H8]
+Lnarrow16SignedASEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ WORD $0x6e618c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedASEQLoop
+
+Lnarrow16SignedASNE:
+VLD1R (R4), [V1.H8]
+Lnarrow16SignedASNELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ WORD $0x6e618c02
+ WORD $0x6e205842
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedASNELoop
+
+Lnarrow16SignedASGT:
+VLD1R (R4), [V1.H8]
+Lnarrow16SignedASGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ WORD $0x4e613402
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedASGTLoop
+
+Lnarrow16SignedASGE:
+VLD1R (R4), [V1.H8]
+Lnarrow16SignedASGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ WORD $0x4e613c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedASGELoop
+
+Lnarrow16SignedSAEQ:
+VLD1R (R3), [V0.H8]
+Lnarrow16SignedSAEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e618c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedSAEQLoop
+
+Lnarrow16SignedSANE:
+VLD1R (R3), [V0.H8]
+Lnarrow16SignedSANELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e618c02
+ WORD $0x6e205842
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedSANELoop
+
+Lnarrow16SignedSAGT:
+VLD1R (R3), [V0.H8]
+Lnarrow16SignedSAGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.H8]
+ WORD $0x4e613402
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedSAGTLoop
+
+Lnarrow16SignedSAGE:
+VLD1R (R3), [V0.H8]
+Lnarrow16SignedSAGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.H8]
+ WORD $0x4e613c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16SignedSAGELoop
+
+Lnarrow16Unsigned:
+ MOVD $LCMPNEON_NARROW_WEIGHTS<>(SB), R10
+ ADD $8, R10, R10
+ VLD1 (R10), [V20.H8]
+ CMP $0, R2
+ BEQ Lnarrow16UnsignedAASelect
+ CMP $1, R2
+ BEQ Lnarrow16UnsignedASSelect
+ CMP $2, R2
+ BEQ Lnarrow16UnsignedSASelect
+ JMP LnarrowReturn
+
+Lnarrow16UnsignedAASelect:
+ CMP $0, R1
+ BEQ Lnarrow16UnsignedAAEQ
+ CMP $1, R1
+ BEQ Lnarrow16UnsignedAANE
+ CMP $2, R1
+ BEQ Lnarrow16UnsignedAAGT
+ CMP $3, R1
+ BEQ Lnarrow16UnsignedAAGE
+ JMP LnarrowReturn
+
+Lnarrow16UnsignedASSelect:
+ CMP $0, R1
+ BEQ Lnarrow16UnsignedASEQ
+ CMP $1, R1
+ BEQ Lnarrow16UnsignedASNE
+ CMP $2, R1
+ BEQ Lnarrow16UnsignedASGT
+ CMP $3, R1
+ BEQ Lnarrow16UnsignedASGE
+ JMP LnarrowReturn
+
+Lnarrow16UnsignedSASelect:
+ CMP $0, R1
+ BEQ Lnarrow16UnsignedSAEQ
+ CMP $1, R1
+ BEQ Lnarrow16UnsignedSANE
+ CMP $2, R1
+ BEQ Lnarrow16UnsignedSAGT
+ CMP $3, R1
+ BEQ Lnarrow16UnsignedSAGE
+ JMP LnarrowReturn
+
+Lnarrow16UnsignedAAEQ:
+Lnarrow16UnsignedAAEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e618c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedAAEQLoop
+
+Lnarrow16UnsignedAANE:
+Lnarrow16UnsignedAANELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e618c02
+ WORD $0x6e205842
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedAANELoop
+
+Lnarrow16UnsignedAAGT:
+Lnarrow16UnsignedAAGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e613402
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedAAGTLoop
+
+Lnarrow16UnsignedAAGE:
+Lnarrow16UnsignedAAGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e613c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedAAGELoop
+
+Lnarrow16UnsignedASEQ:
+VLD1R (R4), [V1.H8]
+Lnarrow16UnsignedASEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ WORD $0x6e618c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedASEQLoop
+
+Lnarrow16UnsignedASNE:
+VLD1R (R4), [V1.H8]
+Lnarrow16UnsignedASNELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ WORD $0x6e618c02
+ WORD $0x6e205842
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedASNELoop
+
+Lnarrow16UnsignedASGT:
+VLD1R (R4), [V1.H8]
+Lnarrow16UnsignedASGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ WORD $0x6e613402
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedASGTLoop
+
+Lnarrow16UnsignedASGE:
+VLD1R (R4), [V1.H8]
+Lnarrow16UnsignedASGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R3), [V0.H8]
+ WORD $0x6e613c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R3, R3
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedASGELoop
+
+Lnarrow16UnsignedSAEQ:
+VLD1R (R3), [V0.H8]
+Lnarrow16UnsignedSAEQLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e618c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedSAEQLoop
+
+Lnarrow16UnsignedSANE:
+VLD1R (R3), [V0.H8]
+Lnarrow16UnsignedSANELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e618c02
+ WORD $0x6e205842
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedSANELoop
+
+Lnarrow16UnsignedSAGT:
+VLD1R (R3), [V0.H8]
+Lnarrow16UnsignedSAGTLoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e613402
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedSAGTLoop
+
+Lnarrow16UnsignedSAGE:
+VLD1R (R3), [V0.H8]
+Lnarrow16UnsignedSAGELoop:
+ CMP $0, R6
+ BEQ LnarrowReturn
+ VLD1 (R4), [V1.H8]
+ WORD $0x6e613c02
+ VUSHR $15, V2.H8, V2.H8
+ WORD $0x6e744442
+ VADDV V2.H8, V2
+ VMOV V2.H[0], R7
+ MOVB R7, (R5)
+ ADD $16, R4, R4
+ ADD $1, R5, R5
+ SUB $1, R6, R6
+ JMP Lnarrow16UnsignedSAGELoop
+
+LnarrowReturn:
+ RET
diff --git
a/arrow/compute/internal/kernels/scalar_comparison_narrow_bench_test.go
b/arrow/compute/internal/kernels/scalar_comparison_narrow_bench_test.go
new file mode 100644
index 00000000..1086e874
--- /dev/null
+++ b/arrow/compute/internal/kernels/scalar_comparison_narrow_bench_test.go
@@ -0,0 +1,105 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//go:build go1.18
+
+package kernels
+
+import (
+ "fmt"
+ "testing"
+ "unsafe"
+
+ "github.com/apache/arrow-go/v18/arrow"
+ "github.com/apache/arrow-go/v18/arrow/bitutil"
+)
+
+var narrowComparisonBenchmarkSink byte
+
+func BenchmarkNarrowComparisons(b *testing.B) {
+ b.Run("int8", func(b *testing.B) {
+ benchmarkNarrowComparison[int8](b)
+ })
+ b.Run("uint8", func(b *testing.B) {
+ benchmarkNarrowComparison[uint8](b)
+ })
+ b.Run("int16", func(b *testing.B) {
+ benchmarkNarrowComparison[int16](b)
+ })
+ b.Run("uint16", func(b *testing.B) {
+ benchmarkNarrowComparison[uint16](b)
+ })
+}
+
+func benchmarkNarrowComparison[T arrow.NumericType](b *testing.B) {
+ patterns := []struct {
+ name string
+ pick func(int) bool
+ }{
+ {"alternating", func(i int) bool { return i%2 == 0 }},
+ {"random25", func(i int) bool { return
(uint32(i)*1664525+1013904223)%100 < 25 }},
+ {"random50", func(i int) bool { return
(uint32(i)*1664525+1013904223)%100 < 50 }},
+ {"random75", func(i int) bool { return
(uint32(i)*1664525+1013904223)%100 < 75 }},
+ {"clustered50", func(i int) bool { return (i/64)%2 == 0 }},
+ {"all", func(int) bool { return true }},
+ {"none", func(int) bool { return false }},
+ }
+
+ for _, size := range []int{1 << 10, 1 << 16, 1 << 20} {
+ for _, pattern := range patterns {
+ left, right := makeNarrowComparisonData[T](size,
pattern.pick)
+ leftBytes := arrow.GetBytes(left)
+ rightBytes := arrow.GetBytes(right)
+ scalarBytes := arrow.GetBytes([]T{100})
+
+ for _, shape := range []string{"array_array",
"array_scalar", "scalar_array"} {
+ b.Run(fmt.Sprintf("%s/%d/%s", shape, size,
pattern.name), func(b *testing.B) {
+ cmp := genCompareKernel[T](CmpGT)
+ out := make([]byte,
bitutil.BytesForBits(int64(size)))
+ b.SetBytes(int64(size) *
int64(unsafe.Sizeof(T(0))))
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ switch shape {
+ case "array_array":
+ cmp.funcAA(leftBytes,
rightBytes, out, 0)
+ case "array_scalar":
+ cmp.funcAS(leftBytes,
scalarBytes, out, 0)
+ case "scalar_array":
+ cmp.funcSA(scalarBytes,
rightBytes, out, 0)
+ }
+ narrowComparisonBenchmarkSink
^= out[0]
+ }
+ })
+ }
+ }
+ }
+}
+
+func makeNarrowComparisonData[T arrow.NumericType](size int, pick func(int)
bool) ([]T, []T) {
+ left := make([]T, size)
+ right := make([]T, size)
+ for i := range left {
+ if pick(i) {
+ left[i] = 100
+ right[i] = 50
+ } else {
+ left[i] = 50
+ right[i] = 100
+ }
+ }
+ return left, right
+}