Source file src/simd/archsimd/internal/simd_test/binary_sve_arm64_test.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build goexperiment.simd && arm64
     6  
     7  // SVE binary-op tests. Unlike amd64, SVE has only a handful of (scalable)
     8  // vector types, so there is nothing to generate — these drivers are hand-written
     9  // in the same shape as the generated testXxxBinary helpers. Each loads two input
    10  // windows via the fixed-array API, runs the op, stores the result, and compares
    11  // the lanes the hardware actually populated: the vector's runtime Len() (VL is
    12  // <= the 32-byte backing, enforced at package init).
    13  
    14  package simd_test
    15  
    16  import (
    17  	"simd/archsimd"
    18  	"testing"
    19  )
    20  
    21  // sveMaxBytes is the fixed backing-array size for a scalable vector: the maximum
    22  // vector length simd supports (256 bits).
    23  const sveMaxBytes = 32
    24  
    25  // testSVEBinary drives a scalable binary op like the generated testXxxBinary
    26  // helpers. active is the runtime number of live lanes (from the vector's Len()).
    27  func testSVEBinary[T number, V any](t *testing.T, pool []T, elemBytes, active int,
    28  	load func([]T) V, f func(V, V) V, store func(V, []T), want func([]T, []T) []T) {
    29  	t.Helper()
    30  	count := sveMaxBytes / elemBytes // lanes in the fixed backing array
    31  	forSlicePair(t, pool, count, func(x, y []T) bool {
    32  		t.Helper()
    33  		g := make([]T, count)
    34  		store(f(load(x), load(y)), g)
    35  		w := want(x, y)
    36  		return checkSlicesLogInput(t, g[:active], w[:active], 0.0, func() {
    37  			t.Helper()
    38  			t.Logf("x=%v", x)
    39  			t.Logf("y=%v", y)
    40  		})
    41  	})
    42  }
    43  
    44  func testInt8sBinary(t *testing.T, f func(_, _ archsimd.Int8s) archsimd.Int8s, want func(_, _ []int8) []int8) {
    45  	var z archsimd.Int8s
    46  	testSVEBinary(t, int8s, 1, z.Len(), archsimd.LoadInt8s, f, archsimd.Int8s.Store, want)
    47  }
    48  
    49  func testInt16sBinary(t *testing.T, f func(_, _ archsimd.Int16s) archsimd.Int16s, want func(_, _ []int16) []int16) {
    50  	var z archsimd.Int16s
    51  	testSVEBinary(t, int16s, 2, z.Len(), archsimd.LoadInt16s, f, archsimd.Int16s.Store, want)
    52  }
    53  
    54  func testInt32sBinary(t *testing.T, f func(_, _ archsimd.Int32s) archsimd.Int32s, want func(_, _ []int32) []int32) {
    55  	var z archsimd.Int32s
    56  	testSVEBinary(t, int32s, 4, z.Len(), archsimd.LoadInt32s, f, archsimd.Int32s.Store, want)
    57  }
    58  
    59  func testInt64sBinary(t *testing.T, f func(_, _ archsimd.Int64s) archsimd.Int64s, want func(_, _ []int64) []int64) {
    60  	var z archsimd.Int64s
    61  	testSVEBinary(t, int64s, 8, z.Len(), archsimd.LoadInt64s, f, archsimd.Int64s.Store, want)
    62  }
    63  
    64  func testUint8sBinary(t *testing.T, f func(_, _ archsimd.Uint8s) archsimd.Uint8s, want func(_, _ []uint8) []uint8) {
    65  	var z archsimd.Uint8s
    66  	testSVEBinary(t, uint8s, 1, z.Len(), archsimd.LoadUint8s, f, archsimd.Uint8s.Store, want)
    67  }
    68  
    69  func testFloat32sBinary(t *testing.T, f func(_, _ archsimd.Float32s) archsimd.Float32s, want func(_, _ []float32) []float32) {
    70  	var z archsimd.Float32s
    71  	testSVEBinary(t, float32s, 4, z.Len(), archsimd.LoadFloat32s, f, archsimd.Float32s.Store, want)
    72  }
    73  
    74  func testFloat64sBinary(t *testing.T, f func(_, _ archsimd.Float64s) archsimd.Float64s, want func(_, _ []float64) []float64) {
    75  	var z archsimd.Float64s
    76  	testSVEBinary(t, float64s, 8, z.Len(), archsimd.LoadFloat64s, f, archsimd.Float64s.Store, want)
    77  }
    78  
    79  func TestAddSVE(t *testing.T) {
    80  	if !archsimd.ARM64.SVE() {
    81  		t.Skip("no SVE")
    82  	}
    83  	testInt8sBinary(t, archsimd.Int8s.Add, addSlice[int8])
    84  	testInt16sBinary(t, archsimd.Int16s.Add, addSlice[int16])
    85  	testInt32sBinary(t, archsimd.Int32s.Add, addSlice[int32])
    86  	testInt64sBinary(t, archsimd.Int64s.Add, addSlice[int64])
    87  	testUint8sBinary(t, archsimd.Uint8s.Add, addSlice[uint8])
    88  	testFloat32sBinary(t, archsimd.Float32s.Add, addSlice[float32])
    89  	testFloat64sBinary(t, archsimd.Float64s.Add, addSlice[float64])
    90  }
    91  

View as plain text