Source file src/simd/archsimd/internal/simd_test/shift_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  package simd_test
     8  
     9  import (
    10  	"math"
    11  	"simd/archsimd"
    12  	"testing"
    13  )
    14  
    15  type sveShiftCase[V any] struct {
    16  	shift uint64
    17  	f     func(V) V // x.ShiftAllLeft(shift) with shift a constant
    18  }
    19  
    20  // testSVEShiftAllLeft checks ShiftAllLeft by every amount in amounts, passed
    21  // as a variable, and by the constant amounts in consts, against Go's <<.
    22  func testSVEShiftAllLeft[T int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64, V any](
    23  	t *testing.T, name string, n int, load func([]T) V, store func(V, []T),
    24  	shift func(V, uint64) V, consts []sveShiftCase[V]) {
    25  	t.Helper()
    26  	xs := make([]T, n)
    27  	for i := range xs {
    28  		xs[i] = T(i*37 - 5) // mixes signs and high bits
    29  	}
    30  	got := make([]T, n)
    31  	check := func(s uint64, how string) {
    32  		t.Helper()
    33  		for i, x := range xs {
    34  			if want := x << s; got[i] != want {
    35  				t.Errorf("%s.ShiftAllLeft(%d) %s: lane %d = %v, want %v", name, s, how, i, got[i], want)
    36  				return
    37  			}
    38  		}
    39  	}
    40  	for _, s := range []uint64{0, 1, 3, 7, 8, 15, 16, 31, 32, 63, 64, 65, 255, 256, 1 << 40, math.MaxUint64} {
    41  		store(shift(load(xs), s), got)
    42  		check(s, "by variable")
    43  	}
    44  	for _, c := range consts {
    45  		store(c.f(load(xs)), got)
    46  		check(c.shift, "by constant")
    47  	}
    48  }
    49  
    50  func TestShiftAllLeftSVE(t *testing.T) {
    51  	if !archsimd.ARM64.SVE() {
    52  		t.Skip("no SVE")
    53  	}
    54  	testSVEShiftAllLeft(t, "Int8s", archsimd.Int8s{}.Len(), archsimd.LoadInt8s, archsimd.Int8s.Store, archsimd.Int8s.ShiftAllLeft,
    55  		[]sveShiftCase[archsimd.Int8s]{
    56  			{3, func(x archsimd.Int8s) archsimd.Int8s { return x.ShiftAllLeft(3) }},
    57  			{7, func(x archsimd.Int8s) archsimd.Int8s { return x.ShiftAllLeft(7) }},
    58  			{8, func(x archsimd.Int8s) archsimd.Int8s { return x.ShiftAllLeft(8) }},
    59  		})
    60  	testSVEShiftAllLeft(t, "Uint8s", archsimd.Uint8s{}.Len(), archsimd.LoadUint8s, archsimd.Uint8s.Store, archsimd.Uint8s.ShiftAllLeft,
    61  		[]sveShiftCase[archsimd.Uint8s]{
    62  			{1, func(x archsimd.Uint8s) archsimd.Uint8s { return x.ShiftAllLeft(1) }},
    63  			{200, func(x archsimd.Uint8s) archsimd.Uint8s { return x.ShiftAllLeft(200) }},
    64  		})
    65  	testSVEShiftAllLeft(t, "Int16s", archsimd.Int16s{}.Len(), archsimd.LoadInt16s, archsimd.Int16s.Store, archsimd.Int16s.ShiftAllLeft,
    66  		[]sveShiftCase[archsimd.Int16s]{
    67  			{15, func(x archsimd.Int16s) archsimd.Int16s { return x.ShiftAllLeft(15) }},
    68  			{16, func(x archsimd.Int16s) archsimd.Int16s { return x.ShiftAllLeft(16) }},
    69  		})
    70  	testSVEShiftAllLeft(t, "Uint16s", archsimd.Uint16s{}.Len(), archsimd.LoadUint16s, archsimd.Uint16s.Store, archsimd.Uint16s.ShiftAllLeft,
    71  		[]sveShiftCase[archsimd.Uint16s]{
    72  			{4, func(x archsimd.Uint16s) archsimd.Uint16s { return x.ShiftAllLeft(4) }},
    73  		})
    74  	testSVEShiftAllLeft(t, "Int32s", archsimd.Int32s{}.Len(), archsimd.LoadInt32s, archsimd.Int32s.Store, archsimd.Int32s.ShiftAllLeft,
    75  		[]sveShiftCase[archsimd.Int32s]{
    76  			{23, func(x archsimd.Int32s) archsimd.Int32s { return x.ShiftAllLeft(23) }},
    77  			{31, func(x archsimd.Int32s) archsimd.Int32s { return x.ShiftAllLeft(31) }},
    78  			{32, func(x archsimd.Int32s) archsimd.Int32s { return x.ShiftAllLeft(32) }},
    79  		})
    80  	testSVEShiftAllLeft(t, "Uint32s", archsimd.Uint32s{}.Len(), archsimd.LoadUint32s, archsimd.Uint32s.Store, archsimd.Uint32s.ShiftAllLeft,
    81  		[]sveShiftCase[archsimd.Uint32s]{
    82  			{0, func(x archsimd.Uint32s) archsimd.Uint32s { return x.ShiftAllLeft(0) }},
    83  		})
    84  	testSVEShiftAllLeft(t, "Int64s", archsimd.Int64s{}.Len(), archsimd.LoadInt64s, archsimd.Int64s.Store, archsimd.Int64s.ShiftAllLeft,
    85  		[]sveShiftCase[archsimd.Int64s]{
    86  			{52, func(x archsimd.Int64s) archsimd.Int64s { return x.ShiftAllLeft(52) }},
    87  			{63, func(x archsimd.Int64s) archsimd.Int64s { return x.ShiftAllLeft(63) }},
    88  			{64, func(x archsimd.Int64s) archsimd.Int64s { return x.ShiftAllLeft(64) }},
    89  		})
    90  	testSVEShiftAllLeft(t, "Uint64s", archsimd.Uint64s{}.Len(), archsimd.LoadUint64s, archsimd.Uint64s.Store, archsimd.Uint64s.ShiftAllLeft,
    91  		[]sveShiftCase[archsimd.Uint64s]{
    92  			{33, func(x archsimd.Uint64s) archsimd.Uint64s { return x.ShiftAllLeft(33) }},
    93  		})
    94  }
    95  

View as plain text