simd/archsimd: add SVE NotEqual

Lower to ZCMPNE for both integer signednesses and ZFCMNE for floats,
predicated-only like ZCMPGT. NEON has no native not-equal compare; SVE
does, so the API is provided directly.

For #79781.

Change-Id: Id58641731b0ea682b699015c3a2eda0d8563b568
Reviewed-on: https://go-review.googlesource.com/c/go/+/822935
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Auto-Submit: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
diff --git a/src/cmd/compile/internal/arm64/simdssa_sve.go b/src/cmd/compile/internal/arm64/simdssa_sve.go
index cee0edf..507c272 100644
--- a/src/cmd/compile/internal/arm64/simdssa_sve.go
+++ b/src/cmd/compile/internal/arm64/simdssa_sve.go
@@ -81,26 +81,32 @@
 
 	case ssaop.OpARM64ZCMPEQB,
 		ssaop.OpARM64ZCMPGTB,
-		ssaop.OpARM64ZCMPHIB:
+		ssaop.OpARM64ZCMPHIB,
+		ssaop.OpARM64ZCMPNEB:
 		p = simdZ2kk(s, v, arm64.ARNG_B)
 
 	case ssaop.OpARM64ZFCMEQD,
 		ssaop.OpARM64ZCMPEQD,
 		ssaop.OpARM64ZFCMGTD,
 		ssaop.OpARM64ZCMPGTD,
-		ssaop.OpARM64ZCMPHID:
+		ssaop.OpARM64ZCMPHID,
+		ssaop.OpARM64ZFCMNED,
+		ssaop.OpARM64ZCMPNED:
 		p = simdZ2kk(s, v, arm64.ARNG_D)
 
 	case ssaop.OpARM64ZCMPEQH,
 		ssaop.OpARM64ZCMPGTH,
-		ssaop.OpARM64ZCMPHIH:
+		ssaop.OpARM64ZCMPHIH,
+		ssaop.OpARM64ZCMPNEH:
 		p = simdZ2kk(s, v, arm64.ARNG_H)
 
 	case ssaop.OpARM64ZFCMEQS,
 		ssaop.OpARM64ZCMPEQS,
 		ssaop.OpARM64ZFCMGTS,
 		ssaop.OpARM64ZCMPGTS,
-		ssaop.OpARM64ZCMPHIS:
+		ssaop.OpARM64ZCMPHIS,
+		ssaop.OpARM64ZFCMNES,
+		ssaop.OpARM64ZCMPNES:
 		p = simdZ2kk(s, v, arm64.ARNG_S)
 
 	case ssaop.OpARM64ZADDMergingB,
diff --git a/src/cmd/compile/internal/ssa/_gen/simdARM64SVE.rules b/src/cmd/compile/internal/ssa/_gen/simdARM64SVE.rules
index 2675254..54d81ae 100644
--- a/src/cmd/compile/internal/ssa/_gen/simdARM64SVE.rules
+++ b/src/cmd/compile/internal/ssa/_gen/simdARM64SVE.rules
@@ -72,6 +72,16 @@
 (NegInt32s x) => (ZNEGS x (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
 (NegInt64s x) => (ZNEGD x (Select0 <types.TypeMask> (PWHILELTD (MOVDconst [0]) (MOVDconst [4]))))
 (NegInt8s x) => (ZNEGB x (Select0 <types.TypeMask> (PWHILELTB (MOVDconst [0]) (MOVDconst [32]))))
+(NotEqualFloat32s x y) => (ZFCMNES x y (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
+(NotEqualFloat64s x y) => (ZFCMNED x y (Select0 <types.TypeMask> (PWHILELTD (MOVDconst [0]) (MOVDconst [4]))))
+(NotEqualInt16s x y) => (ZCMPNEH x y (Select0 <types.TypeMask> (PWHILELTH (MOVDconst [0]) (MOVDconst [16]))))
+(NotEqualInt32s x y) => (ZCMPNES x y (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
+(NotEqualInt64s x y) => (ZCMPNED x y (Select0 <types.TypeMask> (PWHILELTD (MOVDconst [0]) (MOVDconst [4]))))
+(NotEqualInt8s x y) => (ZCMPNEB x y (Select0 <types.TypeMask> (PWHILELTB (MOVDconst [0]) (MOVDconst [32]))))
+(NotEqualUint16s x y) => (ZCMPNEH x y (Select0 <types.TypeMask> (PWHILELTH (MOVDconst [0]) (MOVDconst [16]))))
+(NotEqualUint32s x y) => (ZCMPNES x y (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
+(NotEqualUint64s x y) => (ZCMPNED x y (Select0 <types.TypeMask> (PWHILELTD (MOVDconst [0]) (MOVDconst [4]))))
+(NotEqualUint8s x y) => (ZCMPNEB x y (Select0 <types.TypeMask> (PWHILELTB (MOVDconst [0]) (MOVDconst [32]))))
 (RoundFloat32s x) => (ZFRINTNS x (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
 (RoundFloat64s x) => (ZFRINTND x (Select0 <types.TypeMask> (PWHILELTD (MOVDconst [0]) (MOVDconst [4]))))
 (SqrtFloat32s x) => (ZFSQRTS x (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
diff --git a/src/cmd/compile/internal/ssa/_gen/simdARM64SVEops.go b/src/cmd/compile/internal/ssa/_gen/simdARM64SVEops.go
index 9bf61ab..d7df758 100644
--- a/src/cmd/compile/internal/ssa/_gen/simdARM64SVEops.go
+++ b/src/cmd/compile/internal/ssa/_gen/simdARM64SVEops.go
@@ -36,6 +36,10 @@
 		{name: "ZCMPHID", argLength: 3, reg: z2kk, asm: "ZCMPHI", typ: "Mask"},
 		{name: "ZCMPHIH", argLength: 3, reg: z2kk, asm: "ZCMPHI", typ: "Mask"},
 		{name: "ZCMPHIS", argLength: 3, reg: z2kk, asm: "ZCMPHI", typ: "Mask"},
+		{name: "ZCMPNEB", argLength: 3, reg: z2kk, asm: "ZCMPNE", commutative: true, typ: "Mask"},
+		{name: "ZCMPNED", argLength: 3, reg: z2kk, asm: "ZCMPNE", commutative: true, typ: "Mask"},
+		{name: "ZCMPNEH", argLength: 3, reg: z2kk, asm: "ZCMPNE", commutative: true, typ: "Mask"},
+		{name: "ZCMPNES", argLength: 3, reg: z2kk, asm: "ZCMPNE", commutative: true, typ: "Mask"},
 		{name: "ZFABSD", argLength: 2, reg: zkv, asm: "ZFABS", typ: "Vec256"},
 		{name: "ZFABSMergingD", argLength: 3, reg: z2kvPred, asm: "ZFABS", typ: "Vec256", resultInArg0: true},
 		{name: "ZFABSMergingS", argLength: 3, reg: z2kvPred, asm: "ZFABS", typ: "Vec256", resultInArg0: true},
@@ -50,6 +54,8 @@
 		{name: "ZFCMEQS", argLength: 3, reg: z2kk, asm: "ZFCMEQ", commutative: true, typ: "Mask"},
 		{name: "ZFCMGTD", argLength: 3, reg: z2kk, asm: "ZFCMGT", typ: "Mask"},
 		{name: "ZFCMGTS", argLength: 3, reg: z2kk, asm: "ZFCMGT", typ: "Mask"},
+		{name: "ZFCMNED", argLength: 3, reg: z2kk, asm: "ZFCMNE", commutative: true, typ: "Mask"},
+		{name: "ZFCMNES", argLength: 3, reg: z2kk, asm: "ZFCMNE", commutative: true, typ: "Mask"},
 		{name: "ZFNEGD", argLength: 2, reg: zkv, asm: "ZFNEG", typ: "Vec256"},
 		{name: "ZFNEGMergingD", argLength: 3, reg: z2kvPred, asm: "ZFNEG", typ: "Vec256", resultInArg0: true},
 		{name: "ZFNEGMergingS", argLength: 3, reg: z2kvPred, asm: "ZFNEG", typ: "Vec256", resultInArg0: true},
diff --git a/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go b/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go
index 65fe793..949085f 100644
--- a/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go
+++ b/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go
@@ -858,26 +858,36 @@
 		{name: "NegInt32x4", argLength: 1},                                              // ARCH:arm64,wasm
 		{name: "NegInt64s", argLength: 1},                                               // ARCH:sve
 		{name: "NegInt64x2", argLength: 1},                                              // ARCH:arm64,wasm
+		{name: "NotEqualFloat32s", argLength: 2, commutative: true},                     // ARCH:sve
 		{name: "NotEqualFloat32x4", argLength: 2, commutative: true},                    // ARCH:amd64,wasm
 		{name: "NotEqualFloat32x8", argLength: 2, commutative: true},                    // ARCH:amd64
 		{name: "NotEqualFloat32x16", argLength: 2, commutative: true},                   // ARCH:amd64
+		{name: "NotEqualFloat64s", argLength: 2, commutative: true},                     // ARCH:sve
 		{name: "NotEqualFloat64x2", argLength: 2, commutative: true},                    // ARCH:amd64,wasm
 		{name: "NotEqualFloat64x4", argLength: 2, commutative: true},                    // ARCH:amd64
 		{name: "NotEqualFloat64x8", argLength: 2, commutative: true},                    // ARCH:amd64
+		{name: "NotEqualInt8s", argLength: 2, commutative: true},                        // ARCH:sve
 		{name: "NotEqualInt8x16", argLength: 2, commutative: true},                      // ARCH:wasm
 		{name: "NotEqualInt8x64", argLength: 2, commutative: true},                      // ARCH:amd64
+		{name: "NotEqualInt16s", argLength: 2, commutative: true},                       // ARCH:sve
 		{name: "NotEqualInt16x8", argLength: 2, commutative: true},                      // ARCH:wasm
 		{name: "NotEqualInt16x32", argLength: 2, commutative: true},                     // ARCH:amd64
+		{name: "NotEqualInt32s", argLength: 2, commutative: true},                       // ARCH:sve
 		{name: "NotEqualInt32x4", argLength: 2, commutative: true},                      // ARCH:wasm
 		{name: "NotEqualInt32x16", argLength: 2, commutative: true},                     // ARCH:amd64
+		{name: "NotEqualInt64s", argLength: 2, commutative: true},                       // ARCH:sve
 		{name: "NotEqualInt64x2", argLength: 2, commutative: true},                      // ARCH:wasm
 		{name: "NotEqualInt64x8", argLength: 2, commutative: true},                      // ARCH:amd64
+		{name: "NotEqualUint8s", argLength: 2, commutative: true},                       // ARCH:sve
 		{name: "NotEqualUint8x16", argLength: 2, commutative: true},                     // ARCH:wasm
 		{name: "NotEqualUint8x64", argLength: 2, commutative: true},                     // ARCH:amd64
+		{name: "NotEqualUint16s", argLength: 2, commutative: true},                      // ARCH:sve
 		{name: "NotEqualUint16x8", argLength: 2, commutative: true},                     // ARCH:wasm
 		{name: "NotEqualUint16x32", argLength: 2, commutative: true},                    // ARCH:amd64
+		{name: "NotEqualUint32s", argLength: 2, commutative: true},                      // ARCH:sve
 		{name: "NotEqualUint32x4", argLength: 2, commutative: true},                     // ARCH:wasm
 		{name: "NotEqualUint32x16", argLength: 2, commutative: true},                    // ARCH:amd64
+		{name: "NotEqualUint64s", argLength: 2, commutative: true},                      // ARCH:sve
 		{name: "NotEqualUint64x2", argLength: 2, commutative: true},                     // ARCH:wasm
 		{name: "NotEqualUint64x8", argLength: 2, commutative: true},                     // ARCH:amd64
 		{name: "NotInt8x16", argLength: 1},                                              // ARCH:arm64,wasm
diff --git a/src/cmd/compile/internal/ssa/ssaop/opGen.go b/src/cmd/compile/internal/ssa/ssaop/opGen.go
index 27e0299..ac9146c 100644
--- a/src/cmd/compile/internal/ssa/ssaop/opGen.go
+++ b/src/cmd/compile/internal/ssa/ssaop/opGen.go
@@ -5072,6 +5072,10 @@
 	OpARM64ZCMPHID
 	OpARM64ZCMPHIH
 	OpARM64ZCMPHIS
+	OpARM64ZCMPNEB
+	OpARM64ZCMPNED
+	OpARM64ZCMPNEH
+	OpARM64ZCMPNES
 	OpARM64ZFABSD
 	OpARM64ZFABSMergingD
 	OpARM64ZFABSMergingS
@@ -5086,6 +5090,8 @@
 	OpARM64ZFCMEQS
 	OpARM64ZFCMGTD
 	OpARM64ZFCMGTS
+	OpARM64ZFCMNED
+	OpARM64ZFCMNES
 	OpARM64ZFNEGD
 	OpARM64ZFNEGMergingD
 	OpARM64ZFNEGMergingS
@@ -7988,26 +7994,36 @@
 	OpNegInt64x2
 	OpNegInt8s
 	OpNegInt8x16
+	OpNotEqualFloat32s
 	OpNotEqualFloat32x16
 	OpNotEqualFloat32x4
 	OpNotEqualFloat32x8
+	OpNotEqualFloat64s
 	OpNotEqualFloat64x2
 	OpNotEqualFloat64x4
 	OpNotEqualFloat64x8
+	OpNotEqualInt16s
 	OpNotEqualInt16x32
 	OpNotEqualInt16x8
+	OpNotEqualInt32s
 	OpNotEqualInt32x16
 	OpNotEqualInt32x4
+	OpNotEqualInt64s
 	OpNotEqualInt64x2
 	OpNotEqualInt64x8
+	OpNotEqualInt8s
 	OpNotEqualInt8x16
 	OpNotEqualInt8x64
+	OpNotEqualUint16s
 	OpNotEqualUint16x32
 	OpNotEqualUint16x8
+	OpNotEqualUint32s
 	OpNotEqualUint32x16
 	OpNotEqualUint32x4
+	OpNotEqualUint64s
 	OpNotEqualUint64x2
 	OpNotEqualUint64x8
+	OpNotEqualUint8s
 	OpNotEqualUint8x16
 	OpNotEqualUint8x64
 	OpNotInt16x8
@@ -86307,6 +86323,70 @@
 		},
 	},
 	{
+		Name:        "ZCMPNEB",
+		ArgLen:      3,
+		Commutative: true,
+		asm:         arm64.AZCMPNE,
+		Reg: RegInfo{
+			Inputs: []InputInfo{
+				{2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+				{0, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+				{1, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+			},
+			Outputs: []OutputInfo{
+				{0, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+			},
+		},
+	},
+	{
+		Name:        "ZCMPNED",
+		ArgLen:      3,
+		Commutative: true,
+		asm:         arm64.AZCMPNE,
+		Reg: RegInfo{
+			Inputs: []InputInfo{
+				{2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+				{0, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+				{1, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+			},
+			Outputs: []OutputInfo{
+				{0, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+			},
+		},
+	},
+	{
+		Name:        "ZCMPNEH",
+		ArgLen:      3,
+		Commutative: true,
+		asm:         arm64.AZCMPNE,
+		Reg: RegInfo{
+			Inputs: []InputInfo{
+				{2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+				{0, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+				{1, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+			},
+			Outputs: []OutputInfo{
+				{0, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+			},
+		},
+	},
+	{
+		Name:        "ZCMPNES",
+		ArgLen:      3,
+		Commutative: true,
+		asm:         arm64.AZCMPNE,
+		Reg: RegInfo{
+			Inputs: []InputInfo{
+				{2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+				{0, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+				{1, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+			},
+			Outputs: []OutputInfo{
+				{0, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+			},
+		},
+	},
+	{
 		Name:   "ZFABSD",
 		ArgLen: 2,
 		asm:    arm64.AZFABS,
@@ -86525,6 +86605,38 @@
 		},
 	},
 	{
+		Name:        "ZFCMNED",
+		ArgLen:      3,
+		Commutative: true,
+		asm:         arm64.AZFCMNE,
+		Reg: RegInfo{
+			Inputs: []InputInfo{
+				{2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+				{0, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+				{1, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+			},
+			Outputs: []OutputInfo{
+				{0, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+			},
+		},
+	},
+	{
+		Name:        "ZFCMNES",
+		ArgLen:      3,
+		Commutative: true,
+		asm:         arm64.AZFCMNE,
+		Reg: RegInfo{
+			Inputs: []InputInfo{
+				{2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+				{0, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+				{1, RegMask{V1: 9223372034707292160, V2: 0}},     // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+			},
+			Outputs: []OutputInfo{
+				{0, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15
+			},
+		},
+	},
+	{
 		Name:   "ZFNEGD",
 		ArgLen: 2,
 		asm:    arm64.AZFNEG,
@@ -116000,6 +116112,12 @@
 		Generic: true,
 	},
 	{
+		Name:        "NotEqualFloat32s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualFloat32x16",
 		ArgLen:      2,
 		Commutative: true,
@@ -116018,6 +116136,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualFloat64s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualFloat64x2",
 		ArgLen:      2,
 		Commutative: true,
@@ -116036,6 +116160,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualInt16s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualInt16x32",
 		ArgLen:      2,
 		Commutative: true,
@@ -116048,6 +116178,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualInt32s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualInt32x16",
 		ArgLen:      2,
 		Commutative: true,
@@ -116060,6 +116196,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualInt64s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualInt64x2",
 		ArgLen:      2,
 		Commutative: true,
@@ -116072,6 +116214,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualInt8s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualInt8x16",
 		ArgLen:      2,
 		Commutative: true,
@@ -116084,6 +116232,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualUint16s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualUint16x32",
 		ArgLen:      2,
 		Commutative: true,
@@ -116096,6 +116250,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualUint32s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualUint32x16",
 		ArgLen:      2,
 		Commutative: true,
@@ -116108,6 +116268,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualUint64s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualUint64x2",
 		ArgLen:      2,
 		Commutative: true,
@@ -116120,6 +116286,12 @@
 		Generic:     true,
 	},
 	{
+		Name:        "NotEqualUint8s",
+		ArgLen:      2,
+		Commutative: true,
+		Generic:     true,
+	},
+	{
 		Name:        "NotEqualUint8x16",
 		ArgLen:      2,
 		Commutative: true,
diff --git a/src/cmd/compile/internal/ssagen/simdARM64SVEintrinsics.go b/src/cmd/compile/internal/ssagen/simdARM64SVEintrinsics.go
index 60eb999..b4631e4 100644
--- a/src/cmd/compile/internal/ssagen/simdARM64SVEintrinsics.go
+++ b/src/cmd/compile/internal/ssagen/simdARM64SVEintrinsics.go
@@ -65,6 +65,16 @@
 	addF(simdPackage, "Int16s.Neg", opLen1(ssaop.OpNegInt16s, types.TypeVec256), sys.ARM64)
 	addF(simdPackage, "Int32s.Neg", opLen1(ssaop.OpNegInt32s, types.TypeVec256), sys.ARM64)
 	addF(simdPackage, "Int64s.Neg", opLen1(ssaop.OpNegInt64s, types.TypeVec256), sys.ARM64)
+	addF(simdPackage, "Float32s.NotEqual", opLen2(ssaop.OpNotEqualFloat32s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Float64s.NotEqual", opLen2(ssaop.OpNotEqualFloat64s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Int8s.NotEqual", opLen2(ssaop.OpNotEqualInt8s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Int16s.NotEqual", opLen2(ssaop.OpNotEqualInt16s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Int32s.NotEqual", opLen2(ssaop.OpNotEqualInt32s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Int64s.NotEqual", opLen2(ssaop.OpNotEqualInt64s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Uint8s.NotEqual", opLen2(ssaop.OpNotEqualUint8s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Uint16s.NotEqual", opLen2(ssaop.OpNotEqualUint16s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Uint32s.NotEqual", opLen2(ssaop.OpNotEqualUint32s, types.TypeMask), sys.ARM64)
+	addF(simdPackage, "Uint64s.NotEqual", opLen2(ssaop.OpNotEqualUint64s, types.TypeMask), sys.ARM64)
 	addF(simdPackage, "Float32s.Round", opLen1(ssaop.OpRoundFloat32s, types.TypeVec256), sys.ARM64)
 	addF(simdPackage, "Float64s.Round", opLen1(ssaop.OpRoundFloat64s, types.TypeVec256), sys.ARM64)
 	addF(simdPackage, "Float32s.Sqrt", opLen1(ssaop.OpSqrtFloat32s, types.TypeVec256), sys.ARM64)
diff --git a/src/cmd/compile/internal/ssarewrite/rewritearm64/rewriteARM64.go b/src/cmd/compile/internal/ssarewrite/rewritearm64/rewriteARM64.go
index 61ea2be..358cc72 100644
--- a/src/cmd/compile/internal/ssarewrite/rewritearm64/rewriteARM64.go
+++ b/src/cmd/compile/internal/ssarewrite/rewritearm64/rewriteARM64.go
@@ -1885,6 +1885,26 @@
 		return true
 	case ssaop.OpNot:
 		return rewriteValue_OpNot(v)
+	case ssaop.OpNotEqualFloat32s:
+		return rewriteValue_OpNotEqualFloat32s(v)
+	case ssaop.OpNotEqualFloat64s:
+		return rewriteValue_OpNotEqualFloat64s(v)
+	case ssaop.OpNotEqualInt16s:
+		return rewriteValue_OpNotEqualInt16s(v)
+	case ssaop.OpNotEqualInt32s:
+		return rewriteValue_OpNotEqualInt32s(v)
+	case ssaop.OpNotEqualInt64s:
+		return rewriteValue_OpNotEqualInt64s(v)
+	case ssaop.OpNotEqualInt8s:
+		return rewriteValue_OpNotEqualInt8s(v)
+	case ssaop.OpNotEqualUint16s:
+		return rewriteValue_OpNotEqualUint16s(v)
+	case ssaop.OpNotEqualUint32s:
+		return rewriteValue_OpNotEqualUint32s(v)
+	case ssaop.OpNotEqualUint64s:
+		return rewriteValue_OpNotEqualUint64s(v)
+	case ssaop.OpNotEqualUint8s:
+		return rewriteValue_OpNotEqualUint8s(v)
 	case ssaop.OpNotInt16x8:
 		v.Op = ssaop.OpARM64VNOT16B
 		return true
@@ -25012,6 +25032,236 @@
 		return true
 	}
 }
+func rewriteValue_OpNotEqualFloat32s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualFloat32s x y)
+	// result: (ZFCMNES x y (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZFCMNES)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTS, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(8)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualFloat64s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualFloat64s x y)
+	// result: (ZFCMNED x y (Select0 <types.TypeMask> (PWHILELTD (MOVDconst [0]) (MOVDconst [4]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZFCMNED)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTD, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(4)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualInt16s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualInt16s x y)
+	// result: (ZCMPNEH x y (Select0 <types.TypeMask> (PWHILELTH (MOVDconst [0]) (MOVDconst [16]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZCMPNEH)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTH, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(16)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualInt32s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualInt32s x y)
+	// result: (ZCMPNES x y (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZCMPNES)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTS, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(8)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualInt64s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualInt64s x y)
+	// result: (ZCMPNED x y (Select0 <types.TypeMask> (PWHILELTD (MOVDconst [0]) (MOVDconst [4]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZCMPNED)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTD, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(4)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualInt8s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualInt8s x y)
+	// result: (ZCMPNEB x y (Select0 <types.TypeMask> (PWHILELTB (MOVDconst [0]) (MOVDconst [32]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZCMPNEB)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTB, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(32)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualUint16s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualUint16s x y)
+	// result: (ZCMPNEH x y (Select0 <types.TypeMask> (PWHILELTH (MOVDconst [0]) (MOVDconst [16]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZCMPNEH)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTH, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(16)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualUint32s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualUint32s x y)
+	// result: (ZCMPNES x y (Select0 <types.TypeMask> (PWHILELTS (MOVDconst [0]) (MOVDconst [8]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZCMPNES)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTS, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(8)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualUint64s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualUint64s x y)
+	// result: (ZCMPNED x y (Select0 <types.TypeMask> (PWHILELTD (MOVDconst [0]) (MOVDconst [4]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZCMPNED)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTD, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(4)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
+func rewriteValue_OpNotEqualUint8s(v *ssa.Value) bool {
+	v_1 := v.Args[1]
+	v_0 := v.Args[0]
+	b := v.Block
+	typ := &b.Func.Config.Types
+	// match: (NotEqualUint8s x y)
+	// result: (ZCMPNEB x y (Select0 <types.TypeMask> (PWHILELTB (MOVDconst [0]) (MOVDconst [32]))))
+	for {
+		x := v_0
+		y := v_1
+		v.Reset(ssaop.OpARM64ZCMPNEB)
+		v0 := b.NewValue0(v.Pos, ssaop.OpSelect0, types.TypeMask)
+		v1 := b.NewValue0(v.Pos, ssaop.OpARM64PWHILELTB, types.NewTuple(typ.Mask, types.TypeFlags))
+		v2 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v2.AuxInt = ssa.Int64ToAuxInt(0)
+		v3 := b.NewValue0(v.Pos, ssaop.OpARM64MOVDconst, typ.UInt64)
+		v3.AuxInt = ssa.Int64ToAuxInt(32)
+		v1.AddArg2(v2, v3)
+		v0.AddArg(v1)
+		v.AddArg3(x, y, v0)
+		return true
+	}
+}
 func rewriteValue_OpOffPtr(v *ssa.Value) bool {
 	v_0 := v.Args[0]
 	// match: (OffPtr [off] ptr:(SP))
diff --git a/src/simd/archsimd/_gen/simdgen/ops/Compares/go_sve.yaml b/src/simd/archsimd/_gen/simdgen/ops/Compares/go_sve.yaml
index 1325b32..dc6e181 100644
--- a/src/simd/archsimd/_gen/simdgen/ops/Compares/go_sve.yaml
+++ b/src/simd/archsimd/_gen/simdgen/ops/Compares/go_sve.yaml
@@ -64,3 +64,32 @@
   - class: mask # governing predicate
   out:
   - class: mask
+
+# NotEqual — integer compare, ZCMPNE (sign-agnostic, both signednesses).
+- go: NotEqual
+  asm: "ZCMPNE"
+  in:
+  - *int
+  - *int
+  - class: mask # governing predicate
+  out:
+  - class: mask
+
+- go: NotEqual
+  asm: "ZCMPNE"
+  in:
+  - *uint
+  - *uint
+  - class: mask # governing predicate
+  out:
+  - class: mask
+
+# NotEqual — floating-point compare, ZFCMNE.
+- go: NotEqual
+  asm: "ZFCMNE"
+  in:
+  - *float
+  - *float
+  - class: mask # governing predicate
+  out:
+  - class: mask
diff --git a/src/simd/archsimd/internal/simd_test/compare_sve_arm64_test.go b/src/simd/archsimd/internal/simd_test/compare_sve_arm64_test.go
index 20c1412..5f14926 100644
--- a/src/simd/archsimd/internal/simd_test/compare_sve_arm64_test.go
+++ b/src/simd/archsimd/internal/simd_test/compare_sve_arm64_test.go
@@ -111,3 +111,12 @@
 	testUint8sCompare(t, archsimd.Uint8s.Equal, func(a, b uint8) bool { return a == b })
 	testFloat64sCompare(t, archsimd.Float64s.Equal, func(a, b float64) bool { return a == b })
 }
+
+func TestNotEqualSVE(t *testing.T) {
+	if !archsimd.ARM64.SVE() {
+		t.Skip("no sve")
+	}
+	testInt8sCompare(t, archsimd.Int8s.NotEqual, func(a, b int8) bool { return a != b })
+	testUint8sCompare(t, archsimd.Uint8s.NotEqual, func(a, b uint8) bool { return a != b })
+	testFloat64sCompare(t, archsimd.Float64s.NotEqual, func(a, b float64) bool { return a != b })
+}
diff --git a/src/simd/archsimd/ops_sve.go b/src/simd/archsimd/ops_sve.go
index 9656e3b..622ffe2 100644
--- a/src/simd/archsimd/ops_sve.go
+++ b/src/simd/archsimd/ops_sve.go
@@ -290,6 +290,58 @@
 // Asm: ZNEG, CPU Feature: SVE
 func (x Int64s) Neg() Int64s
 
+/* NotEqual */
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZFCMNE, CPU Feature: SVE
+func (x Float32s) NotEqual(y Float32s) Mask32s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZFCMNE, CPU Feature: SVE
+func (x Float64s) NotEqual(y Float64s) Mask64s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZCMPNE, CPU Feature: SVE
+func (x Int8s) NotEqual(y Int8s) Mask8s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZCMPNE, CPU Feature: SVE
+func (x Int16s) NotEqual(y Int16s) Mask16s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZCMPNE, CPU Feature: SVE
+func (x Int32s) NotEqual(y Int32s) Mask32s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZCMPNE, CPU Feature: SVE
+func (x Int64s) NotEqual(y Int64s) Mask64s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZCMPNE, CPU Feature: SVE
+func (x Uint8s) NotEqual(y Uint8s) Mask8s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZCMPNE, CPU Feature: SVE
+func (x Uint16s) NotEqual(y Uint16s) Mask16s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZCMPNE, CPU Feature: SVE
+func (x Uint32s) NotEqual(y Uint32s) Mask32s
+
+// NotEqual returns a mask whose elements indicate whether x != y.
+//
+// Asm: ZCMPNE, CPU Feature: SVE
+func (x Uint64s) NotEqual(y Uint64s) Mask64s
+
 /* Round */
 
 // Round rounds elements to the nearest integer, rounding ties to even.