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 11209bc4 perf(compute): add ARM64 NEON comparison kernels (#1266)
11209bc4 is described below

commit 11209bc494563ba5c5606ee157ba95ddffbf2205
Author: Minh Vu <[email protected]>
AuthorDate: Wed Sep 2 20:04:16 2026 +0200

    perf(compute): add ARM64 NEON comparison kernels (#1266)
    
    ## Summary
    
    - **Added** ARM64 NEON kernels for primitive comparisons.
    - **Covered** `int32`, `uint32`, `int64`, `uint64`, `float32`, and
    `float64`.
    - **Kept** narrow integer types and unsupported builds on the generic
    path without the NEON wrapper.
    - **Removed** redundant 64-bit packing shifts from the hot loops.
    - **Handled** array/array, array/scalar, scalar/array, bitmap offsets,
    tails, NaNs, and unsigned boundary values.
    
    ## Benchmark
    
    Apple M1 Pro, 65,536 `int64` values, `nullprob=0.000000`, 3 runs with
    `-benchtime=1s`. The generic baseline uses `-tags noasm`. Values below
    are medians.
    
    | Case | NEON | Generic | Speedup |
    | --- | ---: | ---: | ---: |
    | Array/scalar | 29.6 us/op | 76.3 us/op | ~2.6x |
    | Array/array | 29.3 us/op | 313.6 us/op | ~10.7x |
    
    Native uses 29 allocs/op versus 30 for the generic baseline in both
    cases.
    
    ## Tests
    
    - `go test ./arrow/compute/internal/kernels ./arrow/compute -count=1`
    - `go test -tags noasm ./arrow/compute/internal/kernels ./arrow/compute
    -count=1`
    - `go test -race ./arrow/compute/internal/kernels ./arrow/compute
    -count=1`
    - `go vet ./arrow/compute/internal/kernels`
    - Linux ARM64 and AMD64 cross-builds for the touched packages
    - Differential ARM64 coverage for offsets 0-7 and lengths through 1024
---
 .../internal/kernels/scalar_comparison_arm64.go    |  131 +
 .../internal/kernels/scalar_comparison_arm64.s     | 2683 ++++++++++++++++++++
 .../kernels/scalar_comparison_arm64_test.go        |  210 ++
 .../internal/kernels/scalar_comparison_noasm.go    |    2 +-
 4 files changed, 3025 insertions(+), 1 deletion(-)

diff --git a/arrow/compute/internal/kernels/scalar_comparison_arm64.go 
b/arrow/compute/internal/kernels/scalar_comparison_arm64.go
new file mode 100644
index 00000000..f5d99611
--- /dev/null
+++ b/arrow/compute/internal/kernels/scalar_comparison_arm64.go
@@ -0,0 +1,131 @@
+// 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
+
+package kernels
+
+import (
+       "unsafe"
+
+       "github.com/apache/arrow-go/v18/arrow"
+       "golang.org/x/sys/cpu"
+)
+
+const (
+       neonCompareArrayArray = iota
+       neonCompareArrayScalar
+       neonCompareScalarArray
+)
+
+//go:noescape
+func _comparison_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,
+               arrow.FLOAT32, arrow.FLOAT64:
+               return true
+       default:
+               return false
+       }
+}
+
+func compareNeon(typ arrow.Type, op CompareOperator, width, shape int, left, 
right, out []byte, offset int, fallback binaryKernel) {
+       n := len(left) / width
+       if shape == neonCompareScalarArray {
+               n = len(right) / width
+       }
+       if n == 0 {
+               return
+       }
+
+       if offset != 0 {
+               prefix := min(n, 8-offset)
+               switch shape {
+               case neonCompareArrayArray:
+                       fallback(left[:prefix*width], right[:prefix*width], 
out, offset)
+               case neonCompareArrayScalar:
+                       fallback(left[:prefix*width], right, out, offset)
+               case neonCompareScalarArray:
+                       fallback(left, right[:prefix*width], out, offset)
+               }
+               if prefix == n {
+                       return
+               }
+
+               switch shape {
+               case neonCompareArrayArray:
+                       left = left[prefix*width:]
+                       right = right[prefix*width:]
+               case neonCompareArrayScalar:
+                       left = left[prefix*width:]
+               case neonCompareScalarArray:
+                       right = right[prefix*width:]
+               }
+               out = out[1:]
+               n -= prefix
+       }
+
+       bulk := n &^ 7
+       if bulk != 0 {
+               assemblyLeft, assemblyRight := left, right
+               switch shape {
+               case neonCompareArrayArray:
+                       assemblyLeft = left[:bulk*width]
+                       assemblyRight = right[:bulk*width]
+               case neonCompareArrayScalar:
+                       assemblyLeft = left[:bulk*width]
+               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 tail := n - bulk; tail != 0 {
+               out = out[bulk/8:]
+               switch shape {
+               case neonCompareArrayArray:
+                       fallback(left[bulk*width:bulk*width+tail*width], 
right[bulk*width:bulk*width+tail*width], out, 0)
+               case neonCompareArrayScalar:
+                       fallback(left[bulk*width:bulk*width+tail*width], right, 
out, 0)
+               case neonCompareScalarArray:
+                       fallback(left, right[bulk*width:bulk*width+tail*width], 
out, 0)
+               }
+       }
+}
+
+func genCompareKernel[T arrow.NumericType](op CompareOperator) *CompareData {
+       ty := arrow.GetType[T]()
+       fallback := genGoCompareKernel(getCmpOp[T](op))
+       if !cpu.ARM64.HasASIMD || !neonComparisonSupported(ty) {
+               return fallback
+       }
+
+       width := int(unsafe.Sizeof(T(0)))
+       return &CompareData{
+               funcAA: func(left, right, out []byte, offset int) {
+                       compareNeon(ty, op, width, neonCompareArrayArray, left, 
right, out, offset, fallback.funcAA)
+               },
+               funcAS: func(left, right, out []byte, offset int) {
+                       compareNeon(ty, op, width, neonCompareArrayScalar, 
left, right, out, offset, fallback.funcAS)
+               },
+               funcSA: func(left, right, out []byte, offset int) {
+                       compareNeon(ty, op, width, neonCompareScalarArray, 
left, right, out, offset, fallback.funcSA)
+               },
+       }
+}
diff --git a/arrow/compute/internal/kernels/scalar_comparison_arm64.s 
b/arrow/compute/internal/kernels/scalar_comparison_arm64.s
new file mode 100644
index 00000000..80ffc09c
--- /dev/null
+++ b/arrow/compute/internal/kernels/scalar_comparison_arm64.s
@@ -0,0 +1,2683 @@
+// 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"
+
+// 32-bit packing weights: [1, 2, 4, 8].
+DATA LCMPNEON_WEIGHTS<>+0(SB)/8, $0x0000000200000001
+DATA LCMPNEON_WEIGHTS<>+8(SB)/8, $0x0000000800000004
+// 64-bit variable shift counts: [0, 1].
+DATA LCMPNEON_WEIGHTS<>+16(SB)/8, $0x0000000000000000
+DATA LCMPNEON_WEIGHTS<>+24(SB)/8, $0x0000000000000001
+GLOBL LCMPNEON_WEIGHTS<>(SB), (NOPTR+RODATA), $32
+
+TEXT ยท_comparison_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 $6, R0
+       BEQ Lcomparison32Int
+       CMP $7, R0
+       BEQ Lcomparison32Int
+       CMP $8, R0
+       BEQ Lcomparison64Int
+       CMP $9, R0
+       BEQ Lcomparison64Int
+       CMP $11, R0
+       BEQ Lcomparison32Float
+       CMP $12, R0
+       BEQ Lcomparison64Float
+       JMP LcomparisonReturn
+
+Lcomparison32Int:
+       MOVD $LCMPNEON_WEIGHTS<>(SB), R10
+       VLD1 (R10), [V20.S4]
+       CMP $0, R2
+       BEQ Lcomparison32IntAASelect
+       CMP $1, R2
+       BEQ Lcomparison32IntASSelect
+       CMP $2, R2
+       BEQ Lcomparison32IntSASelect
+       JMP LcomparisonReturn
+
+Lcomparison32IntAASelect:
+       CMP $0, R1
+       BEQ Lcomparison32IntAAEQ
+       CMP $1, R1
+       BEQ Lcomparison32IntAANE
+       CMP $2, R1
+       BEQ Lcomparison32IntAAGTSelect
+       CMP $3, R1
+       BEQ Lcomparison32IntAAGESelect
+       JMP LcomparisonReturn
+
+Lcomparison32IntAAGTSelect:
+       CMP $6, R0
+       BEQ Lcomparison32IntAAUGT
+       JMP Lcomparison32IntAASGT
+
+Lcomparison32IntAAGESelect:
+       CMP $6, R0
+       BEQ Lcomparison32IntAAUGE
+       JMP Lcomparison32IntAASGE
+
+Lcomparison32IntASSelect:
+       CMP $0, R1
+       BEQ Lcomparison32IntASEQ
+       CMP $1, R1
+       BEQ Lcomparison32IntASNE
+       CMP $2, R1
+       BEQ Lcomparison32IntASGTSelect
+       CMP $3, R1
+       BEQ Lcomparison32IntASGESelect
+       JMP LcomparisonReturn
+
+Lcomparison32IntASGTSelect:
+       CMP $6, R0
+       BEQ Lcomparison32IntASUGT
+       JMP Lcomparison32IntASSGT
+
+Lcomparison32IntASGESelect:
+       CMP $6, R0
+       BEQ Lcomparison32IntASUGE
+       JMP Lcomparison32IntASSGE
+
+Lcomparison32IntSASelect:
+       CMP $0, R1
+       BEQ Lcomparison32IntSAEQ
+       CMP $1, R1
+       BEQ Lcomparison32IntSANE
+       CMP $2, R1
+       BEQ Lcomparison32IntSAGTSelect
+       CMP $3, R1
+       BEQ Lcomparison32IntSAGESelect
+       JMP LcomparisonReturn
+
+Lcomparison32IntSAGTSelect:
+       CMP $6, R0
+       BEQ Lcomparison32IntSAUGT
+       JMP Lcomparison32IntSASGT
+
+Lcomparison32IntSAGESelect:
+       CMP $6, R0
+       BEQ Lcomparison32IntSAUGE
+       JMP Lcomparison32IntSASGE
+
+Lcomparison32IntAAEQ:
+Lcomparison32IntAAEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea18c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea18c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntAAEQLoop
+
+Lcomparison32IntAANE:
+Lcomparison32IntAANELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntAANELoop
+
+Lcomparison32IntAASGT:
+Lcomparison32IntAASGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x4ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x4ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntAASGTLoop
+
+Lcomparison32IntAAUGT:
+Lcomparison32IntAAUGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntAAUGTLoop
+
+Lcomparison32IntAASGE:
+Lcomparison32IntAASGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x4ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x4ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntAASGELoop
+
+Lcomparison32IntAAUGE:
+Lcomparison32IntAAUGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntAAUGELoop
+
+Lcomparison32IntASEQ:
+       VLD1R (R4), [V1.S4]
+Lcomparison32IntASEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea18c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea18c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntASEQLoop
+
+Lcomparison32IntASNE:
+       VLD1R (R4), [V1.S4]
+Lcomparison32IntASNELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntASNELoop
+
+Lcomparison32IntASSGT:
+       VLD1R (R4), [V1.S4]
+Lcomparison32IntASSGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x4ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x4ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntASSGTLoop
+
+Lcomparison32IntASUGT:
+       VLD1R (R4), [V1.S4]
+Lcomparison32IntASUGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntASUGTLoop
+
+Lcomparison32IntASSGE:
+       VLD1R (R4), [V1.S4]
+Lcomparison32IntASSGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x4ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x4ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntASSGELoop
+
+Lcomparison32IntASUGE:
+       VLD1R (R4), [V1.S4]
+Lcomparison32IntASUGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntASUGELoop
+
+Lcomparison32IntSAEQ:
+       VLD1R (R3), [V0.S4]
+Lcomparison32IntSAEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea18c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea18c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntSAEQLoop
+
+Lcomparison32IntSANE:
+       VLD1R (R3), [V0.S4]
+Lcomparison32IntSANELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntSANELoop
+
+Lcomparison32IntSASGT:
+       VLD1R (R3), [V0.S4]
+Lcomparison32IntSASGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x4ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x4ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntSASGTLoop
+
+Lcomparison32IntSAUGT:
+       VLD1R (R3), [V0.S4]
+Lcomparison32IntSAUGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea13402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntSAUGTLoop
+
+Lcomparison32IntSASGE:
+       VLD1R (R3), [V0.S4]
+Lcomparison32IntSASGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x4ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x4ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntSASGELoop
+
+Lcomparison32IntSAUGE:
+       VLD1R (R3), [V0.S4]
+Lcomparison32IntSAUGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea13c02
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32IntSAUGELoop
+
+Lcomparison64Int:
+       MOVD $LCMPNEON_WEIGHTS<>(SB), R10
+       ADD $16, R10, R10
+       VLD1 (R10), [V20.D2]
+       CMP $0, R2
+       BEQ Lcomparison64IntAASelect
+       CMP $1, R2
+       BEQ Lcomparison64IntASSelect
+       CMP $2, R2
+       BEQ Lcomparison64IntSASelect
+       JMP LcomparisonReturn
+
+Lcomparison64IntAASelect:
+       CMP $0, R1
+       BEQ Lcomparison64IntAAEQ
+       CMP $1, R1
+       BEQ Lcomparison64IntAANE
+       CMP $2, R1
+       BEQ Lcomparison64IntAAGTSelect
+       CMP $3, R1
+       BEQ Lcomparison64IntAAGESelect
+       JMP LcomparisonReturn
+
+Lcomparison64IntAAGTSelect:
+       CMP $8, R0
+       BEQ Lcomparison64IntAAUGT
+       JMP Lcomparison64IntAASGT
+
+Lcomparison64IntAAGESelect:
+       CMP $8, R0
+       BEQ Lcomparison64IntAAUGE
+       JMP Lcomparison64IntAASGE
+
+Lcomparison64IntASSelect:
+       CMP $0, R1
+       BEQ Lcomparison64IntASEQ
+       CMP $1, R1
+       BEQ Lcomparison64IntASNE
+       CMP $2, R1
+       BEQ Lcomparison64IntASGTSelect
+       CMP $3, R1
+       BEQ Lcomparison64IntASGESelect
+       JMP LcomparisonReturn
+
+Lcomparison64IntASGTSelect:
+       CMP $8, R0
+       BEQ Lcomparison64IntASUGT
+       JMP Lcomparison64IntASSGT
+
+Lcomparison64IntASGESelect:
+       CMP $8, R0
+       BEQ Lcomparison64IntASUGE
+       JMP Lcomparison64IntASSGE
+
+Lcomparison64IntSASelect:
+       CMP $0, R1
+       BEQ Lcomparison64IntSAEQ
+       CMP $1, R1
+       BEQ Lcomparison64IntSANE
+       CMP $2, R1
+       BEQ Lcomparison64IntSAGTSelect
+       CMP $3, R1
+       BEQ Lcomparison64IntSAGESelect
+       JMP LcomparisonReturn
+
+Lcomparison64IntSAGTSelect:
+       CMP $8, R0
+       BEQ Lcomparison64IntSAUGT
+       JMP Lcomparison64IntSASGT
+
+Lcomparison64IntSAGESelect:
+       CMP $8, R0
+       BEQ Lcomparison64IntSAUGE
+       JMP Lcomparison64IntSASGE
+
+Lcomparison64IntAAEQ:
+Lcomparison64IntAAEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntAAEQLoop
+
+Lcomparison64IntAANE:
+Lcomparison64IntAANELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntAANELoop
+
+Lcomparison64IntAASGT:
+Lcomparison64IntAASGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntAASGTLoop
+
+Lcomparison64IntAAUGT:
+Lcomparison64IntAAUGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntAAUGTLoop
+
+Lcomparison64IntAASGE:
+Lcomparison64IntAASGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntAASGELoop
+
+Lcomparison64IntAAUGE:
+Lcomparison64IntAAUGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntAAUGELoop
+
+Lcomparison64IntASEQ:
+       VLD1R (R4), [V1.D2]
+Lcomparison64IntASEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntASEQLoop
+
+Lcomparison64IntASNE:
+       VLD1R (R4), [V1.D2]
+Lcomparison64IntASNELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntASNELoop
+
+Lcomparison64IntASSGT:
+       VLD1R (R4), [V1.D2]
+Lcomparison64IntASSGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntASSGTLoop
+
+Lcomparison64IntASUGT:
+       VLD1R (R4), [V1.D2]
+Lcomparison64IntASUGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntASUGTLoop
+
+Lcomparison64IntASSGE:
+       VLD1R (R4), [V1.D2]
+Lcomparison64IntASSGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntASSGELoop
+
+Lcomparison64IntASUGE:
+       VLD1R (R4), [V1.D2]
+Lcomparison64IntASUGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntASUGELoop
+
+Lcomparison64IntSAEQ:
+       VLD1R (R3), [V0.D2]
+Lcomparison64IntSAEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntSAEQLoop
+
+Lcomparison64IntSANE:
+       VLD1R (R3), [V0.D2]
+Lcomparison64IntSANELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee18c02
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntSANELoop
+
+Lcomparison64IntSASGT:
+       VLD1R (R3), [V0.D2]
+Lcomparison64IntSASGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntSASGTLoop
+
+Lcomparison64IntSAUGT:
+       VLD1R (R3), [V0.D2]
+Lcomparison64IntSAUGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntSAUGTLoop
+
+Lcomparison64IntSASGE:
+       VLD1R (R3), [V0.D2]
+Lcomparison64IntSASGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntSASGELoop
+
+Lcomparison64IntSAUGE:
+       VLD1R (R3), [V0.D2]
+Lcomparison64IntSAUGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee13c02
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64IntSAUGELoop
+
+Lcomparison32Float:
+       MOVD $LCMPNEON_WEIGHTS<>(SB), R10
+       VLD1 (R10), [V20.S4]
+       CMP $0, R2
+       BEQ Lcomparison32FloatAASelect
+       CMP $1, R2
+       BEQ Lcomparison32FloatASSelect
+       CMP $2, R2
+       BEQ Lcomparison32FloatSASelect
+       JMP LcomparisonReturn
+
+Lcomparison32FloatAASelect:
+       CMP $0, R1
+       BEQ Lcomparison32FloatAAEQ
+       CMP $1, R1
+       BEQ Lcomparison32FloatAANE
+       CMP $2, R1
+       BEQ Lcomparison32FloatAAGTSelect
+       CMP $3, R1
+       BEQ Lcomparison32FloatAAGESelect
+       JMP LcomparisonReturn
+
+Lcomparison32FloatAAGTSelect:
+       JMP Lcomparison32FloatAAFGT
+
+Lcomparison32FloatAAGESelect:
+       JMP Lcomparison32FloatAAFGE
+
+Lcomparison32FloatASSelect:
+       CMP $0, R1
+       BEQ Lcomparison32FloatASEQ
+       CMP $1, R1
+       BEQ Lcomparison32FloatASNE
+       CMP $2, R1
+       BEQ Lcomparison32FloatASGTSelect
+       CMP $3, R1
+       BEQ Lcomparison32FloatASGESelect
+       JMP LcomparisonReturn
+
+Lcomparison32FloatASGTSelect:
+       JMP Lcomparison32FloatASFGT
+
+Lcomparison32FloatASGESelect:
+       JMP Lcomparison32FloatASFGE
+
+Lcomparison32FloatSASelect:
+       CMP $0, R1
+       BEQ Lcomparison32FloatSAEQ
+       CMP $1, R1
+       BEQ Lcomparison32FloatSANE
+       CMP $2, R1
+       BEQ Lcomparison32FloatSAGTSelect
+       CMP $3, R1
+       BEQ Lcomparison32FloatSAGESelect
+       JMP LcomparisonReturn
+
+Lcomparison32FloatSAGTSelect:
+       JMP Lcomparison32FloatSAFGT
+
+Lcomparison32FloatSAGESelect:
+       JMP Lcomparison32FloatSAFGE
+
+Lcomparison32FloatAAEQ:
+Lcomparison32FloatAAEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x4e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x4e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatAAEQLoop
+
+Lcomparison32FloatAANE:
+Lcomparison32FloatAANELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x4e21e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x4e21e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatAANELoop
+
+Lcomparison32FloatAAFGT:
+Lcomparison32FloatAAFGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea1e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea1e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatAAFGTLoop
+
+Lcomparison32FloatAAFGE:
+Lcomparison32FloatAAFGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.S4]
+       VLD1 (R4), [V1.S4]
+       WORD $0x6e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatAAFGELoop
+
+Lcomparison32FloatASEQ:
+       VLD1R (R4), [V1.S4]
+Lcomparison32FloatASEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x4e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x4e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatASEQLoop
+
+Lcomparison32FloatASNE:
+       VLD1R (R4), [V1.S4]
+Lcomparison32FloatASNELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x4e21e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x4e21e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatASNELoop
+
+Lcomparison32FloatASFGT:
+       VLD1R (R4), [V1.S4]
+Lcomparison32FloatASFGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea1e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x6ea1e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatASFGTLoop
+
+Lcomparison32FloatASFGE:
+       VLD1R (R4), [V1.S4]
+Lcomparison32FloatASFGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.S4]
+       WORD $0x6e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.S4]
+       WORD $0x6e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatASFGELoop
+
+Lcomparison32FloatSAEQ:
+       VLD1R (R3), [V0.S4]
+Lcomparison32FloatSAEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x4e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x4e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatSAEQLoop
+
+Lcomparison32FloatSANE:
+       VLD1R (R3), [V0.S4]
+Lcomparison32FloatSANELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x4e21e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x4e21e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatSANELoop
+
+Lcomparison32FloatSAFGT:
+       VLD1R (R3), [V0.S4]
+Lcomparison32FloatSAFGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea1e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x6ea1e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatSAFGTLoop
+
+Lcomparison32FloatSAFGE:
+       VLD1R (R3), [V0.S4]
+Lcomparison32FloatSAFGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.S4]
+       WORD $0x6e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c47 // umov result
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.S4]
+       WORD $0x6e21e402
+       VUSHR $31, V2.S4, V2.S4
+       WORD $0x4eb49c42 // mul v2.4s, v2.4s, v20.4s
+       VADDV V2.S4, V2
+       WORD $0x0e043c48 // umov result
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison32FloatSAFGELoop
+
+Lcomparison64Float:
+       MOVD $LCMPNEON_WEIGHTS<>(SB), R10
+       ADD $16, R10, R10
+       VLD1 (R10), [V20.D2]
+       CMP $0, R2
+       BEQ Lcomparison64FloatAASelect
+       CMP $1, R2
+       BEQ Lcomparison64FloatASSelect
+       CMP $2, R2
+       BEQ Lcomparison64FloatSASelect
+       JMP LcomparisonReturn
+
+Lcomparison64FloatAASelect:
+       CMP $0, R1
+       BEQ Lcomparison64FloatAAEQ
+       CMP $1, R1
+       BEQ Lcomparison64FloatAANE
+       CMP $2, R1
+       BEQ Lcomparison64FloatAAGTSelect
+       CMP $3, R1
+       BEQ Lcomparison64FloatAAGESelect
+       JMP LcomparisonReturn
+
+Lcomparison64FloatAAGTSelect:
+       JMP Lcomparison64FloatAAFGT
+
+Lcomparison64FloatAAGESelect:
+       JMP Lcomparison64FloatAAFGE
+
+Lcomparison64FloatASSelect:
+       CMP $0, R1
+       BEQ Lcomparison64FloatASEQ
+       CMP $1, R1
+       BEQ Lcomparison64FloatASNE
+       CMP $2, R1
+       BEQ Lcomparison64FloatASGTSelect
+       CMP $3, R1
+       BEQ Lcomparison64FloatASGESelect
+       JMP LcomparisonReturn
+
+Lcomparison64FloatASGTSelect:
+       JMP Lcomparison64FloatASFGT
+
+Lcomparison64FloatASGESelect:
+       JMP Lcomparison64FloatASFGE
+
+Lcomparison64FloatSASelect:
+       CMP $0, R1
+       BEQ Lcomparison64FloatSAEQ
+       CMP $1, R1
+       BEQ Lcomparison64FloatSANE
+       CMP $2, R1
+       BEQ Lcomparison64FloatSAGTSelect
+       CMP $3, R1
+       BEQ Lcomparison64FloatSAGESelect
+       JMP LcomparisonReturn
+
+Lcomparison64FloatSAGTSelect:
+       JMP Lcomparison64FloatSAFGT
+
+Lcomparison64FloatSAGESelect:
+       JMP Lcomparison64FloatSAFGE
+
+Lcomparison64FloatAAEQ:
+Lcomparison64FloatAAEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatAAEQLoop
+
+Lcomparison64FloatAANE:
+Lcomparison64FloatAANELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatAANELoop
+
+Lcomparison64FloatAAFGT:
+Lcomparison64FloatAAFGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatAAFGTLoop
+
+Lcomparison64FloatAAFGE:
+Lcomparison64FloatAAFGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       VLD1 (R3), [V0.D2]
+       VLD1 (R4), [V1.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatAAFGELoop
+
+Lcomparison64FloatASEQ:
+       VLD1R (R4), [V1.D2]
+Lcomparison64FloatASEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatASEQLoop
+
+Lcomparison64FloatASNE:
+       VLD1R (R4), [V1.D2]
+Lcomparison64FloatASNELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatASNELoop
+
+Lcomparison64FloatASFGT:
+       VLD1R (R4), [V1.D2]
+Lcomparison64FloatASFGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatASFGTLoop
+
+Lcomparison64FloatASFGE:
+       VLD1R (R4), [V1.D2]
+Lcomparison64FloatASFGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R3), [V0.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R3, R3
+       VLD1 (R3), [V0.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R3, R3
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatASFGELoop
+
+Lcomparison64FloatSAEQ:
+       VLD1R (R3), [V0.D2]
+Lcomparison64FloatSAEQLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatSAEQLoop
+
+Lcomparison64FloatSANE:
+       VLD1R (R3), [V0.D2]
+Lcomparison64FloatSANELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x4e61e402
+       WORD $0x6e205842 // mvn v2.16b, v2.16b
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatSANELoop
+
+Lcomparison64FloatSAFGT:
+       VLD1R (R3), [V0.D2]
+Lcomparison64FloatSAFGTLoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6ee1e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatSAFGTLoop
+
+Lcomparison64FloatSAFGE:
+       VLD1R (R3), [V0.D2]
+Lcomparison64FloatSAFGELoop:
+       CMP $0, R6
+       BEQ LcomparisonReturn
+       VLD1 (R4), [V1.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c47 // umov x7, v2.d[0]
+       WORD $0x4e183c48 // umov x8, v2.d[1]
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $2, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $4, R8, R8
+       ORR R8, R7, R7
+       ADD $16, R4, R4
+       VLD1 (R4), [V1.D2]
+       WORD $0x6e61e402
+       VUSHR $63, V2.D2, V2.D2
+       WORD $0x6ef44442 // ushl v2.2d, v2.2d, v20.2d
+       WORD $0x4e083c48 // umov x8, v2.d[0]
+       WORD $0x4e183c49 // umov x9, v2.d[1]
+       ORR R9, R8, R8
+       LSL $6, R8, R8
+       ORR R8, R7, R7
+       MOVB R7, (R5)
+       ADD $16, R4, R4
+       ADD $1, R5, R5
+       SUB $1, R6, R6
+       JMP Lcomparison64FloatSAFGELoop
+
+LcomparisonReturn:
+       RET
diff --git a/arrow/compute/internal/kernels/scalar_comparison_arm64_test.go 
b/arrow/compute/internal/kernels/scalar_comparison_arm64_test.go
new file mode 100644
index 00000000..460d8aca
--- /dev/null
+++ b/arrow/compute/internal/kernels/scalar_comparison_arm64_test.go
@@ -0,0 +1,210 @@
+// 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
+
+package kernels
+
+import (
+       "bytes"
+       "fmt"
+       "math"
+       "testing"
+       "unsafe"
+
+       "github.com/apache/arrow-go/v18/arrow"
+       "github.com/apache/arrow-go/v18/arrow/bitutil"
+)
+
+const neonComparisonTestLength = 1024
+
+func testNeonComparison[T arrow.NumericType](t *testing.T, left, right []T, 
leftScalar, rightScalar T) {
+       t.Helper()
+
+       operations := []struct {
+               name string
+               op   CompareOperator
+       }{
+               {"equal", CmpEQ},
+               {"not_equal", CmpNE},
+               {"greater", CmpGT},
+               {"greater_equal", CmpGE},
+       }
+
+       leftBytes := arrow.GetBytes(left)
+       rightBytes := arrow.GetBytes(right)
+       leftScalarBytes := arrow.GetBytes([]T{leftScalar})
+       rightScalarBytes := arrow.GetBytes([]T{rightScalar})
+       width := int(unsafe.Sizeof(T(0)))
+       lengths := []int{0, 1, 2, 7, 8, 9, 15, 16, 17, 23, 24, 25, 31, 32, 33, 
63, 64, 65, 127, 128, 129, neonComparisonTestLength}
+
+       for _, operation := range operations {
+               t.Run(operation.name, func(t *testing.T) {
+                       cmp := genCompareKernel[T](operation.op)
+                       fallback := 
genGoCompareKernel(getCmpOp[T](operation.op))
+                       for _, shape := range []string{"array_array", 
"array_scalar", "scalar_array"} {
+                               t.Run(shape, func(t *testing.T) {
+                                       for offset := 0; offset < 8; offset++ {
+                                               for _, length := range lengths {
+                                                       
t.Run(fmt.Sprintf("offset_%d/length_%d", offset, length), func(t *testing.T) {
+                                                               out := 
bytes.Repeat([]byte{0xa5}, int(bitutil.BytesForBits(int64(offset+length))))
+                                                               expected := 
append([]byte(nil), out...)
+
+                                                               switch shape {
+                                                               case 
"array_array":
+                                                                       
fallback.funcAA(leftBytes[:length*width], rightBytes[:length*width], expected, 
offset)
+                                                               case 
"array_scalar":
+                                                                       
fallback.funcAS(leftBytes[:length*width], rightScalarBytes, expected, offset)
+                                                               case 
"scalar_array":
+                                                                       
fallback.funcSA(leftScalarBytes, rightBytes[:length*width], expected, offset)
+                                                               }
+
+                                                               switch shape {
+                                                               case 
"array_array":
+                                                                       
cmp.funcAA(leftBytes[:length*width], rightBytes[:length*width], out, offset)
+                                                               case 
"array_scalar":
+                                                                       
cmp.funcAS(leftBytes[:length*width], rightScalarBytes, out, offset)
+                                                               case 
"scalar_array":
+                                                                       
cmp.funcSA(leftScalarBytes, rightBytes[:length*width], out, offset)
+                                                               }
+
+                                                               if 
!bytes.Equal(expected, out) {
+                                                                       
t.Fatalf("expected %08b, got %08b", expected, out)
+                                                               }
+                                                       })
+                                               }
+                                       }
+                               })
+                       }
+               })
+       }
+}
+
+func TestNeonComparisons(t *testing.T) {
+       t.Run("int32", func(t *testing.T) {
+               leftPattern := []int32{-1 << 31, -17, -1, 0, 1, 17, 1<<31 - 1, 
42, -42, 3, 9, -9, 5, -5, 2, -2}
+               rightPattern := []int32{1<<31 - 1, -17, 0, 1, -1, -42, -1 << 
31, 42, 4, -3, 9, -10, -5, 5, -2, 2}
+               left := make([]int32, neonComparisonTestLength)
+               right := make([]int32, neonComparisonTestLength)
+               for i := range left {
+                       left[i] = leftPattern[i%len(leftPattern)]
+                       right[i] = rightPattern[i%len(rightPattern)]
+               }
+               testNeonComparison(t, left, right, int32(-3), int32(4))
+       })
+
+       t.Run("uint32", func(t *testing.T) {
+               leftPattern := []uint32{0, 1, 2, 1<<31 - 1, 1 << 31, 
^uint32(0), 42, 7, 100, 3, 19, 5, 77, 11, 12, 13}
+               rightPattern := []uint32{^uint32(0), 1, 3, 1 << 31, 1<<31 - 1, 
0, 42, 8, 99, 4, 19, 6, 78, 10, 13, 12}
+               left := make([]uint32, neonComparisonTestLength)
+               right := make([]uint32, neonComparisonTestLength)
+               for i := range left {
+                       left[i] = leftPattern[i%len(leftPattern)]
+                       right[i] = rightPattern[i%len(rightPattern)]
+               }
+               testNeonComparison(t, left, right, uint32(1<<31), uint32(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}
+               left := make([]int64, neonComparisonTestLength)
+               right := make([]int64, neonComparisonTestLength)
+               for i := range left {
+                       left[i] = leftPattern[i%len(leftPattern)]
+                       right[i] = rightPattern[i%len(rightPattern)]
+               }
+               testNeonComparison(t, left, right, int64(-3), int64(4))
+       })
+
+       t.Run("uint64", func(t *testing.T) {
+               leftPattern := []uint64{0, 1, 2, 1<<63 - 1, 1 << 63, 
^uint64(0), 42, 7, 100, 3, 19, 5, 77, 11, 12, 13}
+               rightPattern := []uint64{^uint64(0), 1, 3, 1 << 63, 1<<63 - 1, 
0, 42, 8, 99, 4, 19, 6, 78, 10, 13, 12}
+               left := make([]uint64, neonComparisonTestLength)
+               right := make([]uint64, neonComparisonTestLength)
+               for i := range left {
+                       left[i] = leftPattern[i%len(leftPattern)]
+                       right[i] = rightPattern[i%len(rightPattern)]
+               }
+               testNeonComparison(t, left, right, uint64(1<<63), uint64(7))
+       })
+
+       t.Run("float32", func(t *testing.T) {
+               leftPattern := []float32{float32(math.NaN()), 
float32(math.Inf(-1)), -1.5, float32(math.Copysign(0, -1)), 0, 1.5, 
float32(math.Inf(1)), float32(math.NaN())}
+               rightPattern := []float32{float32(math.NaN()), 
-float32(math.Inf(1)), -1.5, 0, float32(math.Copysign(0, -1)), 2.5, 
float32(math.Inf(1)), 3}
+               left := make([]float32, neonComparisonTestLength)
+               right := make([]float32, neonComparisonTestLength)
+               for i := range left {
+                       left[i] = leftPattern[i%len(leftPattern)]
+                       right[i] = rightPattern[i%len(rightPattern)]
+               }
+               testNeonComparison(t, left, right, float32(math.NaN()), 
float32(1.5))
+       })
+
+       t.Run("float64", func(t *testing.T) {
+               leftPattern := []float64{math.NaN(), math.Inf(-1), -1.5, 
math.Copysign(0, -1), 0, 1.5, math.Inf(1), math.NaN()}
+               rightPattern := []float64{math.NaN(), -math.Inf(1), -1.5, 0, 
math.Copysign(0, -1), 2.5, math.Inf(1), 3}
+               left := make([]float64, neonComparisonTestLength)
+               right := make([]float64, neonComparisonTestLength)
+               for i := range left {
+                       left[i] = leftPattern[i%len(leftPattern)]
+                       right[i] = rightPattern[i%len(rightPattern)]
+               }
+               testNeonComparison(t, left, right, math.NaN(), 1.5)
+       })
+}
+
+func TestNeonComparisonBitPacking(t *testing.T) {
+       t.Run("int32", testNeonComparisonBitPacking[int32])
+       t.Run("uint32", testNeonComparisonBitPacking[uint32])
+       t.Run("int64", testNeonComparisonBitPacking[int64])
+       t.Run("uint64", testNeonComparisonBitPacking[uint64])
+       t.Run("float32", testNeonComparisonBitPacking[float32])
+       t.Run("float64", testNeonComparisonBitPacking[float64])
+}
+
+func testNeonComparisonBitPacking[T arrow.NumericType](t *testing.T) {
+       const n = 256 * 8
+       left, right := make([]T, n), make([]T, n)
+       for mask := 0; mask < 256; mask++ {
+               for bit := 0; bit < 8; bit++ {
+                       left[mask*8+bit] = T(mask >> bit & 1)
+                       right[mask*8+bit] = T(mask >> (7 - bit) & 1)
+               }
+       }
+       leftBytes, rightBytes := arrow.GetBytes(left), arrow.GetBytes(right)
+       scalar := arrow.GetBytes([]T{0})
+       for _, op := range []CompareOperator{CmpEQ, CmpNE, CmpGT, CmpGE} {
+               got, want := genCompareKernel[T](op), 
genGoCompareKernel(getCmpOp[T](op))
+               for _, shape := range []struct {
+                       name        string
+                       got, want   binaryKernel
+                       left, right []byte
+               }{
+                       {"array_array", got.funcAA, want.funcAA, leftBytes, 
rightBytes},
+                       {"array_scalar", got.funcAS, want.funcAS, leftBytes, 
scalar},
+                       {"scalar_array", got.funcSA, want.funcSA, scalar, 
rightBytes},
+               } {
+                       output := bytes.Repeat([]byte{0xa5}, n/8+2)
+                       expected := bytes.Clone(output)
+                       shape.want(shape.left, shape.right, 
expected[1:len(expected)-1], 0)
+                       shape.got(shape.left, shape.right, 
output[1:len(output)-1], 0)
+                       if !bytes.Equal(output, expected) {
+                               t.Fatalf("%s %s: expected %08b, got %08b", op, 
shape.name, expected, output)
+                       }
+               }
+       }
+}
diff --git a/arrow/compute/internal/kernels/scalar_comparison_noasm.go 
b/arrow/compute/internal/kernels/scalar_comparison_noasm.go
index 61966769..c94ec537 100644
--- a/arrow/compute/internal/kernels/scalar_comparison_noasm.go
+++ b/arrow/compute/internal/kernels/scalar_comparison_noasm.go
@@ -14,7 +14,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-//go:build go1.18 && (noasm || !amd64)
+//go:build go1.18 && (noasm || (!amd64 && !arm64) || (appengine && arm64))
 
 package kernels
 

Reply via email to