Source file src/simd/archsimd/internal/simd_test/shuffle_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 shuffle tests. The expected result of a shuffle depends on the runtime
     8  // vector length, so unlike testSVEBinary, these drivers pass only the active
     9  // lanes to want.
    10  
    11  package simd_test
    12  
    13  import (
    14  	"simd/archsimd"
    15  	"testing"
    16  )
    17  
    18  func testSVEShuffle1[T number, V any](t *testing.T, pool []T, elemBytes, active int,
    19  	load func([]T) V, f func(V) V, store func(V, []T), want func([]T) []T) {
    20  	t.Helper()
    21  	count := sveMaxBytes / elemBytes
    22  	forSlice(t, pool, count, func(x []T) bool {
    23  		t.Helper()
    24  		g := make([]T, count)
    25  		store(f(load(x)), g)
    26  		w := want(x[:active])
    27  		return checkSlicesLogInput(t, g[:active], w, 0.0, func() {
    28  			t.Helper()
    29  			t.Logf("x=%v", x[:active])
    30  		})
    31  	})
    32  }
    33  
    34  func testSVEShuffle2[T number, V any](t *testing.T, pool []T, elemBytes, active int,
    35  	load func([]T) V, f func(V, V) V, store func(V, []T), want func([]T, []T) []T) {
    36  	t.Helper()
    37  	count := sveMaxBytes / elemBytes
    38  	forSlicePair(t, pool, count, func(x, y []T) bool {
    39  		t.Helper()
    40  		g := make([]T, count)
    41  		store(f(load(x), load(y)), g)
    42  		w := want(x[:active], y[:active])
    43  		return checkSlicesLogInput(t, g[:active], w, 0.0, func() {
    44  			t.Helper()
    45  			t.Logf("x=%v", x[:active])
    46  			t.Logf("y=%v", y[:active])
    47  		})
    48  	})
    49  }
    50  
    51  func TestHiToLoSVE(t *testing.T) {
    52  	if !archsimd.ARM64.SVE() {
    53  		t.Skip("no SVE")
    54  	}
    55  	testSVEShuffle1(t, int8s, 1, archsimd.Int8s{}.Len(), archsimd.LoadInt8s, archsimd.Int8s.HiToLo, archsimd.Int8s.Store, hiToLoSlice[int8])
    56  	testSVEShuffle1(t, int16s, 2, archsimd.Int16s{}.Len(), archsimd.LoadInt16s, archsimd.Int16s.HiToLo, archsimd.Int16s.Store, hiToLoSlice[int16])
    57  	testSVEShuffle1(t, int32s, 4, archsimd.Int32s{}.Len(), archsimd.LoadInt32s, archsimd.Int32s.HiToLo, archsimd.Int32s.Store, hiToLoSlice[int32])
    58  	testSVEShuffle1(t, int64s, 8, archsimd.Int64s{}.Len(), archsimd.LoadInt64s, archsimd.Int64s.HiToLo, archsimd.Int64s.Store, hiToLoSlice[int64])
    59  	testSVEShuffle1(t, uint8s, 1, archsimd.Uint8s{}.Len(), archsimd.LoadUint8s, archsimd.Uint8s.HiToLo, archsimd.Uint8s.Store, hiToLoSlice[uint8])
    60  	testSVEShuffle1(t, uint16s, 2, archsimd.Uint16s{}.Len(), archsimd.LoadUint16s, archsimd.Uint16s.HiToLo, archsimd.Uint16s.Store, hiToLoSlice[uint16])
    61  	testSVEShuffle1(t, uint32s, 4, archsimd.Uint32s{}.Len(), archsimd.LoadUint32s, archsimd.Uint32s.HiToLo, archsimd.Uint32s.Store, hiToLoSlice[uint32])
    62  	testSVEShuffle1(t, uint64s, 8, archsimd.Uint64s{}.Len(), archsimd.LoadUint64s, archsimd.Uint64s.HiToLo, archsimd.Uint64s.Store, hiToLoSlice[uint64])
    63  	testSVEShuffle1(t, float32s, 4, archsimd.Float32s{}.Len(), archsimd.LoadFloat32s, archsimd.Float32s.HiToLo, archsimd.Float32s.Store, hiToLoSlice[float32])
    64  	testSVEShuffle1(t, float64s, 8, archsimd.Float64s{}.Len(), archsimd.LoadFloat64s, archsimd.Float64s.HiToLo, archsimd.Float64s.Store, hiToLoSlice[float64])
    65  }
    66  
    67  func TestInterleaveLoSVE(t *testing.T) {
    68  	if !archsimd.ARM64.SVE() {
    69  		t.Skip("no SVE")
    70  	}
    71  	testSVEShuffle2(t, int8s, 1, archsimd.Int8s{}.Len(), archsimd.LoadInt8s, archsimd.Int8s.InterleaveLo, archsimd.Int8s.Store, interleaveSlice[int8](0, false))
    72  	testSVEShuffle2(t, int16s, 2, archsimd.Int16s{}.Len(), archsimd.LoadInt16s, archsimd.Int16s.InterleaveLo, archsimd.Int16s.Store, interleaveSlice[int16](0, false))
    73  	testSVEShuffle2(t, int32s, 4, archsimd.Int32s{}.Len(), archsimd.LoadInt32s, archsimd.Int32s.InterleaveLo, archsimd.Int32s.Store, interleaveSlice[int32](0, false))
    74  	testSVEShuffle2(t, int64s, 8, archsimd.Int64s{}.Len(), archsimd.LoadInt64s, archsimd.Int64s.InterleaveLo, archsimd.Int64s.Store, interleaveSlice[int64](0, false))
    75  	testSVEShuffle2(t, uint8s, 1, archsimd.Uint8s{}.Len(), archsimd.LoadUint8s, archsimd.Uint8s.InterleaveLo, archsimd.Uint8s.Store, interleaveSlice[uint8](0, false))
    76  	testSVEShuffle2(t, uint16s, 2, archsimd.Uint16s{}.Len(), archsimd.LoadUint16s, archsimd.Uint16s.InterleaveLo, archsimd.Uint16s.Store, interleaveSlice[uint16](0, false))
    77  	testSVEShuffle2(t, uint32s, 4, archsimd.Uint32s{}.Len(), archsimd.LoadUint32s, archsimd.Uint32s.InterleaveLo, archsimd.Uint32s.Store, interleaveSlice[uint32](0, false))
    78  	testSVEShuffle2(t, uint64s, 8, archsimd.Uint64s{}.Len(), archsimd.LoadUint64s, archsimd.Uint64s.InterleaveLo, archsimd.Uint64s.Store, interleaveSlice[uint64](0, false))
    79  }
    80  
    81  func TestInterleaveHiSVE(t *testing.T) {
    82  	if !archsimd.ARM64.SVE() {
    83  		t.Skip("no SVE")
    84  	}
    85  	testSVEShuffle2(t, int8s, 1, archsimd.Int8s{}.Len(), archsimd.LoadInt8s, archsimd.Int8s.InterleaveHi, archsimd.Int8s.Store, interleaveSlice[int8](0, true))
    86  	testSVEShuffle2(t, int16s, 2, archsimd.Int16s{}.Len(), archsimd.LoadInt16s, archsimd.Int16s.InterleaveHi, archsimd.Int16s.Store, interleaveSlice[int16](0, true))
    87  	testSVEShuffle2(t, int32s, 4, archsimd.Int32s{}.Len(), archsimd.LoadInt32s, archsimd.Int32s.InterleaveHi, archsimd.Int32s.Store, interleaveSlice[int32](0, true))
    88  	testSVEShuffle2(t, int64s, 8, archsimd.Int64s{}.Len(), archsimd.LoadInt64s, archsimd.Int64s.InterleaveHi, archsimd.Int64s.Store, interleaveSlice[int64](0, true))
    89  	testSVEShuffle2(t, uint8s, 1, archsimd.Uint8s{}.Len(), archsimd.LoadUint8s, archsimd.Uint8s.InterleaveHi, archsimd.Uint8s.Store, interleaveSlice[uint8](0, true))
    90  	testSVEShuffle2(t, uint16s, 2, archsimd.Uint16s{}.Len(), archsimd.LoadUint16s, archsimd.Uint16s.InterleaveHi, archsimd.Uint16s.Store, interleaveSlice[uint16](0, true))
    91  	testSVEShuffle2(t, uint32s, 4, archsimd.Uint32s{}.Len(), archsimd.LoadUint32s, archsimd.Uint32s.InterleaveHi, archsimd.Uint32s.Store, interleaveSlice[uint32](0, true))
    92  	testSVEShuffle2(t, uint64s, 8, archsimd.Uint64s{}.Len(), archsimd.LoadUint64s, archsimd.Uint64s.InterleaveHi, archsimd.Uint64s.Store, interleaveSlice[uint64](0, true))
    93  }
    94  
    95  func TestConcatEvenSVE(t *testing.T) {
    96  	if !archsimd.ARM64.SVE() {
    97  		t.Skip("no SVE")
    98  	}
    99  	testSVEShuffle2(t, int8s, 1, archsimd.Int8s{}.Len(), archsimd.LoadInt8s, archsimd.Int8s.ConcatEven, archsimd.Int8s.Store, deinterleaveSlice[int8](0, false))
   100  	testSVEShuffle2(t, int16s, 2, archsimd.Int16s{}.Len(), archsimd.LoadInt16s, archsimd.Int16s.ConcatEven, archsimd.Int16s.Store, deinterleaveSlice[int16](0, false))
   101  	testSVEShuffle2(t, int32s, 4, archsimd.Int32s{}.Len(), archsimd.LoadInt32s, archsimd.Int32s.ConcatEven, archsimd.Int32s.Store, deinterleaveSlice[int32](0, false))
   102  	testSVEShuffle2(t, int64s, 8, archsimd.Int64s{}.Len(), archsimd.LoadInt64s, archsimd.Int64s.ConcatEven, archsimd.Int64s.Store, deinterleaveSlice[int64](0, false))
   103  	testSVEShuffle2(t, uint8s, 1, archsimd.Uint8s{}.Len(), archsimd.LoadUint8s, archsimd.Uint8s.ConcatEven, archsimd.Uint8s.Store, deinterleaveSlice[uint8](0, false))
   104  	testSVEShuffle2(t, uint16s, 2, archsimd.Uint16s{}.Len(), archsimd.LoadUint16s, archsimd.Uint16s.ConcatEven, archsimd.Uint16s.Store, deinterleaveSlice[uint16](0, false))
   105  	testSVEShuffle2(t, uint32s, 4, archsimd.Uint32s{}.Len(), archsimd.LoadUint32s, archsimd.Uint32s.ConcatEven, archsimd.Uint32s.Store, deinterleaveSlice[uint32](0, false))
   106  	testSVEShuffle2(t, uint64s, 8, archsimd.Uint64s{}.Len(), archsimd.LoadUint64s, archsimd.Uint64s.ConcatEven, archsimd.Uint64s.Store, deinterleaveSlice[uint64](0, false))
   107  }
   108  
   109  func TestConcatOddSVE(t *testing.T) {
   110  	if !archsimd.ARM64.SVE() {
   111  		t.Skip("no SVE")
   112  	}
   113  	testSVEShuffle2(t, int8s, 1, archsimd.Int8s{}.Len(), archsimd.LoadInt8s, archsimd.Int8s.ConcatOdd, archsimd.Int8s.Store, deinterleaveSlice[int8](0, true))
   114  	testSVEShuffle2(t, int16s, 2, archsimd.Int16s{}.Len(), archsimd.LoadInt16s, archsimd.Int16s.ConcatOdd, archsimd.Int16s.Store, deinterleaveSlice[int16](0, true))
   115  	testSVEShuffle2(t, int32s, 4, archsimd.Int32s{}.Len(), archsimd.LoadInt32s, archsimd.Int32s.ConcatOdd, archsimd.Int32s.Store, deinterleaveSlice[int32](0, true))
   116  	testSVEShuffle2(t, int64s, 8, archsimd.Int64s{}.Len(), archsimd.LoadInt64s, archsimd.Int64s.ConcatOdd, archsimd.Int64s.Store, deinterleaveSlice[int64](0, true))
   117  	testSVEShuffle2(t, uint8s, 1, archsimd.Uint8s{}.Len(), archsimd.LoadUint8s, archsimd.Uint8s.ConcatOdd, archsimd.Uint8s.Store, deinterleaveSlice[uint8](0, true))
   118  	testSVEShuffle2(t, uint16s, 2, archsimd.Uint16s{}.Len(), archsimd.LoadUint16s, archsimd.Uint16s.ConcatOdd, archsimd.Uint16s.Store, deinterleaveSlice[uint16](0, true))
   119  	testSVEShuffle2(t, uint32s, 4, archsimd.Uint32s{}.Len(), archsimd.LoadUint32s, archsimd.Uint32s.ConcatOdd, archsimd.Uint32s.Store, deinterleaveSlice[uint32](0, true))
   120  	testSVEShuffle2(t, uint64s, 8, archsimd.Uint64s{}.Len(), archsimd.LoadUint64s, archsimd.Uint64s.ConcatOdd, archsimd.Uint64s.Store, deinterleaveSlice[uint64](0, true))
   121  }
   122  

View as plain text