]> Cypherpunks repositories - gostls13.git/commitdiff
simd/archsimd: make IsNaN unary
authorCherry Mui <cherryyz@google.com>
Wed, 31 Dec 2025 07:42:30 +0000 (02:42 -0500)
committerCherry Mui <cherryyz@google.com>
Fri, 2 Jan 2026 20:13:40 +0000 (12:13 -0800)
Currently, the IsNan API is defined as x.IsNan(y), which returns
a mask to represent, for each element, either x or y is NaN.
Albeit closer to the machine instruction, this is weird API, as
IsNaN is a unary operation. This CL changes it to unary, x.IsNaN().
It compiles to VCMPPS $3, x, x (or VCMPPD). For the two-operand
version, we can optimize x.IsNaN().Or(y.IsNaN()) to VCMPPS $3, x,
y (not done in this CL).

While here, change the name to IsNaN (uppercase both Ns), which
matches math.IsNaN.

Tests in the next CL.

Change-Id: Ib6e7afc2635e6c3c606db5ea16420ee673a6c6d6
Reviewed-on: https://go-review.googlesource.com/c/go/+/733660
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

12 files changed:
src/cmd/compile/internal/ssa/_gen/AMD64.rules
src/cmd/compile/internal/ssa/_gen/genericOps.go
src/cmd/compile/internal/ssa/_gen/simdAMD64.rules
src/cmd/compile/internal/ssa/_gen/simdgenericOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteAMD64.go
src/cmd/compile/internal/ssagen/intrinsics.go
src/cmd/compile/internal/ssagen/simdintrinsics.go
src/simd/archsimd/_gen/simdgen/ops/Compares/categories.yaml
src/simd/archsimd/_gen/simdgen/ops/Compares/go.yaml
src/simd/archsimd/extra_amd64.go
src/simd/archsimd/ops_amd64.go

index 38ca44f7eb092d09b98d5d12924e44e7859985fd..9c541868548d40443e8ad33074f9fe1dce43bb00 100644 (file)
 // Misc
 (IsZeroVec x) => (SETEQ (VPTEST x x))
 
+(IsNaNFloat32x4  x) => (VCMPPS128 [3] x x)
+(IsNaNFloat32x8  x) => (VCMPPS256 [3] x x)
+(IsNaNFloat32x16 x) => (VPMOVMToVec32x16 (VCMPPS512 [3] x x))
+(IsNaNFloat64x2  x) => (VCMPPD128 [3] x x)
+(IsNaNFloat64x4  x) => (VCMPPD256 [3] x x)
+(IsNaNFloat64x8  x) => (VPMOVMToVec64x8 (VCMPPD512 [3] x x))
+
 // SIMD vector K-masked loads and stores
 
 (LoadMasked64 <t> ptr mask mem) && t.Size() == 64 => (VPMASK64load512 ptr (VPMOVVec64x8ToM  <types.TypeMask> mask) mem)
index 8637133e5f77e9d2e406bcf9791145ba6b5bd976..85bde1aab27724a926b23f878d5e1a246e4ab4f1 100644 (file)
@@ -715,6 +715,14 @@ var genericOps = []opData{
 
        // Returns true if arg0 is all zero.
        {name: "IsZeroVec", argLength: 1},
+
+       // Returns a mask indicating whether arg0's elements are NaN.
+       {name: "IsNaNFloat32x4", argLength: 1},
+       {name: "IsNaNFloat32x8", argLength: 1},
+       {name: "IsNaNFloat32x16", argLength: 1},
+       {name: "IsNaNFloat64x2", argLength: 1},
+       {name: "IsNaNFloat64x4", argLength: 1},
+       {name: "IsNaNFloat64x8", argLength: 1},
 }
 
 //     kind          controls          successors   implicit exit
index 8a5b70da308fe63ace019e2831c7f0873e12e62d..5c83f39a1fec33e41ee382a919ecd54a20f94733 100644 (file)
 (InterleaveLoGroupedUint32x16 ...) => (VPUNPCKLDQ512 ...)
 (InterleaveLoGroupedUint64x4 ...) => (VPUNPCKLQDQ256 ...)
 (InterleaveLoGroupedUint64x8 ...) => (VPUNPCKLQDQ512 ...)
-(IsNanFloat32x4 x y) => (VCMPPS128 [3] x y)
-(IsNanFloat32x8 x y) => (VCMPPS256 [3] x y)
-(IsNanFloat32x16 x y) => (VPMOVMToVec32x16 (VCMPPS512 [3] x y))
-(IsNanFloat64x2 x y) => (VCMPPD128 [3] x y)
-(IsNanFloat64x4 x y) => (VCMPPD256 [3] x y)
-(IsNanFloat64x8 x y) => (VPMOVMToVec64x8 (VCMPPD512 [3] x y))
 (LeadingZerosInt32x4 ...) => (VPLZCNTD128 ...)
 (LeadingZerosInt32x8 ...) => (VPLZCNTD256 ...)
 (LeadingZerosInt32x16 ...) => (VPLZCNTD512 ...)
index af1007cd542e8389560b87e6629b336db4cf313f..889ab0d84ffa22b0da8174048ed7109bb19cd6b1 100644 (file)
@@ -519,12 +519,6 @@ func simdGenericOps() []opData {
                {name: "InterleaveLoUint16x8", argLength: 2, commutative: false},
                {name: "InterleaveLoUint32x4", argLength: 2, commutative: false},
                {name: "InterleaveLoUint64x2", argLength: 2, commutative: false},
-               {name: "IsNanFloat32x4", argLength: 2, commutative: true},
-               {name: "IsNanFloat32x8", argLength: 2, commutative: true},
-               {name: "IsNanFloat32x16", argLength: 2, commutative: true},
-               {name: "IsNanFloat64x2", argLength: 2, commutative: true},
-               {name: "IsNanFloat64x4", argLength: 2, commutative: true},
-               {name: "IsNanFloat64x8", argLength: 2, commutative: true},
                {name: "LeadingZerosInt32x4", argLength: 1, commutative: false},
                {name: "LeadingZerosInt32x8", argLength: 1, commutative: false},
                {name: "LeadingZerosInt32x16", argLength: 1, commutative: false},
index d2ba15f740983df11844eafcca05b4e9e780a3e0..abaf7911d47086bc97e66b46f52aad7706eec0f2 100644 (file)
@@ -6158,6 +6158,12 @@ const (
        OpCvtMask64x4to8
        OpCvtMask64x8to8
        OpIsZeroVec
+       OpIsNaNFloat32x4
+       OpIsNaNFloat32x8
+       OpIsNaNFloat32x16
+       OpIsNaNFloat64x2
+       OpIsNaNFloat64x4
+       OpIsNaNFloat64x8
        OpAESDecryptLastRoundUint8x16
        OpAESDecryptLastRoundUint8x32
        OpAESDecryptLastRoundUint8x64
@@ -6673,12 +6679,6 @@ const (
        OpInterleaveLoUint16x8
        OpInterleaveLoUint32x4
        OpInterleaveLoUint64x2
-       OpIsNanFloat32x4
-       OpIsNanFloat32x8
-       OpIsNanFloat32x16
-       OpIsNanFloat64x2
-       OpIsNanFloat64x4
-       OpIsNanFloat64x8
        OpLeadingZerosInt32x4
        OpLeadingZerosInt32x8
        OpLeadingZerosInt32x16
@@ -88993,6 +88993,36 @@ var opcodeTable = [...]opInfo{
                argLen:  1,
                generic: true,
        },
+       {
+               name:    "IsNaNFloat32x4",
+               argLen:  1,
+               generic: true,
+       },
+       {
+               name:    "IsNaNFloat32x8",
+               argLen:  1,
+               generic: true,
+       },
+       {
+               name:    "IsNaNFloat32x16",
+               argLen:  1,
+               generic: true,
+       },
+       {
+               name:    "IsNaNFloat64x2",
+               argLen:  1,
+               generic: true,
+       },
+       {
+               name:    "IsNaNFloat64x4",
+               argLen:  1,
+               generic: true,
+       },
+       {
+               name:    "IsNaNFloat64x8",
+               argLen:  1,
+               generic: true,
+       },
        {
                name:    "AESDecryptLastRoundUint8x16",
                argLen:  2,
@@ -91670,42 +91700,6 @@ var opcodeTable = [...]opInfo{
                argLen:  2,
                generic: true,
        },
-       {
-               name:        "IsNanFloat32x4",
-               argLen:      2,
-               commutative: true,
-               generic:     true,
-       },
-       {
-               name:        "IsNanFloat32x8",
-               argLen:      2,
-               commutative: true,
-               generic:     true,
-       },
-       {
-               name:        "IsNanFloat32x16",
-               argLen:      2,
-               commutative: true,
-               generic:     true,
-       },
-       {
-               name:        "IsNanFloat64x2",
-               argLen:      2,
-               commutative: true,
-               generic:     true,
-       },
-       {
-               name:        "IsNanFloat64x4",
-               argLen:      2,
-               commutative: true,
-               generic:     true,
-       },
-       {
-               name:        "IsNanFloat64x8",
-               argLen:      2,
-               commutative: true,
-               generic:     true,
-       },
        {
                name:    "LeadingZerosInt32x4",
                argLen:  1,
index 0c0441007486bbda149d74ff3047452ecfa3b1a4..0b2bb74ce489c91306ee1183a732cdb8bd91a553 100644 (file)
@@ -3773,18 +3773,18 @@ func rewriteValueAMD64(v *Value) bool {
                return true
        case OpIsInBounds:
                return rewriteValueAMD64_OpIsInBounds(v)
-       case OpIsNanFloat32x16:
-               return rewriteValueAMD64_OpIsNanFloat32x16(v)
-       case OpIsNanFloat32x4:
-               return rewriteValueAMD64_OpIsNanFloat32x4(v)
-       case OpIsNanFloat32x8:
-               return rewriteValueAMD64_OpIsNanFloat32x8(v)
-       case OpIsNanFloat64x2:
-               return rewriteValueAMD64_OpIsNanFloat64x2(v)
-       case OpIsNanFloat64x4:
-               return rewriteValueAMD64_OpIsNanFloat64x4(v)
-       case OpIsNanFloat64x8:
-               return rewriteValueAMD64_OpIsNanFloat64x8(v)
+       case OpIsNaNFloat32x16:
+               return rewriteValueAMD64_OpIsNaNFloat32x16(v)
+       case OpIsNaNFloat32x4:
+               return rewriteValueAMD64_OpIsNaNFloat32x4(v)
+       case OpIsNaNFloat32x8:
+               return rewriteValueAMD64_OpIsNaNFloat32x8(v)
+       case OpIsNaNFloat64x2:
+               return rewriteValueAMD64_OpIsNaNFloat64x2(v)
+       case OpIsNaNFloat64x4:
+               return rewriteValueAMD64_OpIsNaNFloat64x4(v)
+       case OpIsNaNFloat64x8:
+               return rewriteValueAMD64_OpIsNaNFloat64x8(v)
        case OpIsNonNil:
                return rewriteValueAMD64_OpIsNonNil(v)
        case OpIsSliceInBounds:
@@ -70957,94 +70957,82 @@ func rewriteValueAMD64_OpIsInBounds(v *Value) bool {
                return true
        }
 }
-func rewriteValueAMD64_OpIsNanFloat32x16(v *Value) bool {
-       v_1 := v.Args[1]
+func rewriteValueAMD64_OpIsNaNFloat32x16(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (IsNanFloat32x16 x y)
-       // result: (VPMOVMToVec32x16 (VCMPPS512 [3] x y))
+       // match: (IsNaNFloat32x16 x)
+       // result: (VPMOVMToVec32x16 (VCMPPS512 [3] x x))
        for {
                x := v_0
-               y := v_1
                v.reset(OpAMD64VPMOVMToVec32x16)
                v0 := b.NewValue0(v.Pos, OpAMD64VCMPPS512, typ.Mask)
                v0.AuxInt = uint8ToAuxInt(3)
-               v0.AddArg2(x, y)
+               v0.AddArg2(x, x)
                v.AddArg(v0)
                return true
        }
 }
-func rewriteValueAMD64_OpIsNanFloat32x4(v *Value) bool {
-       v_1 := v.Args[1]
+func rewriteValueAMD64_OpIsNaNFloat32x4(v *Value) bool {
        v_0 := v.Args[0]
-       // match: (IsNanFloat32x4 x y)
-       // result: (VCMPPS128 [3] x y)
+       // match: (IsNaNFloat32x4 x)
+       // result: (VCMPPS128 [3] x x)
        for {
                x := v_0
-               y := v_1
                v.reset(OpAMD64VCMPPS128)
                v.AuxInt = uint8ToAuxInt(3)
-               v.AddArg2(x, y)
+               v.AddArg2(x, x)
                return true
        }
 }
-func rewriteValueAMD64_OpIsNanFloat32x8(v *Value) bool {
-       v_1 := v.Args[1]
+func rewriteValueAMD64_OpIsNaNFloat32x8(v *Value) bool {
        v_0 := v.Args[0]
-       // match: (IsNanFloat32x8 x y)
-       // result: (VCMPPS256 [3] x y)
+       // match: (IsNaNFloat32x8 x)
+       // result: (VCMPPS256 [3] x x)
        for {
                x := v_0
-               y := v_1
                v.reset(OpAMD64VCMPPS256)
                v.AuxInt = uint8ToAuxInt(3)
-               v.AddArg2(x, y)
+               v.AddArg2(x, x)
                return true
        }
 }
-func rewriteValueAMD64_OpIsNanFloat64x2(v *Value) bool {
-       v_1 := v.Args[1]
+func rewriteValueAMD64_OpIsNaNFloat64x2(v *Value) bool {
        v_0 := v.Args[0]
-       // match: (IsNanFloat64x2 x y)
-       // result: (VCMPPD128 [3] x y)
+       // match: (IsNaNFloat64x2 x)
+       // result: (VCMPPD128 [3] x x)
        for {
                x := v_0
-               y := v_1
                v.reset(OpAMD64VCMPPD128)
                v.AuxInt = uint8ToAuxInt(3)
-               v.AddArg2(x, y)
+               v.AddArg2(x, x)
                return true
        }
 }
-func rewriteValueAMD64_OpIsNanFloat64x4(v *Value) bool {
-       v_1 := v.Args[1]
+func rewriteValueAMD64_OpIsNaNFloat64x4(v *Value) bool {
        v_0 := v.Args[0]
-       // match: (IsNanFloat64x4 x y)
-       // result: (VCMPPD256 [3] x y)
+       // match: (IsNaNFloat64x4 x)
+       // result: (VCMPPD256 [3] x x)
        for {
                x := v_0
-               y := v_1
                v.reset(OpAMD64VCMPPD256)
                v.AuxInt = uint8ToAuxInt(3)
-               v.AddArg2(x, y)
+               v.AddArg2(x, x)
                return true
        }
 }
-func rewriteValueAMD64_OpIsNanFloat64x8(v *Value) bool {
-       v_1 := v.Args[1]
+func rewriteValueAMD64_OpIsNaNFloat64x8(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (IsNanFloat64x8 x y)
-       // result: (VPMOVMToVec64x8 (VCMPPD512 [3] x y))
+       // match: (IsNaNFloat64x8 x)
+       // result: (VPMOVMToVec64x8 (VCMPPD512 [3] x x))
        for {
                x := v_0
-               y := v_1
                v.reset(OpAMD64VPMOVMToVec64x8)
                v0 := b.NewValue0(v.Pos, OpAMD64VCMPPD512, typ.Mask)
                v0.AuxInt = uint8ToAuxInt(3)
-               v0.AddArg2(x, y)
+               v0.AddArg2(x, x)
                v.AddArg(v0)
                return true
        }
index 4425c5617b1e4bc30341706e9e836e3921a58e6e..e2eebd783d5f76442b1aa84b0d82e7dc6ff7e1d0 100644 (file)
@@ -1667,6 +1667,12 @@ func initIntrinsics(cfg *intrinsicBuildConfig) {
                addF(simdPackage, "Uint16x16.IsZero", opLen1(ssa.OpIsZeroVec, types.Types[types.TBOOL]), sys.AMD64)
                addF(simdPackage, "Uint32x8.IsZero", opLen1(ssa.OpIsZeroVec, types.Types[types.TBOOL]), sys.AMD64)
                addF(simdPackage, "Uint64x4.IsZero", opLen1(ssa.OpIsZeroVec, types.Types[types.TBOOL]), sys.AMD64)
+               addF(simdPackage, "Float32x4.IsNaN", opLen1(ssa.OpIsNaNFloat32x4, types.TypeVec128), sys.AMD64)
+               addF(simdPackage, "Float32x8.IsNaN", opLen1(ssa.OpIsNaNFloat32x8, types.TypeVec256), sys.AMD64)
+               addF(simdPackage, "Float32x16.IsNaN", opLen1(ssa.OpIsNaNFloat32x16, types.TypeVec512), sys.AMD64)
+               addF(simdPackage, "Float64x2.IsNaN", opLen1(ssa.OpIsNaNFloat64x2, types.TypeVec128), sys.AMD64)
+               addF(simdPackage, "Float64x4.IsNaN", opLen1(ssa.OpIsNaNFloat64x4, types.TypeVec256), sys.AMD64)
+               addF(simdPackage, "Float64x8.IsNaN", opLen1(ssa.OpIsNaNFloat64x8, types.TypeVec512), sys.AMD64)
 
                // sfp4 is intrinsic-if-constant, but otherwise it's complicated enough to just implement in Go.
                sfp4 := func(method string, hwop ssa.Op, vectype *types.Type) {
index 5a95761228860282349f02c52e4bd4b4e84e2969..4ad0c6032c0cf5223d3cd6547306fbeaf4914625 100644 (file)
@@ -571,12 +571,6 @@ func simdIntrinsics(addF func(pkg, fn string, b intrinsicBuilder, archFamilies .
        addF(simdPackage, "Uint32x16.InterleaveLoGrouped", opLen2(ssa.OpInterleaveLoGroupedUint32x16, types.TypeVec512), sys.AMD64)
        addF(simdPackage, "Uint64x4.InterleaveLoGrouped", opLen2(ssa.OpInterleaveLoGroupedUint64x4, types.TypeVec256), sys.AMD64)
        addF(simdPackage, "Uint64x8.InterleaveLoGrouped", opLen2(ssa.OpInterleaveLoGroupedUint64x8, types.TypeVec512), sys.AMD64)
-       addF(simdPackage, "Float32x4.IsNan", opLen2(ssa.OpIsNanFloat32x4, types.TypeVec128), sys.AMD64)
-       addF(simdPackage, "Float32x8.IsNan", opLen2(ssa.OpIsNanFloat32x8, types.TypeVec256), sys.AMD64)
-       addF(simdPackage, "Float32x16.IsNan", opLen2(ssa.OpIsNanFloat32x16, types.TypeVec512), sys.AMD64)
-       addF(simdPackage, "Float64x2.IsNan", opLen2(ssa.OpIsNanFloat64x2, types.TypeVec128), sys.AMD64)
-       addF(simdPackage, "Float64x4.IsNan", opLen2(ssa.OpIsNanFloat64x4, types.TypeVec256), sys.AMD64)
-       addF(simdPackage, "Float64x8.IsNan", opLen2(ssa.OpIsNanFloat64x8, types.TypeVec512), sys.AMD64)
        addF(simdPackage, "Int32x4.LeadingZeros", opLen1(ssa.OpLeadingZerosInt32x4, types.TypeVec128), sys.AMD64)
        addF(simdPackage, "Int32x8.LeadingZeros", opLen1(ssa.OpLeadingZerosInt32x8, types.TypeVec256), sys.AMD64)
        addF(simdPackage, "Int32x16.LeadingZeros", opLen1(ssa.OpLeadingZerosInt32x16, types.TypeVec512), sys.AMD64)
index eb1d8161c3b36762cf1bb59ca8520a4089131428..97ee587503e183529d932387b769cccd95de98bc 100644 (file)
   commutative: false
   documentation: !string |-
     // NAME returns a mask whose elements indicate whether x <= y.
-- go: IsNan # For float only.
-  constImm: 3
-  commutative: true
-  documentation: !string |-
-    // NAME checks if elements are NaN. Use as x.IsNan(x).
 - go: NotEqual
   constImm: 4
   commutative: true
index 3f6c8a45b6858e25a6e6f78d7a52110c140ddaa9..6dbfb573434eca9126da60bd183fad85a9468b9f 100644 (file)
   - class: mask
 
 # Floats
-- go: Equal|Greater|Less|LessEqual|GreaterEqual|NotEqual|IsNan
+- go: (Equal|Greater|Less|LessEqual|GreaterEqual|NotEqual)
   regexpTag: "compares"
   asm: "VCMPP[SD]"
   in:
   - go: $t
     overwriteBase: int
     overwriteClass: mask
-- go: (Equal|Greater|Less|LessEqual|GreaterEqual|NotEqual|IsNan)
+- go: (Equal|Greater|Less|LessEqual|GreaterEqual|NotEqual)
   regexpTag: "compares"
   asm: "VCMPP[SD]"
   in:
index cd5a3230b93aba35f097a7f22e0bdb1484c7aadb..b0dba6d2345b677d146c920f334fa07762159983 100644 (file)
@@ -143,3 +143,39 @@ func (x Uint64x2) IsZero() bool
 //
 // Asm: VPTEST, CPU Feature: AVX
 func (x Uint64x4) IsZero() bool
+
+// IsNaN returns a mask whose elements indicate whether the corresponding
+// elements of x are NaN.
+//
+// Asm: VCMPPS, CPU Feature: AVX
+func (x Float32x4) IsNaN() Mask32x4
+
+// IsNaN returns a mask whose elements indicate whether the corresponding
+// elements of x are NaN.
+//
+// Asm: VCMPPS, CPU Feature: AVX
+func (x Float32x8) IsNaN() Mask32x8
+
+// IsNaN returns a mask whose elements indicate whether the corresponding
+// elements of x are NaN.
+//
+// Asm: VCMPPS, CPU Feature: AVX512
+func (x Float32x16) IsNaN() Mask32x16
+
+// IsNaN returns a mask whose elements indicate whether the corresponding
+// elements of x are NaN.
+//
+// Asm: VCMPPD, CPU Feature: AVX
+func (x Float64x2) IsNaN() Mask64x2
+
+// IsNaN returns a mask whose elements indicate whether the corresponding
+// elements of x are NaN.
+//
+// Asm: VCMPPD, CPU Feature: AVX
+func (x Float64x4) IsNaN() Mask64x4
+
+// IsNaN returns a mask whose elements indicate whether the corresponding
+// elements of x are NaN.
+//
+// Asm: VCMPPD, CPU Feature: AVX512
+func (x Float64x8) IsNaN() Mask64x8
index 95d417b3dfedc4527b99b35801247041dcdc1e94..eba340c79390785b8a5d3e9f38dedefb7af9976d 100644 (file)
@@ -3446,38 +3446,6 @@ func (x Uint64x4) InterleaveLoGrouped(y Uint64x4) Uint64x4
 // Asm: VPUNPCKLQDQ, CPU Feature: AVX512
 func (x Uint64x8) InterleaveLoGrouped(y Uint64x8) Uint64x8
 
-/* IsNan */
-
-// IsNan checks if elements are NaN. Use as x.IsNan(x).
-//
-// Asm: VCMPPS, CPU Feature: AVX
-func (x Float32x4) IsNan(y Float32x4) Mask32x4
-
-// IsNan checks if elements are NaN. Use as x.IsNan(x).
-//
-// Asm: VCMPPS, CPU Feature: AVX
-func (x Float32x8) IsNan(y Float32x8) Mask32x8
-
-// IsNan checks if elements are NaN. Use as x.IsNan(x).
-//
-// Asm: VCMPPS, CPU Feature: AVX512
-func (x Float32x16) IsNan(y Float32x16) Mask32x16
-
-// IsNan checks if elements are NaN. Use as x.IsNan(x).
-//
-// Asm: VCMPPD, CPU Feature: AVX
-func (x Float64x2) IsNan(y Float64x2) Mask64x2
-
-// IsNan checks if elements are NaN. Use as x.IsNan(x).
-//
-// Asm: VCMPPD, CPU Feature: AVX
-func (x Float64x4) IsNan(y Float64x4) Mask64x4
-
-// IsNan checks if elements are NaN. Use as x.IsNan(x).
-//
-// Asm: VCMPPD, CPU Feature: AVX512
-func (x Float64x8) IsNan(y Float64x8) Mask64x8
-
 /* LeadingZeros */
 
 // LeadingZeros counts the leading zeros of each element in x.