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.