api/go1.26.txt | 5 ----- lib/fips140/fips140.sum | 1 + lib/time/update.bash | 4 ++-- src/archive/tar/reader_test.go | 30 +++++++++++++++++++++--------- src/archive/tar/testdata/gnu-sparse-big.tar.base64 | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/archive/tar/testdata/neg-size.tar.base64 | 9 +++++++++ src/archive/tar/testdata/pax-sparse-big.tar.base64 | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/archive/tar/testdata/writer-big-long.tar.base64 | 27 +++++++++++++++++++++++++++ src/archive/tar/writer_test.go | 28 +++++++++++++++++++++------- src/cmd/cgo/doc.go | 4 ++-- src/cmd/cgo/internal/test/cgo_test.go | 194 +++++++++++++++++++++++++++-------------------------- src/cmd/cgo/internal/test/test.go | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/cgo/internal/test/testx.go | 9 +++++++++ src/cmd/compile/abi-internal.md | 6 ++---- src/cmd/compile/internal/amd64/simdssa.go | 3 +++ src/cmd/compile/internal/amd64/ssa.go | 40 ++++++++++------------------------------ src/cmd/compile/internal/inline/inl.go | 2 +- src/cmd/compile/internal/inline/inlheur/analyze_func_params.go | 6 +++--- src/cmd/compile/internal/ssa/_gen/AMD64Ops.go | 9 +++++++-- src/cmd/compile/internal/ssa/_gen/simdAMD64.rules | 3 +++ src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go | 3 +++ src/cmd/compile/internal/ssa/_gen/simdgenericOps.go | 3 +++ src/cmd/compile/internal/ssa/opGen.go | 87 +++++++++++++++++++++++++++++++++++++++++++++++------ src/cmd/compile/internal/ssa/rewriteAMD64.go | 9 +++++++++ src/cmd/compile/internal/ssagen/intrinsics.go | 32 ++++++++++++++++++++++---------- src/cmd/compile/internal/ssagen/intrinsics_test.go | 4 ++-- src/cmd/compile/internal/ssagen/simdintrinsics.go | 29 ++++++++++++++++------------- src/cmd/compile/internal/test/testdata/arith_test.go | 4 ++-- src/cmd/compile/internal/types/size.go | 8 +------- src/cmd/compile/internal/types2/cycles.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/compile/internal/types2/expr.go | 9 +++------ src/cmd/compile/internal/types2/named.go | 25 +++++++++++++++++-------- src/cmd/compile/internal/types2/sizeof_test.go | 2 +- src/cmd/compile/internal/types2/stdlib_test.go | 4 ++-- src/cmd/dist/test.go | 11 ++++++++++- src/cmd/go.mod | 8 ++++---- src/cmd/go.sum | 16 ++++++++-------- src/cmd/go/go_test.go | 101 ----------------------------------------------------- src/cmd/go/internal/doc/doc_test.go | 29 +++++++++++++++++++++++++++++ src/cmd/go/internal/doc/pkg.go | 9 +++++---- src/cmd/go/internal/doc/testdata/pkg.go | 13 +++++++++++++ src/cmd/go/internal/generate/generate_test.go | 2 +- src/cmd/go/internal/vet/vet.go | 9 +++++++++ src/cmd/go/testdata/script/fix_vendor.txt | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/cmd/go/testdata/script/list_template_context_function.txt | 15 +++++++++++++++ src/cmd/go/testdata/script/list_test.txt | 33 +++++++++++++++++++++++++++++++++ src/cmd/go/testdata/script/list_toolexec_stderr_issue22588.txt | 11 +++++++++++ src/cmd/go/testdata/script/test_main_compiler_flags.txt | 22 ++++++++++++++++++++++ src/cmd/go/testdata/script/vet_asm.txt | 1 + src/cmd/link/dwarf_test.go | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cmd/link/internal/ld/dwarf.go | 2 +- src/cmd/link/internal/ld/fips140.go | 2 +- src/cmd/link/internal/ld/lib.go | 4 +++- src/cmd/link/internal/ld/pcln.go | 34 +++++++++++++++++++++++----------- src/cmd/link/internal/ld/symtab.go | 2 ++ src/cmd/link/internal/ld/xcoff.go | 12 +++++++++--- src/cmd/link/internal/loader/loader.go | 31 ++++++++++++++++++++++++++----- src/cmd/link/internal/loader/loader_test.go | 2 +- src/cmd/link/internal/x86/asm.go | 3 +++ src/cmd/link/link_test.go | 93 ++++++++++++++++++++++++++++------------------------- src/cmd/nm/nm_test.go | 5 ----- src/cmd/vendor/golang.org/x/sync/errgroup/errgroup.go | 4 ++-- src/cmd/vendor/modules.txt | 8 ++++---- src/compress/bzip2/bzip2_test.go | 12 +++++++++++- src/compress/bzip2/testdata/fail-issue5747.bz2.base64 | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/crypto/cipher/gcm_fips140v2.0_test.go | 14 ++++++++++++++ src/crypto/cipher/gcm_test.go | 15 ++++++++++++++- src/crypto/ecdh/ecdh_test.go | 11 ++++------- src/crypto/fips140/enforcement_test.go | 93 ++++++++++++++++++++++++++++++++++++----------------- src/crypto/fips140/testdata/enforcement_test.go | 65 ----------------------------------------------------- src/crypto/hpke/aead.go | 9 --------- src/crypto/hpke/aead_fipsv1.0.go | 20 ++++++++++++++++++++ src/crypto/hpke/aead_fipsv2.0.go | 21 +++++++++++++++++++++ src/crypto/hpke/hpke_test.go | 177 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/crypto/hpke/kem.go | 3 ++- src/crypto/hpke/pq.go | 31 +++++++++++++++++++++++++------ src/crypto/internal/cryptotest/fetchmodule.go | 7 +++---- src/crypto/internal/fips140/aes/gcm/gcm_nonces.go | 100 +++++++++++++++++++++++++++++++---------------------- src/crypto/internal/fips140deps/fipsdeps_test.go | 2 +- src/crypto/internal/fips140test/acvp_test.go | 23 ++++++++++------------- src/crypto/internal/fips140test/cast_test.go | 15 +++++++-------- src/crypto/internal/fips140test/check_test.go | 3 +-- src/crypto/internal/sysrand/rand_linux_test.go | 5 +++-- src/crypto/internal/sysrand/rand_test.go | 3 +-- src/crypto/mlkem/mlkemtest/mlkemtest.go | 7 +++++++ src/crypto/purego_test.go | 10 +++++----- src/crypto/rand/rand_test.go | 2 +- src/crypto/subtle/dit.go | 29 +++++++++++++++++++++-------- src/crypto/subtle/dit_test.go | 22 ++++++++++++++++++++++ src/crypto/tls/bogo_shim_test.go | 6 +----- src/crypto/tls/link_test.go | 13 +++++-------- src/crypto/x509/bettertls_test.go | 8 ++------ src/crypto/x509/name_constraints_test.go | 11 ++++------- src/crypto/x509/root_linux_test.go | 13 ++++++------- src/crypto/x509/x509_test.go | 5 +---- src/database/sql/driver/driver.go | 12 ------------ src/database/sql/sql.go | 11 +---------- src/database/sql/sql_test.go | 96 ----------------------------------------------------- src/encoding/json/jsontext/decode.go | 8 ++++---- src/encoding/json/jsontext/decode_test.go | 4 ++-- src/encoding/json/jsontext/encode.go | 6 +++--- src/encoding/json/jsontext/token.go | 63 +++++++++++++++++++++++++++++++++++++---------------- src/encoding/json/jsontext/value.go | 2 +- src/encoding/json/stream_test.go | 12 ++++++++++++ src/encoding/json/v2_stream.go | 18 +++++++++++++++++- src/encoding/json/v2_stream_test.go | 12 ++++++++++++ src/go.mod | 6 +++--- src/go.sum | 12 ++++++------ src/go/build/deps_test.go | 4 ++-- src/go/doc/example.go | 3 +-- src/go/doc/testdata/examples/major_version.go | 14 ++++++++++++++ src/go/doc/testdata/examples/major_version.golden | 15 +++++++++++++++ src/go/types/cycles.go | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/go/types/expr.go | 9 +++------ src/go/types/named.go | 25 +++++++++++++++++-------- src/go/types/sizeof_test.go | 2 +- src/go/types/stdlib_test.go | 4 ++-- src/internal/buildcfg/cfg.go | 34 ++++++++++++++++++++++------------ src/internal/runtime/gc/scan/filter_amd64.s | 2 ++ src/internal/trace/reader_test.go | 1 + src/internal/trace/summary.go | 43 +++++++++++++++++++++++++++++++++++++------ src/internal/trace/summary_test.go | 5 +++++ src/internal/trace/trace_test.go | 3 +++ src/internal/types/testdata/fixedbugs/issue52915.go | 4 +--- src/internal/types/testdata/fixedbugs/issue75918.go | 13 +++++++++++++ src/internal/types/testdata/fixedbugs/issue76478.go | 25 +++++++++++++++++++++++++ src/runtime/asm_amd64.s | 10 ---------- src/runtime/asm_ppc64x.s | 7 ++++--- src/runtime/cgocall.go | 33 ++++++++++++++++++++++++++++++--- src/runtime/crash_test.go | 123 +++++++++++++++++++++++++++-------------------------- src/runtime/dit.go | 26 ++++++++++++++++++++++++++ src/runtime/metrics_cgo_test.go | 32 ++++++++++++++++++++++++++++++++ src/runtime/metrics_test.go | 15 --------------- src/runtime/os_wasm.go | 2 ++ src/runtime/pprof/pprof_test.go | 132 ++++++++++++++++++++++++++++++----------------------- src/runtime/proc.go | 34 +++++++++++++++++++++++++++++----- src/runtime/profbuf_test.go | 16 ++++++++++------ src/runtime/race_amd64.s | 5 ----- src/runtime/runtime2.go | 2 ++ src/runtime/secret/export.go | 2 ++ src/runtime/secret/secret.go | 2 +- src/runtime/secret/stubs_noasm.go | 2 +- src/runtime/sizeof_test.go | 2 +- src/runtime/stack.go | 8 +++++++- src/runtime/stkframe.go | 4 ++-- src/runtime/stubs_386.go | 2 ++ src/runtime/stubs_arm.go | 2 ++ src/runtime/stubs_loong64.go | 2 ++ src/runtime/stubs_mips64x.go | 2 ++ src/runtime/stubs_mipsx.go | 2 ++ src/runtime/stubs_ppc64x.go | 2 ++ src/runtime/stubs_riscv64.go | 2 ++ src/runtime/stubs_s390x.go | 2 ++ src/runtime/symtab.go | 1 + src/runtime/sys_darwin_amd64.s | 5 ----- src/runtime/sys_dragonfly_amd64.s | 5 ----- src/runtime/sys_freebsd_amd64.s | 10 ---------- src/runtime/sys_linux_amd64.s | 10 ---------- src/runtime/sys_netbsd_amd64.s | 5 ----- src/runtime/sys_openbsd_amd64.s | 5 ----- src/runtime/sys_windows_amd64.s | 5 ----- src/runtime/testdata/testprogcgo/notingo.go | 5 ++--- src/runtime/trace.go | 73 +++++++++++++++++++++++------------------------------ src/runtime/trace/subscribe_test.go | 35 +++++++++++++++++++++++------------ src/simd/_gen/go.mod => src/simd/archsimd/_gen/go.mod | 2 +- src/simd/_gen/go.sum => src/simd/archsimd/_gen/go.sum | 0 src/simd/_gen/main.go => src/simd/archsimd/_gen/main.go | 0 src/simd/_gen/simdgen/.gitignore | 3 --- src/simd/_gen/simdgen/categories.yaml => src/simd/archsimd/_gen/simdgen/categories.yaml | 0 src/simd/_gen/simdgen/etetest.sh | 48 ------------------------------------------------ src/simd/_gen/simdgen/gen_simdGenericOps.go => src/simd/archsimd/_gen/simdgen/gen_simdGenericOps.go | 0 src/simd/_gen/simdgen/gen_simdIntrinsics.go => src/simd/archsimd/_gen/simdgen/gen_simdIntrinsics.go | 2 +- src/simd/_gen/simdgen/gen_simdMachineOps.go => src/simd/archsimd/_gen/simdgen/gen_simdMachineOps.go | 0 src/simd/_gen/simdgen/gen_simdTypes.go => src/simd/archsimd/_gen/simdgen/gen_simdTypes.go | 6 +++--- src/simd/_gen/simdgen/gen_simdrules.go => src/simd/archsimd/_gen/simdgen/gen_simdrules.go | 0 src/simd/_gen/simdgen/gen_simdssa.go => src/simd/archsimd/_gen/simdgen/gen_simdssa.go | 0 src/simd/_gen/simdgen/gen_utility.go => src/simd/archsimd/_gen/simdgen/gen_utility.go | 0 src/simd/_gen/simdgen/go.yaml => src/simd/archsimd/_gen/simdgen/go.yaml | 0 src/simd/_gen/simdgen/godefs.go => src/simd/archsimd/_gen/simdgen/godefs.go | 2 +- src/simd/_gen/simdgen/main.go => src/simd/archsimd/_gen/simdgen/main.go | 4 ++-- src/simd/_gen/simdgen/ops/AddSub/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/AddSub/categories.yaml | 0 src/simd/_gen/simdgen/ops/AddSub/go.yaml => src/simd/archsimd/_gen/simdgen/ops/AddSub/go.yaml | 0 src/simd/_gen/simdgen/ops/BitwiseLogic/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/categories.yaml | 0 src/simd/_gen/simdgen/ops/BitwiseLogic/go.yaml => src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/go.yaml | 0 src/simd/_gen/simdgen/ops/Compares/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/Compares/categories.yaml | 0 src/simd/_gen/simdgen/ops/Compares/go.yaml => src/simd/archsimd/_gen/simdgen/ops/Compares/go.yaml | 0 src/simd/_gen/simdgen/ops/Converts/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/Converts/categories.yaml | 0 src/simd/_gen/simdgen/ops/Converts/go.yaml => src/simd/archsimd/_gen/simdgen/ops/Converts/go.yaml | 0 src/simd/_gen/simdgen/ops/FPonlyArith/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/FPonlyArith/categories.yaml | 0 src/simd/_gen/simdgen/ops/FPonlyArith/go.yaml => src/simd/archsimd/_gen/simdgen/ops/FPonlyArith/go.yaml | 0 src/simd/_gen/simdgen/ops/GaloisField/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/GaloisField/categories.yaml | 2 ++ src/simd/_gen/simdgen/ops/GaloisField/go.yaml | 32 -------------------------------- src/simd/_gen/simdgen/ops/IntOnlyArith/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/IntOnlyArith/categories.yaml | 0 src/simd/_gen/simdgen/ops/IntOnlyArith/go.yaml => src/simd/archsimd/_gen/simdgen/ops/IntOnlyArith/go.yaml | 0 src/simd/_gen/simdgen/ops/MLOps/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/MLOps/categories.yaml | 0 src/simd/_gen/simdgen/ops/MLOps/go.yaml => src/simd/archsimd/_gen/simdgen/ops/MLOps/go.yaml | 0 src/simd/_gen/simdgen/ops/MinMax/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/MinMax/categories.yaml | 0 src/simd/_gen/simdgen/ops/MinMax/go.yaml => src/simd/archsimd/_gen/simdgen/ops/MinMax/go.yaml | 0 src/simd/_gen/simdgen/ops/Moves/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/Moves/categories.yaml | 0 src/simd/_gen/simdgen/ops/Moves/go.yaml => src/simd/archsimd/_gen/simdgen/ops/Moves/go.yaml | 0 src/simd/_gen/simdgen/ops/Mul/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/Mul/categories.yaml | 0 src/simd/_gen/simdgen/ops/Mul/go.yaml => src/simd/archsimd/_gen/simdgen/ops/Mul/go.yaml | 0 src/simd/_gen/simdgen/ops/Others/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/Others/categories.yaml | 0 src/simd/_gen/simdgen/ops/Others/go.yaml => src/simd/archsimd/_gen/simdgen/ops/Others/go.yaml | 0 src/simd/_gen/simdgen/ops/ShiftRotate/categories.yaml => src/simd/archsimd/_gen/simdgen/ops/ShiftRotate/categories.yaml | 0 src/simd/_gen/simdgen/ops/ShiftRotate/go.yaml => src/simd/archsimd/_gen/simdgen/ops/ShiftRotate/go.yaml | 0 src/simd/_gen/simdgen/pprint.go => src/simd/archsimd/_gen/simdgen/pprint.go | 0 src/simd/_gen/simdgen/sort_test.go => src/simd/archsimd/_gen/simdgen/sort_test.go | 0 src/simd/_gen/simdgen/types.yaml => src/simd/archsimd/_gen/simdgen/types.yaml | 3 +++ src/simd/_gen/simdgen/xed.go => src/simd/archsimd/_gen/simdgen/xed.go | 17 +++++++++-------- src/simd/_gen/tmplgen/main.go => src/simd/archsimd/_gen/tmplgen/main.go | 102 +++++++++++++++++++++++++++--------------------------- src/simd/_gen/unify/closure.go => src/simd/archsimd/_gen/unify/closure.go | 0 src/simd/_gen/unify/domain.go => src/simd/archsimd/_gen/unify/domain.go | 0 src/simd/_gen/unify/dot.go => src/simd/archsimd/_gen/unify/dot.go | 0 src/simd/_gen/unify/env.go => src/simd/archsimd/_gen/unify/env.go | 0 src/simd/_gen/unify/html.go => src/simd/archsimd/_gen/unify/html.go | 0 src/simd/_gen/unify/pos.go => src/simd/archsimd/_gen/unify/pos.go | 0 src/simd/_gen/unify/testdata/stress.yaml => src/simd/archsimd/_gen/unify/testdata/stress.yaml | 0 src/simd/_gen/unify/testdata/unify.yaml => src/simd/archsimd/_gen/unify/testdata/unify.yaml | 0 src/simd/_gen/unify/testdata/vars.yaml => src/simd/archsimd/_gen/unify/testdata/vars.yaml | 0 src/simd/_gen/unify/trace.go => src/simd/archsimd/_gen/unify/trace.go | 0 src/simd/_gen/unify/unify.go => src/simd/archsimd/_gen/unify/unify.go | 0 src/simd/_gen/unify/unify_test.go => src/simd/archsimd/_gen/unify/unify_test.go | 0 src/simd/_gen/unify/value.go => src/simd/archsimd/_gen/unify/value.go | 0 src/simd/_gen/unify/value_test.go => src/simd/archsimd/_gen/unify/value_test.go | 0 src/simd/_gen/unify/yaml.go => src/simd/archsimd/_gen/unify/yaml.go | 0 src/simd/_gen/unify/yaml_test.go => src/simd/archsimd/_gen/unify/yaml_test.go | 0 src/simd/archsimd/_gen/simdgen/etetest.sh | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/_gen/simdgen/ops/GaloisField/go.yaml | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/doc.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/binary_test.go | 361 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/compare_test.go | 265 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/ternary_test.go | 23 +++++++++++++++++++++++ src/simd/archsimd/internal/simd_test/unary_test.go | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/archsimd/pkginternal_test.go | 268 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/simd/compare_gen_amd64.go => src/simd/archsimd/compare_gen_amd64.go | 218 +++++++++++++++++++++++++++--------------------------- src/simd/cpu.go => src/simd/archsimd/cpu.go | 10 +++++++++- src/simd/dummy.s => src/simd/archsimd/dummy.s | 0 src/simd/export_test.go => src/simd/archsimd/export_test.go | 2 +- src/simd/extra_amd64.go => src/simd/archsimd/extra_amd64.go | 2 +- src/simd/generate.go => src/simd/archsimd/generate.go | 2 +- src/simd/internal/simd_test/binary_helpers_test.go => src/simd/archsimd/internal/simd_test/binary_helpers_test.go | 182 +++++++++++++++++++++++++++--------------------------- src/simd/internal/simd_test/binary_test.go | 361 ----------------------------------------------------- src/simd/internal/simd_test/compare_helpers_test.go => src/simd/archsimd/internal/simd_test/compare_helpers_test.go | 242 +++++++++++++++++++++++++++--------------------------- src/simd/internal/simd_test/compare_test.go | 265 ----------------------------------------------------- src/simd/internal/simd_test/comparemasked_helpers_test.go => src/simd/archsimd/internal/simd_test/comparemasked_helpers_test.go | 302 +++++++++++++++++++++++++++--------------------------- src/simd/internal/simd_test/generate.go => src/simd/archsimd/internal/simd_test/generate.go | 0 src/simd/internal/simd_test/helpers_test.go => src/simd/archsimd/internal/simd_test/helpers_test.go | 2 +- src/simd/internal/simd_test/simd_test.go => src/simd/archsimd/internal/simd_test/simd_test.go | 410 +++++++++++++++++++++++++---------------------------- src/simd/internal/simd_test/simulation_helpers_test.go => src/simd/archsimd/internal/simd_test/simulation_helpers_test.go | 0 src/simd/internal/simd_test/slicepart_test.go => src/simd/archsimd/internal/simd_test/slicepart_test.go | 38 +++++++++++++++++++------------------- src/simd/internal/simd_test/ternary_helpers_test.go => src/simd/archsimd/internal/simd_test/ternary_helpers_test.go | 266 +++++++++++++++++++++++++++--------------------------- src/simd/internal/simd_test/ternary_test.go | 23 ----------------------- src/simd/internal/simd_test/transpose_test.go => src/simd/archsimd/internal/simd_test/transpose_test.go | 104 +++++++++++++++++++++++++++--------------------------- src/simd/internal/simd_test/unary_helpers_test.go => src/simd/archsimd/internal/simd_test/unary_helpers_test.go | 390 +++++++++++++++++++++++++++--------------------------- src/simd/internal/simd_test/unary_test.go | 137 ----------------------------------------------------- src/simd/internal/test_helpers/checkslices.go => src/simd/archsimd/internal/test_helpers/checkslices.go | 0 src/simd/maskmerge_gen_amd64.go => src/simd/archsimd/maskmerge_gen_amd64.go | 102 +++++++++++++++++++++++++++--------------------------- src/simd/ops_amd64.go => src/simd/archsimd/ops_amd64.go | 50 +++++++++++++++++++++++++------------------------- src/simd/ops_internal_amd64.go => src/simd/archsimd/ops_internal_amd64.go | 40 +++++++++++++++++++++++++++++++++++++++- src/simd/other_gen_amd64.go => src/simd/archsimd/other_gen_amd64.go | 140 ++++++++++------------------------------------------- src/simd/pkginternal_test.go | 258 ----------------------------------------------------- src/simd/shuffles_amd64.go => src/simd/archsimd/shuffles_amd64.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/simd/slice_gen_amd64.go => src/simd/archsimd/slice_gen_amd64.go | 2 +- src/simd/slicepart_amd64.go => src/simd/archsimd/slicepart_amd64.go | 2 +- src/simd/string.go => src/simd/archsimd/string.go | 2 +- src/simd/testdata/sample.go => src/simd/archsimd/testdata/sample.go | 22 +++++++++++----------- src/simd/types_amd64.go => src/simd/archsimd/types_amd64.go | 2 +- src/simd/unsafe_helpers.go => src/simd/archsimd/unsafe_helpers.go | 2 +- src/text/template/exec_test.go | 7 ++++++- src/text/template/funcs.go | 4 ++++ src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go | 3 +++ src/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_compat.go | 9 +++++++++ src/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_go1.26.go | 11 +++++++++++ src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go | 3 +++ src/vendor/modules.txt | 6 +++--- src/weak/pointer_test.go | 2 +- test/codegen/arithmetic.go | 6 ++++++ test/codegen/simd.go | 42 +++++++++++++++++++++--------------------- test/simd.go | 46 +++++++++++++++++++++++----------------------- test/simd/bug1.go | 26 +++++++++++++------------- test/simd/bug2.go | 8 ++++---- test/simd_inline.go | 4 ++-- diff --git a/api/go1.26.txt b/api/go1.26.txt index 87bcebd1af546883ff1278d24d3da8b32dd94fdf..0706895bbdfef45004a9b499bfe1cf33f46c2ab9 100644 --- a/api/go1.26.txt +++ b/api/go1.26.txt @@ -88,11 +88,6 @@ pkg crypto/x509, func OIDFromASN1OID(asn1.ObjectIdentifier) (OID, error) #75325 pkg crypto/x509, method (ExtKeyUsage) OID() OID #75325 pkg crypto/x509, method (ExtKeyUsage) String() string #56866 pkg crypto/x509, method (KeyUsage) String() string #56866 -pkg database/sql/driver, type RowsColumnScanner interface { Close, Columns, Next, ScanColumn } #67546 -pkg database/sql/driver, type RowsColumnScanner interface, Close() error #67546 -pkg database/sql/driver, type RowsColumnScanner interface, Columns() []string #67546 -pkg database/sql/driver, type RowsColumnScanner interface, Next([]Value) error #67546 -pkg database/sql/driver, type RowsColumnScanner interface, ScanColumn(interface{}, int) error #67546 pkg debug/elf, const R_LARCH_CALL36 = 110 #75562 pkg debug/elf, const R_LARCH_CALL36 R_LARCH #75562 pkg debug/elf, const R_LARCH_TLS_DESC32 = 13 #75562 diff --git a/lib/fips140/fips140.sum b/lib/fips140/fips140.sum index 703d1dc60e58ab7c960c15001d22d1247d6a727c..c4d185da73aa53be97130898c87a06216ad8acba 100644 --- a/lib/fips140/fips140.sum +++ b/lib/fips140/fips140.sum @@ -10,3 +10,4 @@ # # go test cmd/go/internal/fips140 -update # v1.0.0-c2097c7c.zip daf3614e0406f67ae6323c902db3f953a1effb199142362a039e7526dfb9368b +v1.1.0-rc1.zip ea94f8c3885294c9efe1bd8f9b6e86daeb25b6aff2aeb20707cd9a5101f6f54e diff --git a/lib/fips140/v1.1.0-rc1.zip b/lib/fips140/v1.1.0-rc1.zip new file mode 100644 index 0000000000000000000000000000000000000000..d4264bdb2e5b149bc47df0f51930ba23175aa1a5 Binary files /dev/null and b/lib/fips140/v1.1.0-rc1.zip differ diff --git a/lib/time/update.bash b/lib/time/update.bash index 66494752ea3c4b38efd04ad2994aeb24f8477a83..e43160cbda8bc4dee035fdf53c4507a9a045dc76 100755 --- a/lib/time/update.bash +++ b/lib/time/update.bash @@ -24,8 +24,8 @@ # If it prints "No updates needed.", then the generated files # in the CL match the update.bash in the CL. # Versions to use. -CODE=2025b -DATA=2025b +CODE=2025c +DATA=2025c set -e diff --git a/lib/time/zoneinfo.zip b/lib/time/zoneinfo.zip index b107695d1ef042e46600602da5954ce4891e2fdd..3e781165ca055c52b1df8576e910c263bb77e91d 100644 Binary files a/lib/time/zoneinfo.zip and b/lib/time/zoneinfo.zip differ diff --git a/src/archive/tar/reader_test.go b/src/archive/tar/reader_test.go index fca53dae741bd51c2e2f7b5b5cfb54335a38f0dc..de3d36530470d1142c0336aab4172512336a2c5b 100644 --- a/src/archive/tar/reader_test.go +++ b/src/archive/tar/reader_test.go @@ -10,6 +10,7 @@ "compress/bzip2" "errors" "fmt" "hash/crc32" + "internal/obscuretestdata" "io" "maps" "math" @@ -25,10 +26,11 @@ ) func TestReader(t *testing.T) { vectors := []struct { - file string // Test input file - headers []*Header // Expected output headers - chksums []string // CRC32 checksum of files, leave as nil if not checked - err error // Expected error to occur + file string // Test input file + obscured bool // Obscured with obscuretestdata package + headers []*Header // Expected output headers + chksums []string // CRC32 checksum of files, leave as nil if not checked + err error // Expected error to occur }{{ file: "testdata/gnu.tar", headers: []*Header{{ @@ -523,8 +525,9 @@ // of NUL-terminated C-strings. file: "testdata/pax-nul-path.tar", err: ErrHeader, }, { - file: "testdata/neg-size.tar", - err: ErrHeader, + file: "testdata/neg-size.tar.base64", + obscured: true, + err: ErrHeader, }, { file: "testdata/issue10968.tar", err: ErrHeader, @@ -629,15 +632,24 @@ err: errSparseTooLong, }} for _, v := range vectors { - t.Run(path.Base(v.file), func(t *testing.T) { - f, err := os.Open(v.file) + t.Run(strings.TrimSuffix(path.Base(v.file), ".base64"), func(t *testing.T) { + path := v.file + if v.obscured { + tf, err := obscuretestdata.DecodeToTempFile(path) + if err != nil { + t.Fatalf("obscuredtestdata.DecodeToTempFile(%s): %v", path, err) + } + path = tf + } + + f, err := os.Open(path) if err != nil { t.Fatalf("unexpected error: %v", err) } defer f.Close() var fr io.Reader = f - if strings.HasSuffix(v.file, ".bz2") { + if strings.HasSuffix(v.file, ".bz2") || strings.HasSuffix(v.file, ".bz2.base64") { fr = bzip2.NewReader(fr) } diff --git a/src/archive/tar/testdata/gnu-sparse-big.tar b/src/archive/tar/testdata/gnu-sparse-big.tar deleted file mode 100644 index 1a5cfc96d92983b42dab09b51bec236fe00d24c3..0000000000000000000000000000000000000000 Binary files a/src/archive/tar/testdata/gnu-sparse-big.tar and /dev/null differ diff --git a/src/archive/tar/testdata/gnu-sparse-big.tar.base64 b/src/archive/tar/testdata/gnu-sparse-big.tar.base64 new file mode 100644 index 0000000000000000000000000000000000000000..c25505083b1304f571f5614b90a2c917b9e6df22 --- /dev/null +++ b/src/archive/tar/testdata/gnu-sparse-big.tar.base64 @@ -0,0 +1,90 @@ +Z251LXNwYXJzZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAAMDAwMDAw +MAAwMDAwMDAwADAwMDAwMDA2MDAwADAwMDAwMDAwMDAwADAyMjIyNwAgUwAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhciAgAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAw +MDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAlQL4gAw +MDAwMDAwMTAwMACAAAAAAAAABKgXxgAwMDAwMDAwMTAwMACAAAAAAAAABvwjqgAwMDAwMDAwMTAw +MACAAAAAAAAACVAvjgAwMDAwMDAwMTAwMAABgAAAAAAAAA34R1gAAAAAAAAAAAAAAAAAAAAAAACA +AAAAAAAAC6Q7cgAwMDAwMDAwMTAwMACAAAAAAAAADfhHVgAwMDAwMDAwMTAwMAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1 +Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5AAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAADAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2 +Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAMDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3 +ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4 +OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5AAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAADAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5 +MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAMDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkw +MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= diff --git a/src/archive/tar/testdata/neg-size.tar b/src/archive/tar/testdata/neg-size.tar deleted file mode 100644 index 21edf38cc3c3d98c834d07b6d31e8325898ec492..0000000000000000000000000000000000000000 Binary files a/src/archive/tar/testdata/neg-size.tar and /dev/null differ diff --git a/src/archive/tar/testdata/neg-size.tar.base64 b/src/archive/tar/testdata/neg-size.tar.base64 new file mode 100644 index 0000000000000000000000000000000000000000..b7e26a05b1e1ce52b79fc8ab0f75e2dfa44e39a4 --- /dev/null +++ b/src/archive/tar/testdata/neg-size.tar.base64 @@ -0,0 +1,9 @@ +EwMwMBMDLTgyMTk1MDI5NnQTE4NzfINzEzAwcXfhZrsDMDAwAAAAEDAxMRNz9DEwMTAwdBMTg3N8 +g3NzADATc3yDc3P0eFMTc/QxMDEwMHQTE4NzfINzc/QwE3N8g3Nz9HFTMNR0MBMwMHEw9DAAAAAQ +MDGAABAwMTETc/QxMDH0MHQTMDBx1OFmuwMAAAD/gICAADExNTYyMQAgMBP///+AMTAwdHhTMDB0 +MBMwMHF3MDEwMTAwdBMTg3N8g3Nz9HhTMDB0MBMwMHF34Wa7AzAwMAAAABAwMTETc/QxMDEwMHQT +E4NzfINzc/QwE3N8g3Nz9HhTE3P0MTAxMDB0ExODc3yDc3MwMBNzfINzczB4UzAwdDATMDBxMDAA +gAAAEDAxc/QxMDEwMHQTAAAAIOFmuwMwNAAAABAwMTET////gDEwMHR4UzAwdDATMDBxd+FmuwMw +MDAAAAAQMDExE3ODc3P0eFMTc/QxMDEwMHQTE4NzfINzc/QzMTEwMzM2MjQ4NDYxMjgzODBzfINz +c/R4UzAwdDATMDBxMDAwAAAAEDAxAAAQMDExE3P0MTAxMDB0EzAwcdThZrsDMDQAAAAQg3N8g3Nz +9DATc3yDc3P0eFMwMHQwEzAwcTAwMAAAABAwMQAAEDAxMRNz9DEwMTAwdBMwMHgw4Wa7AwAAEDA= diff --git a/src/archive/tar/testdata/pax-sparse-big.tar b/src/archive/tar/testdata/pax-sparse-big.tar deleted file mode 100644 index 65d1f8eceb084955d03ef41f6efbbed0ab3ab07d..0000000000000000000000000000000000000000 Binary files a/src/archive/tar/testdata/pax-sparse-big.tar and /dev/null differ diff --git a/src/archive/tar/testdata/pax-sparse-big.tar.base64 b/src/archive/tar/testdata/pax-sparse-big.tar.base64 new file mode 100644 index 0000000000000000000000000000000000000000..640ef32159fd4825f7afc6324cd01966da5011c2 --- /dev/null +++ b/src/archive/tar/testdata/pax-sparse-big.tar.base64 @@ -0,0 +1,108 @@ +UGF4SGVhZGVycy4wL3BheC1zcGFyc2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAAMDAwMDAw +MAAwMDAwMDAwADAwMDAwMDAwMTcyADAwMDAwMDAwMDAwADAxMjIyNwAgeAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy +MiBHTlUuc3BhcnNlLm1ham9yPTEKMjIgR05VLnNwYXJzZS5taW5vcj0wCjMwIEdOVS5zcGFyc2Uu +bmFtZT1wYXgtc3BhcnNlCjM1IEdOVS5zcGFyc2UucmVhbHNpemU9NjAwMDAwMDAwMDAKMTMgc2l6 +ZT0zNTg0CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEdO +VVNwYXJzZUZpbGUuMC9wYXgtc3BhcnNlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAA +MDAwMDAwMAAwMDAwMDAwNzAwMAAwMDAwMDAwMDAwMAAwMTM3MzcAIDAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIAMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDAwMAAwMDAwMDAw +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANgo5 +OTk5OTk5NDg4CjUxMgoxOTk5OTk5OTQ4OAo1MTIKMjk5OTk5OTk0ODgKNTEyCjM5OTk5OTk5NDg4 +CjUxMgo0OTk5OTk5OTQ4OAo1MTIKNTk5OTk5OTk0ODgKNTEyCgAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAMDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3 +ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4 +OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5AAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAADAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5 +MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAMDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkw +MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OQAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAx +MjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5AAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAADAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEy +MzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA diff --git a/src/archive/tar/testdata/writer-big-long.tar b/src/archive/tar/testdata/writer-big-long.tar deleted file mode 100644 index 09fc5dd3dd7fc5de3b6d22461fa23152fd499a41..0000000000000000000000000000000000000000 Binary files a/src/archive/tar/testdata/writer-big-long.tar and /dev/null differ diff --git a/src/archive/tar/testdata/writer-big-long.tar.base64 b/src/archive/tar/testdata/writer-big-long.tar.base64 new file mode 100644 index 0000000000000000000000000000000000000000..171d2870685f3926fd960b588b871b9fda11d8e6 --- /dev/null +++ b/src/archive/tar/testdata/writer-big-long.tar.base64 @@ -0,0 +1,27 @@ +bG9uZ25hbWUvbG9uZ25hbWUvbG9uZ25hbWUvbG9uZ25hbWUvbG9uZ25hbWUvbG9uZ25hbWUvbG9u +Z25hbWUvbG9uZ25hbWUvbG9uZ25hbWUvbG9uZ25hbWUvbG9uZ25hbWUvbDAwMDAwMDAAMDAwMDAw +MAAwMDAwMDAwADAwMDAwMDAwMjU2ADAwMDAwMDAwMDAwADAzMTQyMAAgeAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx +NTQgcGF0aD1sb25nbmFtZS9sb25nbmFtZS9sb25nbmFtZS9sb25nbmFtZS9sb25nbmFtZS9sb25n +bmFtZS9sb25nbmFtZS9sb25nbmFtZS9sb25nbmFtZS9sb25nbmFtZS9sb25nbmFtZS9sb25nbmFt +ZS9sb25nbmFtZS9sb25nbmFtZS9sb25nbmFtZS8xNmdpZy50eHQKMjAgc2l6ZT0xNzE3OTg2OTE4 +NAoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGxv +bmduYW1lL2xvbmduYW1lL2xvbmduYW1lL2xvbmduYW1lL2xvbmduYW1lL2xvbmduYW1lL2xvbmdu +YW1lL2xvbmduYW1lL2xvbmduYW1lL2xvbmduYW1lL2xvbmduYW1lL2wwMDAwNjQ0ADAwMDE3NTAA +MDAwMTc1MAAwMDAwMDAwMDAwMAAxMjMzMjc3MDUwNwAwMzY0NjIAIDAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIAMDBndWlsbGF1bWUAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAGd1aWxsYXVtZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDAwMAAwMDAwMDAw +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA diff --git a/src/archive/tar/writer_test.go b/src/archive/tar/writer_test.go index 9e484432ea90b67f1f044ac8e63e94d59d20a608..759000f6b9569a23001f4ba1e0d74383c03bb2c8 100644 --- a/src/archive/tar/writer_test.go +++ b/src/archive/tar/writer_test.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/hex" "errors" + "internal/obscuretestdata" "io" "io/fs" "maps" @@ -74,8 +75,9 @@ testFnc any // testHeader | testWrite | testReadFrom | testClose ) vectors := []struct { - file string // Optional filename of expected output - tests []testFnc + file string // Optional filename of expected output + obscured bool // Whether file is obscured + tests []testFnc }{{ // The writer test file was produced with this command: // tar (GNU tar) 1.26 @@ -151,7 +153,8 @@ // gnutar -xvf writer-big-long.tar // bsdtar -xvf writer-big-long.tar // // This file is in PAX format. - file: "testdata/writer-big-long.tar", + file: "testdata/writer-big-long.tar.base64", + obscured: true, tests: []testFnc{ testHeader{Header{ Typeflag: TypeReg, @@ -393,7 +396,8 @@ testWrite{strings.Repeat("\x00", 1000), 1000, nil}, testClose{}, }, }, { - file: "testdata/gnu-sparse-big.tar", + file: "testdata/gnu-sparse-big.tar.base64", + obscured: true, tests: []testFnc{ testHeader{Header{ Typeflag: TypeGNUSparse, @@ -425,7 +429,8 @@ }, 6e10, nil}, testClose{nil}, }, }, { - file: "testdata/pax-sparse-big.tar", + file: "testdata/pax-sparse-big.tar.base64", + obscured: true, tests: []testFnc{ testHeader{Header{ Typeflag: TypeReg, @@ -483,7 +488,7 @@ } return x == y } for _, v := range vectors { - t.Run(path.Base(v.file), func(t *testing.T) { + t.Run(strings.TrimSuffix(path.Base(v.file), ".base64"), func(t *testing.T) { const maxSize = 10 << 10 // 10KiB buf := new(bytes.Buffer) tw := NewWriter(iotest.TruncateWriter(buf, maxSize)) @@ -522,7 +527,16 @@ } } if v.file != "" { - want, err := os.ReadFile(v.file) + path := v.file + if v.obscured { + tf, err := obscuretestdata.DecodeToTempFile(path) + if err != nil { + t.Fatalf("obscuretestdata.DecodeToTempFile(%s): %v", path, err) + } + path = tf + } + + want, err := os.ReadFile(path) if err != nil { t.Fatalf("ReadFile() = %v, want nil", err) } diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 7e8486874ef142a9a998f879b08676342b8988e6..47d243d1a16190b5205dde6aad8ea521cbabe8ad 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -425,8 +425,8 @@ and of course there is nothing stopping the C code from doing anything it likes. However, programs that break these rules are likely to fail in unexpected and unpredictable ways. -The runtime/cgo.Handle type can be used to safely pass Go values -between Go and C. See the runtime/cgo package documentation for details. +The type [runtime/cgo.Handle] can be used to safely pass Go values +between Go and C. Note: the current implementation has a bug. While Go code is permitted to write nil or a C pointer (but not a Go pointer) to C memory, the diff --git a/src/cmd/cgo/internal/test/cgo_test.go b/src/cmd/cgo/internal/test/cgo_test.go index 04e06cf95ec55086ec3a606b4f9fe4e4b716f83f..17f5f3531c02c5bbeb55cfdfe2c895ed4c50a983 100644 --- a/src/cmd/cgo/internal/test/cgo_test.go +++ b/src/cmd/cgo/internal/test/cgo_test.go @@ -12,101 +12,105 @@ // The actual test functions are in non-_test.go files // so that they can use cgo (import "C"). // These wrappers are here for gotest to find. -func Test1328(t *testing.T) { test1328(t) } -func Test1560(t *testing.T) { test1560(t) } -func Test1635(t *testing.T) { test1635(t) } -func Test3250(t *testing.T) { test3250(t) } -func Test3729(t *testing.T) { test3729(t) } -func Test3775(t *testing.T) { test3775(t) } -func Test4029(t *testing.T) { test4029(t) } -func Test4339(t *testing.T) { test4339(t) } -func Test5227(t *testing.T) { test5227(t) } -func Test5242(t *testing.T) { test5242(t) } -func Test5337(t *testing.T) { test5337(t) } -func Test5548(t *testing.T) { test5548(t) } -func Test5603(t *testing.T) { test5603(t) } -func Test5986(t *testing.T) { test5986(t) } -func Test6390(t *testing.T) { test6390(t) } -func Test6833(t *testing.T) { test6833(t) } -func Test6907(t *testing.T) { test6907(t) } -func Test6907Go(t *testing.T) { test6907Go(t) } -func Test7560(t *testing.T) { test7560(t) } -func Test7665(t *testing.T) { test7665(t) } -func Test7978(t *testing.T) { test7978(t) } -func Test8092(t *testing.T) { test8092(t) } -func Test8517(t *testing.T) { test8517(t) } -func Test8694(t *testing.T) { test8694(t) } -func Test8756(t *testing.T) { test8756(t) } -func Test8811(t *testing.T) { test8811(t) } -func Test9026(t *testing.T) { test9026(t) } -func Test9510(t *testing.T) { test9510(t) } -func Test9557(t *testing.T) { test9557(t) } -func Test10303(t *testing.T) { test10303(t, 10) } -func Test11925(t *testing.T) { test11925(t) } -func Test12030(t *testing.T) { test12030(t) } -func Test14838(t *testing.T) { test14838(t) } -func Test17065(t *testing.T) { test17065(t) } -func Test17537(t *testing.T) { test17537(t) } -func Test18126(t *testing.T) { test18126(t) } -func Test18720(t *testing.T) { test18720(t) } -func Test20129(t *testing.T) { test20129(t) } -func Test20266(t *testing.T) { test20266(t) } -func Test20369(t *testing.T) { test20369(t) } -func Test20910(t *testing.T) { test20910(t) } -func Test21708(t *testing.T) { test21708(t) } -func Test21809(t *testing.T) { test21809(t) } -func Test21897(t *testing.T) { test21897(t) } -func Test22906(t *testing.T) { test22906(t) } -func Test23356(t *testing.T) { test23356(t) } -func Test24206(t *testing.T) { test24206(t) } -func Test25143(t *testing.T) { test25143(t) } -func Test26066(t *testing.T) { test26066(t) } -func Test26213(t *testing.T) { test26213(t) } -func Test27660(t *testing.T) { test27660(t) } -func Test28896(t *testing.T) { test28896(t) } -func Test30065(t *testing.T) { test30065(t) } -func Test32579(t *testing.T) { test32579(t) } -func Test31891(t *testing.T) { test31891(t) } -func Test42018(t *testing.T) { test42018(t) } -func Test45451(t *testing.T) { test45451(t) } -func Test49633(t *testing.T) { test49633(t) } -func Test69086(t *testing.T) { test69086(t) } -func TestAlign(t *testing.T) { testAlign(t) } -func TestAtol(t *testing.T) { testAtol(t) } -func TestBlocking(t *testing.T) { testBlocking(t) } -func TestBoolAlign(t *testing.T) { testBoolAlign(t) } -func TestCallGoWithString(t *testing.T) { testCallGoWithString(t) } -func TestCallback(t *testing.T) { testCallback(t) } -func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) } -func TestCallbackGC(t *testing.T) { testCallbackGC(t) } -func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) } -func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) } -func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) } -func TestCallbackStack(t *testing.T) { testCallbackStack(t) } -func TestCflags(t *testing.T) { testCflags(t) } -func TestCheckConst(t *testing.T) { testCheckConst(t) } -func TestConst(t *testing.T) { testConst(t) } -func TestCthread(t *testing.T) { testCthread(t) } -func TestEnum(t *testing.T) { testEnum(t) } -func TestNamedEnum(t *testing.T) { testNamedEnum(t) } -func TestCastToEnum(t *testing.T) { testCastToEnum(t) } -func TestErrno(t *testing.T) { testErrno(t) } -func TestFpVar(t *testing.T) { testFpVar(t) } -func TestGCC68255(t *testing.T) { testGCC68255(t) } -func TestHandle(t *testing.T) { testHandle(t) } -func TestHelpers(t *testing.T) { testHelpers(t) } -func TestLibgcc(t *testing.T) { testLibgcc(t) } -func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) } -func TestNaming(t *testing.T) { testNaming(t) } -func TestPanicFromC(t *testing.T) { testPanicFromC(t) } -func TestPrintf(t *testing.T) { testPrintf(t) } -func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) } -func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) } -func TestSetEnv(t *testing.T) { testSetEnv(t) } -func TestThreadLock(t *testing.T) { testThreadLockFunc(t) } -func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) } -func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) } -func Test76340(t *testing.T) { test76340(t) } +func Test1328(t *testing.T) { test1328(t) } +func Test1560(t *testing.T) { test1560(t) } +func Test1635(t *testing.T) { test1635(t) } +func Test3250(t *testing.T) { test3250(t) } +func Test3729(t *testing.T) { test3729(t) } +func Test3775(t *testing.T) { test3775(t) } +func Test4029(t *testing.T) { test4029(t) } +func Test4339(t *testing.T) { test4339(t) } +func Test5227(t *testing.T) { test5227(t) } +func Test5242(t *testing.T) { test5242(t) } +func Test5337(t *testing.T) { test5337(t) } +func Test5548(t *testing.T) { test5548(t) } +func Test5603(t *testing.T) { test5603(t) } +func Test5986(t *testing.T) { test5986(t) } +func Test6390(t *testing.T) { test6390(t) } +func Test6833(t *testing.T) { test6833(t) } +func Test6907(t *testing.T) { test6907(t) } +func Test6907Go(t *testing.T) { test6907Go(t) } +func Test7560(t *testing.T) { test7560(t) } +func Test7665(t *testing.T) { test7665(t) } +func Test7978(t *testing.T) { test7978(t) } +func Test8092(t *testing.T) { test8092(t) } +func Test8517(t *testing.T) { test8517(t) } +func Test8694(t *testing.T) { test8694(t) } +func Test8756(t *testing.T) { test8756(t) } +func Test8811(t *testing.T) { test8811(t) } +func Test9026(t *testing.T) { test9026(t) } +func Test9510(t *testing.T) { test9510(t) } +func Test9557(t *testing.T) { test9557(t) } +func Test10303(t *testing.T) { test10303(t, 10) } +func Test11925(t *testing.T) { test11925(t) } +func Test12030(t *testing.T) { test12030(t) } +func Test14838(t *testing.T) { test14838(t) } +func Test17065(t *testing.T) { test17065(t) } +func Test17537(t *testing.T) { test17537(t) } +func Test18126(t *testing.T) { test18126(t) } +func Test18720(t *testing.T) { test18720(t) } +func Test20129(t *testing.T) { test20129(t) } +func Test20266(t *testing.T) { test20266(t) } +func Test20369(t *testing.T) { test20369(t) } +func Test20910(t *testing.T) { test20910(t) } +func Test21708(t *testing.T) { test21708(t) } +func Test21809(t *testing.T) { test21809(t) } +func Test21897(t *testing.T) { test21897(t) } +func Test22906(t *testing.T) { test22906(t) } +func Test23356(t *testing.T) { test23356(t) } +func Test24206(t *testing.T) { test24206(t) } +func Test25143(t *testing.T) { test25143(t) } +func Test26066(t *testing.T) { test26066(t) } +func Test26213(t *testing.T) { test26213(t) } +func Test27660(t *testing.T) { test27660(t) } +func Test28896(t *testing.T) { test28896(t) } +func Test30065(t *testing.T) { test30065(t) } +func Test32579(t *testing.T) { test32579(t) } +func Test31891(t *testing.T) { test31891(t) } +func Test42018(t *testing.T) { test42018(t) } +func Test45451(t *testing.T) { test45451(t) } +func Test49633(t *testing.T) { test49633(t) } +func Test69086(t *testing.T) { test69086(t) } +func TestAlign(t *testing.T) { testAlign(t) } +func TestAtol(t *testing.T) { testAtol(t) } +func TestBlocking(t *testing.T) { testBlocking(t) } +func TestBoolAlign(t *testing.T) { testBoolAlign(t) } +func TestCallGoWithString(t *testing.T) { testCallGoWithString(t) } +func TestCallback(t *testing.T) { testCallback(t) } +func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) } +func TestCallbackGC(t *testing.T) { testCallbackGC(t) } +func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) } +func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) } +func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) } +func TestCallbackStack(t *testing.T) { testCallbackStack(t) } +func TestCflags(t *testing.T) { testCflags(t) } +func TestCheckConst(t *testing.T) { testCheckConst(t) } +func TestConst(t *testing.T) { testConst(t) } +func TestCthread(t *testing.T) { testCthread(t) } +func TestEnum(t *testing.T) { testEnum(t) } +func TestNamedEnum(t *testing.T) { testNamedEnum(t) } +func TestCastToEnum(t *testing.T) { testCastToEnum(t) } +func TestErrno(t *testing.T) { testErrno(t) } +func TestFpVar(t *testing.T) { testFpVar(t) } +func TestGCC68255(t *testing.T) { testGCC68255(t) } +func TestHandle(t *testing.T) { testHandle(t) } +func TestHelpers(t *testing.T) { testHelpers(t) } +func TestLibgcc(t *testing.T) { testLibgcc(t) } +func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) } +func TestNaming(t *testing.T) { testNaming(t) } +func TestPanicFromC(t *testing.T) { testPanicFromC(t) } +func TestPrintf(t *testing.T) { testPrintf(t) } +func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) } +func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) } +func TestSetEnv(t *testing.T) { testSetEnv(t) } +func TestThreadLock(t *testing.T) { testThreadLockFunc(t) } +func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) } +func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) } +func Test76340(t *testing.T) { test76340(t) } +func TestDITCgo(t *testing.T) { testDITCgo(t) } +func TestDITCgoCallback(t *testing.T) { testDITCgoCallback(t) } +func TestDITCgoCallbackEnableDIT(t *testing.T) { testDITCgoCallbackEnableDIT(t) } +func TestDITCgoCallbackDisableDIT(t *testing.T) { testDITCgoCallbackDisableDIT(t) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } func BenchmarkGoString(b *testing.B) { benchGoString(b) } diff --git a/src/cmd/cgo/internal/test/test.go b/src/cmd/cgo/internal/test/test.go index 4dd14facb50e6b88b1ab124b81209d03d2fb1b62..3f0732b428b2fcb8612b75e67efbe0a725c9cdfd 100644 --- a/src/cmd/cgo/internal/test/test.go +++ b/src/cmd/cgo/internal/test/test.go @@ -971,13 +971,43 @@ GoInterface issue76340returnFromC(int val) { return exportAny76340Return(val); } + +static void enableDIT() { + #ifdef __arm64__ + __asm__ __volatile__("msr dit, #1"); + #endif +} + +static void disableDIT() { + #ifdef __arm64__ + __asm__ __volatile__("msr dit, #0"); + #endif +} + +extern uint8_t ditCallback(); + +static uint8_t ditCallbackTest() { + return ditCallback(); +} + +static void ditCallbackEnableDIT() { + enableDIT(); + ditCallback(); +} + +static void ditCallbackDisableDIT() { + disableDIT(); + ditCallback(); +} */ import "C" import ( "context" + "crypto/subtle" "fmt" "internal/asan" + "internal/runtime/sys" "math" "math/rand" "os" @@ -2438,3 +2468,76 @@ if r3.t != nil || r3.v != nil { t.Errorf("issue76340returnFromC(0) returned non-nil interface: got %v, want nil", r3) } } + +func testDITCgo(t *testing.T) { + if !sys.DITSupported { + t.Skip("CPU does not support DIT") + } + + ditAlreadyEnabled := sys.DITEnabled() + C.enableDIT() + + if ditAlreadyEnabled != sys.DITEnabled() { + t.Fatalf("DIT state not preserved across cgo call: before %t, after %t", ditAlreadyEnabled, sys.DITEnabled()) + } + + subtle.WithDataIndependentTiming(func() { + C.disableDIT() + + if !sys.DITEnabled() { + t.Fatal("DIT disabled after disabling in cgo call") + } + }) +} + +func testDITCgoCallback(t *testing.T) { + if !sys.DITSupported { + t.Skip("CPU does not support DIT") + } + + ditAlreadyEnabled := sys.DITEnabled() + + subtle.WithDataIndependentTiming(func() { + if C.ditCallbackTest() != 1 { + t.Fatal("DIT not enabled in cgo callback within WithDataIndependentTiming") + } + }) + + if ditAlreadyEnabled != sys.DITEnabled() { + t.Fatalf("DIT state not preserved across cgo callback: before %t, after %t", ditAlreadyEnabled, sys.DITEnabled()) + } +} + +func testDITCgoCallbackEnableDIT(t *testing.T) { + if !sys.DITSupported { + t.Skip("CPU does not support DIT") + } + + ditAlreadyEnabled := sys.DITEnabled() + + C.ditCallbackEnableDIT() + + if ditAlreadyEnabled != sys.DITEnabled() { + t.Fatalf("DIT state not preserved across cgo callback: before %t, after %t", ditAlreadyEnabled, sys.DITEnabled()) + } +} + +func testDITCgoCallbackDisableDIT(t *testing.T) { + if !sys.DITSupported { + t.Skip("CPU does not support DIT") + } + + ditAlreadyEnabled := sys.DITEnabled() + + subtle.WithDataIndependentTiming(func() { + C.ditCallbackDisableDIT() + + if !sys.DITEnabled() { + t.Fatal("DIT disabled after disabling in cgo call") + } + }) + + if ditAlreadyEnabled != sys.DITEnabled() { + t.Fatalf("DIT state not preserved across cgo callback: before %t, after %t", ditAlreadyEnabled, sys.DITEnabled()) + } +} diff --git a/src/cmd/cgo/internal/test/testx.go b/src/cmd/cgo/internal/test/testx.go index 21ba52260ef893e2e5f5a620de6de63e61b3eb0a..5a6f42e44e6021b1da9e010762bd28fc76ba3202 100644 --- a/src/cmd/cgo/internal/test/testx.go +++ b/src/cmd/cgo/internal/test/testx.go @@ -11,6 +11,7 @@ package cgotest import ( + "internal/runtime/sys" "runtime" "runtime/cgo" "runtime/debug" @@ -613,3 +614,11 @@ } return int(val) } + +//export ditCallback +func ditCallback() uint8 { + if sys.DITEnabled() { + return 1 + } + return 0 +} diff --git a/src/cmd/compile/abi-internal.md b/src/cmd/compile/abi-internal.md index 8de8356132ad14cc4cff0b2084371923af30082c..a04b5aed3faccc4f8aa469d529c91b955c08903a 100644 --- a/src/cmd/compile/abi-internal.md +++ b/src/cmd/compile/abi-internal.md @@ -799,17 +799,15 @@ | X1 | Link register | Link register | Scratch | | X2 | Stack pointer | Same | Same | | X3 | Global pointer | Same | Used by dynamic linker | | X4 | TLS (thread pointer) | TLS | Scratch | -| X24,X25 | Scratch | Scratch | Used by duffcopy, duffzero | | X26 | Closure context pointer | Scratch | Scratch | | X27 | Current goroutine | Same | Same | | X31 | Scratch | Scratch | Scratch | *Rationale*: These register meanings are compatible with Go’s -stack-based calling convention. Context register X20 will change to X26, -duffcopy, duffzero register will change to X24, X25 before this register ABI been adopted. +stack-based calling convention. X10 – X17, X8, X9, X18 – X23, is the same order as A0 – A7, S0 – S7 in platform ABI. F10 – F17, F8, F9, F18 – F23, is the same order as FA0 – FA7, FS0 – FS7 in platform ABI. -X8 – X23, F8 – F15 are used for compressed instruction (RVC) which will benefit code size in the future. +X8 – X23, F8 – F15 are used for compressed instruction (RVC) which benefits code size. #### Stack layout diff --git a/src/cmd/compile/internal/amd64/simdssa.go b/src/cmd/compile/internal/amd64/simdssa.go index 465fb980a50ce29ea7dbf9a9de8350c638b4fc16..f6deba3ec15f674a04f676335a7ae6e8531d8cfe 100644 --- a/src/cmd/compile/internal/amd64/simdssa.go +++ b/src/cmd/compile/internal/amd64/simdssa.go @@ -1232,6 +1232,9 @@ ssa.OpAMD64VPSHRDD512, ssa.OpAMD64VPSHRDQ128, ssa.OpAMD64VPSHRDQ256, ssa.OpAMD64VPSHRDQ512, + ssa.OpAMD64VPCLMULQDQ128, + ssa.OpAMD64VPCLMULQDQ256, + ssa.OpAMD64VPCLMULQDQ512, ssa.OpAMD64VSHUFPS128, ssa.OpAMD64VSHUFPD128, ssa.OpAMD64VSHUFPS256, diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 9a0fa27470a44a30af4bd52281e7a677c5d38c8c..5ddcb84c59560aba722e12bf736e9a7f59f5dbd0 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -18,7 +18,6 @@ "cmd/compile/internal/types" "cmd/internal/obj" "cmd/internal/obj/x86" "internal/abi" - "internal/buildcfg" ) // ssaMarkMoves marks any MOVXconst ops that need to avoid clobbering flags. @@ -1718,7 +1717,15 @@ // SIMD ops case ssa.OpAMD64VZEROUPPER, ssa.OpAMD64VZEROALL: s.Prog(v.Op.Asm()) - case ssa.OpAMD64Zero128, ssa.OpAMD64Zero256, ssa.OpAMD64Zero512: // no code emitted + case ssa.OpAMD64Zero128: // no code emitted + + case ssa.OpAMD64Zero256, ssa.OpAMD64Zero512: + p := s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = simdReg(v) + p.AddRestSourceReg(simdReg(v)) + p.To.Type = obj.TYPE_REG + p.To.Reg = simdReg(v) case ssa.OpAMD64VMOVSSf2v, ssa.OpAMD64VMOVSDf2v: // These are for initializing the least 32/64 bits of a SIMD register from a "float". @@ -1871,34 +1878,7 @@ } // zeroX15 zeroes the X15 register. func zeroX15(s *ssagen.State) { - if !buildcfg.Experiment.SIMD { - opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) - return - } - vxorps := func(s *ssagen.State) { - p := s.Prog(x86.AVXORPS) - p.From.Type = obj.TYPE_REG - p.From.Reg = x86.REG_X15 - p.AddRestSourceReg(x86.REG_X15) - p.To.Type = obj.TYPE_REG - p.To.Reg = x86.REG_X15 - } - if buildcfg.GOAMD64 >= 3 { - vxorps(s) - return - } - // AVX may not be available, check before zeroing the high bits. - p := s.Prog(x86.ACMPB) - p.From.Type = obj.TYPE_MEM - p.From.Name = obj.NAME_EXTERN - p.From.Sym = ir.Syms.X86HasAVX - p.To.Type = obj.TYPE_CONST - p.To.Offset = 1 - jmp := s.Prog(x86.AJNE) - jmp.To.Type = obj.TYPE_BRANCH - vxorps(s) - sse := opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) - jmp.To.SetTarget(sse) + opregreg(s, x86.AXORPS, x86.REG_X15, x86.REG_X15) } // Example instruction: VRSQRTPS X1, X1 diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 2ce5c8accc54b39ac1468343b37ccbe4fff384ce..33f9c325c36f5b1c1c79c879c4392f81313496aa 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -445,7 +445,7 @@ } func isDebugFn(fn *ir.Func) bool { // if n := fn.Nname; n != nil { - // if n.Sym().Name == "Int32x8.Transpose8" && n.Sym().Pkg.Path == "simd" { + // if n.Sym().Name == "Int32x8.Transpose8" && n.Sym().Pkg.Path == "simd/archsimd" { // fmt.Printf("isDebugFn '%s' DOT '%s'\n", n.Sym().Pkg.Path, n.Sym().Name) // return true // } diff --git a/src/cmd/compile/internal/inline/inlheur/analyze_func_params.go b/src/cmd/compile/internal/inline/inlheur/analyze_func_params.go index f6bd84c3f507f134c616f8058d67f8f2601429ea..abfcb3ab3289978506c1dc877bccdabb2d1ff960 100644 --- a/src/cmd/compile/internal/inline/inlheur/analyze_func_params.go +++ b/src/cmd/compile/internal/inline/inlheur/analyze_func_params.go @@ -122,9 +122,9 @@ } type testfType func(x ir.Node, param *ir.Name, idx int) (bool, bool) -// paramsAnalyzer invokes function 'testf' on the specified expression -// 'x' for each parameter, and if the result is TRUE, or's 'flag' into -// the flags for that param. +// checkParams invokes function 'testf' on the specified expression 'x' +// for each parameter. If the result is TRUE, it OR's either 'flag' or 'mayflag' +// into the flags for that param, depending on whether we are in a conditional context. func (pa *paramsAnalyzer) checkParams(x ir.Node, flag ParamPropBits, mayflag ParamPropBits, testf testfType) { for idx, p := range pa.params { if !pa.top[idx] && pa.values[idx] == ParamNoInfo { diff --git a/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go index e77f55ab5e58aa63210f66c5579d3cef5cb90f35..2fb4fdfc966291d91e2fda7477ae7ea4838dfdc2 100644 --- a/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/AMD64Ops.go @@ -214,6 +214,7 @@ vstorev = regInfo{inputs: []regMask{gpspsb, v, v, 0}} vloadk = regInfo{inputs: []regMask{gpspsb, mask, 0}, outputs: vonly} vstorek = regInfo{inputs: []regMask{gpspsb, mask, v, 0}} + v01 = regInfo{inputs: nil, outputs: vonly} v11 = regInfo{inputs: vonly, outputs: vonly} // used in resultInArg0 ops, arg0 must not be x15 v21 = regInfo{inputs: []regMask{v, vz}, outputs: vonly} // used in resultInArg0 ops, arg0 must not be x15 vk = regInfo{inputs: vzonly, outputs: maskonly} @@ -232,6 +233,7 @@ fpv = regInfo{inputs: []regMask{fp}, outputs: vonly} gpv = regInfo{inputs: []regMask{gp}, outputs: vonly} v2flags = regInfo{inputs: []regMask{vz, vz}} + w01 = regInfo{inputs: nil, outputs: wonly} w11 = regInfo{inputs: wonly, outputs: wonly} // used in resultInArg0 ops, arg0 must not be x15 w21 = regInfo{inputs: []regMask{wz, wz}, outputs: wonly} wk = regInfo{inputs: wzonly, outputs: maskonly} @@ -1398,12 +1400,15 @@ {name: "VPMOVVec64x2ToM", argLength: 1, reg: vk, asm: "VPMOVQ2M"}, {name: "VPMOVVec64x4ToM", argLength: 1, reg: vk, asm: "VPMOVQ2M"}, {name: "VPMOVVec64x8ToM", argLength: 1, reg: wk, asm: "VPMOVQ2M"}, + // X15 is the zero register up to 128-bit. For larger values, we zero it on the fly. {name: "Zero128", argLength: 0, reg: x15only, zeroWidth: true, fixedReg: true}, - {name: "Zero256", argLength: 0, reg: x15only, zeroWidth: true, fixedReg: true}, - {name: "Zero512", argLength: 0, reg: x15only, zeroWidth: true, fixedReg: true}, + {name: "Zero256", argLength: 0, reg: v01, asm: "VPXOR"}, + {name: "Zero512", argLength: 0, reg: w01, asm: "VPXORQ"}, + // Move a 32/64 bit float to a 128-bit SIMD register. {name: "VMOVSDf2v", argLength: 1, reg: fpv, asm: "VMOVSD"}, {name: "VMOVSSf2v", argLength: 1, reg: fpv, asm: "VMOVSS"}, + {name: "VMOVQ", argLength: 1, reg: gpv, asm: "VMOVQ"}, {name: "VMOVD", argLength: 1, reg: gpv, asm: "VMOVD"}, diff --git a/src/cmd/compile/internal/ssa/_gen/simdAMD64.rules b/src/cmd/compile/internal/ssa/_gen/simdAMD64.rules index 752fb9d9b0c7e60a34afa03981082803896a1485..649940497ce42cdf0a1e3caae20a3afd8332fbf3 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdAMD64.rules +++ b/src/cmd/compile/internal/ssa/_gen/simdAMD64.rules @@ -1333,6 +1333,9 @@ (blendMaskedInt8x64 x y mask) => (VPBLENDMBMasked512 x y (VPMOVVec8x64ToM mask)) (blendMaskedInt16x32 x y mask) => (VPBLENDMWMasked512 x y (VPMOVVec16x32ToM mask)) (blendMaskedInt32x16 x y mask) => (VPBLENDMDMasked512 x y (VPMOVVec32x16ToM mask)) (blendMaskedInt64x8 x y mask) => (VPBLENDMQMasked512 x y (VPMOVVec64x8ToM mask)) +(carrylessMultiplyUint64x2 ...) => (VPCLMULQDQ128 ...) +(carrylessMultiplyUint64x4 ...) => (VPCLMULQDQ256 ...) +(carrylessMultiplyUint64x8 ...) => (VPCLMULQDQ512 ...) (concatSelectedConstantFloat32x4 ...) => (VSHUFPS128 ...) (concatSelectedConstantFloat64x2 ...) => (VSHUFPD128 ...) (concatSelectedConstantInt32x4 ...) => (VSHUFPS128 ...) diff --git a/src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go b/src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go index 0727f626fb12182d16070c8a6a8061e0ca9081b8..f38d24fde7e14b00a471a305f6ea70e75c0353c5 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go +++ b/src/cmd/compile/internal/ssa/_gen/simdAMD64ops.go @@ -1269,6 +1269,9 @@ {name: "VPALIGNR512", argLength: 2, reg: w21, asm: "VPALIGNR", aux: "UInt8", commutative: false, typ: "Vec512", resultInArg0: false}, {name: "VPALIGNRMasked128", argLength: 3, reg: w2kw, asm: "VPALIGNR", aux: "UInt8", commutative: false, typ: "Vec128", resultInArg0: false}, {name: "VPALIGNRMasked256", argLength: 3, reg: w2kw, asm: "VPALIGNR", aux: "UInt8", commutative: false, typ: "Vec256", resultInArg0: false}, {name: "VPALIGNRMasked512", argLength: 3, reg: w2kw, asm: "VPALIGNR", aux: "UInt8", commutative: false, typ: "Vec512", resultInArg0: false}, + {name: "VPCLMULQDQ128", argLength: 2, reg: v21, asm: "VPCLMULQDQ", aux: "UInt8", commutative: false, typ: "Vec128", resultInArg0: false}, + {name: "VPCLMULQDQ256", argLength: 2, reg: w21, asm: "VPCLMULQDQ", aux: "UInt8", commutative: false, typ: "Vec256", resultInArg0: false}, + {name: "VPCLMULQDQ512", argLength: 2, reg: w21, asm: "VPCLMULQDQ", aux: "UInt8", commutative: false, typ: "Vec512", resultInArg0: false}, {name: "VPCMPB512", argLength: 2, reg: w2k, asm: "VPCMPB", aux: "UInt8", commutative: false, typ: "Mask", resultInArg0: false}, {name: "VPCMPBMasked128", argLength: 3, reg: w2kk, asm: "VPCMPB", aux: "UInt8", commutative: false, typ: "Mask", resultInArg0: false}, {name: "VPCMPBMasked256", argLength: 3, reg: w2kk, asm: "VPCMPB", aux: "UInt8", commutative: false, typ: "Mask", resultInArg0: false}, diff --git a/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go b/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go index 53bd208e34e54ed7cd5f2f3841e1233f8047d142..a68d8c4122697c75fa2766baaedc653c33deb606 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go +++ b/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go @@ -1301,6 +1301,9 @@ {name: "TruncScaledResidueFloat32x16", argLength: 1, commutative: false, aux: "UInt8"}, {name: "TruncScaledResidueFloat64x2", argLength: 1, commutative: false, aux: "UInt8"}, {name: "TruncScaledResidueFloat64x4", argLength: 1, commutative: false, aux: "UInt8"}, {name: "TruncScaledResidueFloat64x8", argLength: 1, commutative: false, aux: "UInt8"}, + {name: "carrylessMultiplyUint64x2", argLength: 2, commutative: false, aux: "UInt8"}, + {name: "carrylessMultiplyUint64x4", argLength: 2, commutative: false, aux: "UInt8"}, + {name: "carrylessMultiplyUint64x8", argLength: 2, commutative: false, aux: "UInt8"}, {name: "concatSelectedConstantFloat32x4", argLength: 2, commutative: false, aux: "UInt8"}, {name: "concatSelectedConstantFloat64x2", argLength: 2, commutative: false, aux: "UInt8"}, {name: "concatSelectedConstantGroupedFloat32x8", argLength: 2, commutative: false, aux: "UInt8"}, diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 46a986a35a355f7524c73eb88e5846b674b2e366..00d581ec9af41dd8fb55db8d1de892c90231b25d 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -2510,6 +2510,9 @@ OpAMD64VPALIGNR512 OpAMD64VPALIGNRMasked128 OpAMD64VPALIGNRMasked256 OpAMD64VPALIGNRMasked512 + OpAMD64VPCLMULQDQ128 + OpAMD64VPCLMULQDQ256 + OpAMD64VPCLMULQDQ512 OpAMD64VPCMPB512 OpAMD64VPCMPBMasked128 OpAMD64VPCMPBMasked256 @@ -7448,6 +7451,9 @@ OpTruncScaledResidueFloat32x16 OpTruncScaledResidueFloat64x2 OpTruncScaledResidueFloat64x4 OpTruncScaledResidueFloat64x8 + OpcarrylessMultiplyUint64x2 + OpcarrylessMultiplyUint64x4 + OpcarrylessMultiplyUint64x8 OpconcatSelectedConstantFloat32x4 OpconcatSelectedConstantFloat64x2 OpconcatSelectedConstantGroupedFloat32x8 @@ -20359,24 +20365,22 @@ }, }, }, { - name: "Zero256", - argLen: 0, - zeroWidth: true, - fixedReg: true, + name: "Zero256", + argLen: 0, + asm: x86.AVPXOR, reg: regInfo{ outputs: []outputInfo{ - {0, 2147483648}, // X15 + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 }, }, }, { - name: "Zero512", - argLen: 0, - zeroWidth: true, - fixedReg: true, + name: "Zero512", + argLen: 0, + asm: x86.AVPXORQ, reg: regInfo{ outputs: []outputInfo{ - {0, 2147483648}, // X15 + {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 }, }, }, @@ -39205,6 +39209,51 @@ inputs: []inputInfo{ {2, 71494644084506624}, // K1 K2 K3 K4 K5 K6 K7 {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + }, + outputs: []outputInfo{ + {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + }, + }, + }, + { + name: "VPCLMULQDQ128", + auxType: auxUInt8, + argLen: 2, + asm: x86.AVPCLMULQDQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + {1, 4294901760}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 + }, + outputs: []outputInfo{ + {0, 2147418112}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 + }, + }, + }, + { + name: "VPCLMULQDQ256", + auxType: auxUInt8, + argLen: 2, + asm: x86.AVPCLMULQDQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + }, + outputs: []outputInfo{ + {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + }, + }, + }, + { + name: "VPCLMULQDQ512", + auxType: auxUInt8, + argLen: 2, + asm: x86.AVPCLMULQDQ, + reg: regInfo{ + inputs: []inputInfo{ + {0, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 + {1, 281474976645120}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 }, outputs: []outputInfo{ {0, 281472829161472}, // X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X27 X28 X29 X30 X31 @@ -95846,6 +95895,24 @@ { name: "TruncScaledResidueFloat64x8", auxType: auxUInt8, argLen: 1, + generic: true, + }, + { + name: "carrylessMultiplyUint64x2", + auxType: auxUInt8, + argLen: 2, + generic: true, + }, + { + name: "carrylessMultiplyUint64x4", + auxType: auxUInt8, + argLen: 2, + generic: true, + }, + { + name: "carrylessMultiplyUint64x8", + auxType: auxUInt8, + argLen: 2, generic: true, }, { diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go index 99956c56a06a548a9ae77fb701571ad436a0a35a..19f16e1cbb14a008b4d69bbf63d0d603e28c8031 100644 --- a/src/cmd/compile/internal/ssa/rewriteAMD64.go +++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go @@ -6307,6 +6307,15 @@ case OpblendMaskedInt64x8: return rewriteValueAMD64_OpblendMaskedInt64x8(v) case OpblendMaskedInt8x64: return rewriteValueAMD64_OpblendMaskedInt8x64(v) + case OpcarrylessMultiplyUint64x2: + v.Op = OpAMD64VPCLMULQDQ128 + return true + case OpcarrylessMultiplyUint64x4: + v.Op = OpAMD64VPCLMULQDQ256 + return true + case OpcarrylessMultiplyUint64x8: + v.Op = OpAMD64VPCLMULQDQ512 + return true case OpconcatSelectedConstantFloat32x4: v.Op = OpAMD64VSHUFPS128 return true diff --git a/src/cmd/compile/internal/ssagen/intrinsics.go b/src/cmd/compile/internal/ssagen/intrinsics.go index 17beb7b8488455a991eb793e1030d7f0ebbbd880..4425c5617b1e4bc30341706e9e836e3921a58e6e 100644 --- a/src/cmd/compile/internal/ssagen/intrinsics.go +++ b/src/cmd/compile/internal/ssagen/intrinsics.go @@ -1644,7 +1644,7 @@ if buildcfg.Experiment.SIMD { // Only enable intrinsics, if SIMD experiment. simdIntrinsics(addF) - addF("simd", "ClearAVXUpperBits", + addF(simdPackage, "ClearAVXUpperBits", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { s.vars[memVar] = s.newValue1(ssa.OpAMD64VZEROUPPER, types.TypeMem, s.mem()) return nil @@ -1668,15 +1668,18 @@ 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) + // 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) { - addF("simd", method, + addF(simdPackage, method, func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { x, a, b, c, d, y := args[0], args[1], args[2], args[3], args[4], args[5] if a.Op == ssa.OpConst8 && b.Op == ssa.OpConst8 && c.Op == ssa.OpConst8 && d.Op == ssa.OpConst8 { - return select4FromPair(x, a, b, c, d, y, s, hwop, vectype) - } else { - return s.callResult(n, callNormal) + z := select4FromPair(x, a, b, c, d, y, s, hwop, vectype) + if z != nil { + return z + } } + return s.callResult(n, callNormal) }, sys.AMD64) } @@ -1693,15 +1696,18 @@ sfp4("Int32x16.SelectFromPairGrouped", ssa.OpconcatSelectedConstantGroupedInt32x16, types.TypeVec512) sfp4("Uint32x16.SelectFromPairGrouped", ssa.OpconcatSelectedConstantGroupedUint32x16, types.TypeVec512) sfp4("Float32x16.SelectFromPairGrouped", ssa.OpconcatSelectedConstantGroupedFloat32x16, types.TypeVec512) + // sfp2 is intrinsic-if-constant, but otherwise it's complicated enough to just implement in Go. sfp2 := func(method string, hwop ssa.Op, vectype *types.Type, cscimm func(i, j uint8) int64) { - addF("simd", method, + addF(simdPackage, method, func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { x, a, b, y := args[0], args[1], args[2], args[3] if a.Op == ssa.OpConst8 && b.Op == ssa.OpConst8 { - return select2FromPair(x, a, b, y, s, hwop, vectype, cscimm) - } else { - return s.callResult(n, callNormal) + z := select2FromPair(x, a, b, y, s, hwop, vectype, cscimm) + if z != nil { + return z + } } + return s.callResult(n, callNormal) }, sys.AMD64) } @@ -1767,6 +1773,9 @@ ) func select2FromPair(x, _a, _b, y *ssa.Value, s *state, op ssa.Op, t *types.Type, csc func(a, b uint8) int64) *ssa.Value { a, b := uint8(_a.AuxInt8()), uint8(_b.AuxInt8()) + if a > 3 || b > 3 { + return nil + } pattern := (a&2)>>1 + (b & 2) a, b = a&1, b&1 @@ -1785,6 +1794,9 @@ } func select4FromPair(x, _a, _b, _c, _d, y *ssa.Value, s *state, op ssa.Op, t *types.Type) *ssa.Value { a, b, c, d := uint8(_a.AuxInt8()), uint8(_b.AuxInt8()), uint8(_c.AuxInt8()), uint8(_d.AuxInt8()) + if a > 7 || b > 7 || c > 7 || d > 7 { + return nil + } pattern := a>>2 + (b&4)>>1 + (c & 4) + (d&4)<<1 a, b, c, d = a&3, b&3, c&3, d&3 @@ -2154,7 +2166,7 @@ fn := sym.Name if ssa.IntrinsicsDisable { if pkg == "internal/runtime/sys" && (fn == "GetCallerPC" || fn == "GrtCallerSP" || fn == "GetClosurePtr") || - pkg == "internal/simd" || pkg == "simd" { // TODO after simd has been moved to package simd, remove internal/simd + pkg == simdPackage { // These runtime functions don't have definitions, must be intrinsics. } else { return nil diff --git a/src/cmd/compile/internal/ssagen/intrinsics_test.go b/src/cmd/compile/internal/ssagen/intrinsics_test.go index 91b975c913f7c037f7efe275015b50bbc7a5cf5e..3d866a6bf4a8848499a8d61bdc066ef8567d7dc3 100644 --- a/src/cmd/compile/internal/ssagen/intrinsics_test.go +++ b/src/cmd/compile/internal/ssagen/intrinsics_test.go @@ -1407,13 +1407,13 @@ for ik, _ := range intrinsics { gotIntrinsics[testIntrinsicKey{ik.arch.Name, ik.pkg, ik.fn}] = struct{}{} } for ik, _ := range gotIntrinsics { - if _, found := wantIntrinsics[ik]; !found && (ik.pkg != "simd" || *simd) { + if _, found := wantIntrinsics[ik]; !found && (ik.pkg != "simd/archsimd" || *simd) { t.Errorf("Got unwanted intrinsic %v %v.%v", ik.archName, ik.pkg, ik.fn) } } for ik, _ := range wantIntrinsics { - if _, found := gotIntrinsics[ik]; !found && (ik.pkg != "simd" || *simd) { + if _, found := gotIntrinsics[ik]; !found && (ik.pkg != "simd/archsimd" || *simd) { t.Errorf("Want missing intrinsic %v %v.%v", ik.archName, ik.pkg, ik.fn) } } diff --git a/src/cmd/compile/internal/ssagen/simdintrinsics.go b/src/cmd/compile/internal/ssagen/simdintrinsics.go index 607311d3b2891dd88a729bd0090e1f1d968a25d0..7eb54569944d57d5bd4ad0c0c9876d44e3769b6f 100644 --- a/src/cmd/compile/internal/ssagen/simdintrinsics.go +++ b/src/cmd/compile/internal/ssagen/simdintrinsics.go @@ -9,7 +9,7 @@ "cmd/compile/internal/types" "cmd/internal/sys" ) -const simdPackage = "simd" +const simdPackage = "simd/archsimd" func simdIntrinsics(addF func(pkg, fn string, b intrinsicBuilder, archFamilies ...sys.ArchFamily)) { addF(simdPackage, "Uint8x16.AESDecryptLastRound", opLen2(ssa.OpAESDecryptLastRoundUint8x16, types.TypeVec128), sys.AMD64) @@ -1309,6 +1309,9 @@ addF(simdPackage, "Int8x64.blendMasked", opLen3(ssa.OpblendMaskedInt8x64, types.TypeVec512), sys.AMD64) addF(simdPackage, "Int16x32.blendMasked", opLen3(ssa.OpblendMaskedInt16x32, types.TypeVec512), sys.AMD64) addF(simdPackage, "Int32x16.blendMasked", opLen3(ssa.OpblendMaskedInt32x16, types.TypeVec512), sys.AMD64) addF(simdPackage, "Int64x8.blendMasked", opLen3(ssa.OpblendMaskedInt64x8, types.TypeVec512), sys.AMD64) + addF(simdPackage, "Uint64x2.carrylessMultiply", opLen2Imm8(ssa.OpcarrylessMultiplyUint64x2, types.TypeVec128, 0), sys.AMD64) + addF(simdPackage, "Uint64x4.carrylessMultiply", opLen2Imm8(ssa.OpcarrylessMultiplyUint64x4, types.TypeVec256, 0), sys.AMD64) + addF(simdPackage, "Uint64x8.carrylessMultiply", opLen2Imm8(ssa.OpcarrylessMultiplyUint64x8, types.TypeVec512, 0), sys.AMD64) addF(simdPackage, "Float32x4.concatSelectedConstant", opLen2Imm8(ssa.OpconcatSelectedConstantFloat32x4, types.TypeVec128, 0), sys.AMD64) addF(simdPackage, "Float64x2.concatSelectedConstant", opLen2Imm8(ssa.OpconcatSelectedConstantFloat64x2, types.TypeVec128, 0), sys.AMD64) addF(simdPackage, "Int32x4.concatSelectedConstant", opLen2Imm8(ssa.OpconcatSelectedConstantInt32x4, types.TypeVec128, 0), sys.AMD64) @@ -1739,73 +1742,73 @@ addF(simdPackage, "LoadMaskedMask32x16", simdMaskedLoad(ssa.OpLoadMasked32), sys.AMD64) addF(simdPackage, "Mask32x16.StoreMasked", simdMaskedStore(ssa.OpStoreMasked32), sys.AMD64) addF(simdPackage, "LoadMaskedMask64x8", simdMaskedLoad(ssa.OpLoadMasked64), sys.AMD64) addF(simdPackage, "Mask64x8.StoreMasked", simdMaskedStore(ssa.OpStoreMasked64), sys.AMD64) - addF(simdPackage, "Mask8x16.AsInt8x16", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask8x16.ToInt8x16", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int8x16.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask8x16.And", opLen2(ssa.OpAndInt32x4, types.TypeVec128), sys.AMD64) addF(simdPackage, "Mask8x16.Or", opLen2(ssa.OpOrInt32x4, types.TypeVec128), sys.AMD64) addF(simdPackage, "Mask8x16FromBits", simdCvtVToMask(8, 16), sys.AMD64) addF(simdPackage, "Mask8x16.ToBits", simdCvtMaskToV(8, 16), sys.AMD64) - addF(simdPackage, "Mask8x32.AsInt8x32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask8x32.ToInt8x32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int8x32.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask8x32.And", opLen2(ssa.OpAndInt32x8, types.TypeVec256), sys.AMD64) addF(simdPackage, "Mask8x32.Or", opLen2(ssa.OpOrInt32x8, types.TypeVec256), sys.AMD64) addF(simdPackage, "Mask8x32FromBits", simdCvtVToMask(8, 32), sys.AMD64) addF(simdPackage, "Mask8x32.ToBits", simdCvtMaskToV(8, 32), sys.AMD64) - addF(simdPackage, "Mask8x64.AsInt8x64", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask8x64.ToInt8x64", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int8x64.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask8x64.And", opLen2(ssa.OpAndInt32x16, types.TypeVec512), sys.AMD64) addF(simdPackage, "Mask8x64.Or", opLen2(ssa.OpOrInt32x16, types.TypeVec512), sys.AMD64) addF(simdPackage, "Mask8x64FromBits", simdCvtVToMask(8, 64), sys.AMD64) addF(simdPackage, "Mask8x64.ToBits", simdCvtMaskToV(8, 64), sys.AMD64) - addF(simdPackage, "Mask16x8.AsInt16x8", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask16x8.ToInt16x8", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int16x8.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask16x8.And", opLen2(ssa.OpAndInt32x4, types.TypeVec128), sys.AMD64) addF(simdPackage, "Mask16x8.Or", opLen2(ssa.OpOrInt32x4, types.TypeVec128), sys.AMD64) addF(simdPackage, "Mask16x8FromBits", simdCvtVToMask(16, 8), sys.AMD64) addF(simdPackage, "Mask16x8.ToBits", simdCvtMaskToV(16, 8), sys.AMD64) - addF(simdPackage, "Mask16x16.AsInt16x16", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask16x16.ToInt16x16", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int16x16.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask16x16.And", opLen2(ssa.OpAndInt32x8, types.TypeVec256), sys.AMD64) addF(simdPackage, "Mask16x16.Or", opLen2(ssa.OpOrInt32x8, types.TypeVec256), sys.AMD64) addF(simdPackage, "Mask16x16FromBits", simdCvtVToMask(16, 16), sys.AMD64) addF(simdPackage, "Mask16x16.ToBits", simdCvtMaskToV(16, 16), sys.AMD64) - addF(simdPackage, "Mask16x32.AsInt16x32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask16x32.ToInt16x32", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int16x32.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask16x32.And", opLen2(ssa.OpAndInt32x16, types.TypeVec512), sys.AMD64) addF(simdPackage, "Mask16x32.Or", opLen2(ssa.OpOrInt32x16, types.TypeVec512), sys.AMD64) addF(simdPackage, "Mask16x32FromBits", simdCvtVToMask(16, 32), sys.AMD64) addF(simdPackage, "Mask16x32.ToBits", simdCvtMaskToV(16, 32), sys.AMD64) - addF(simdPackage, "Mask32x4.AsInt32x4", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask32x4.ToInt32x4", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int32x4.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask32x4.And", opLen2(ssa.OpAndInt32x4, types.TypeVec128), sys.AMD64) addF(simdPackage, "Mask32x4.Or", opLen2(ssa.OpOrInt32x4, types.TypeVec128), sys.AMD64) addF(simdPackage, "Mask32x4FromBits", simdCvtVToMask(32, 4), sys.AMD64) addF(simdPackage, "Mask32x4.ToBits", simdCvtMaskToV(32, 4), sys.AMD64) - addF(simdPackage, "Mask32x8.AsInt32x8", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask32x8.ToInt32x8", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int32x8.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask32x8.And", opLen2(ssa.OpAndInt32x8, types.TypeVec256), sys.AMD64) addF(simdPackage, "Mask32x8.Or", opLen2(ssa.OpOrInt32x8, types.TypeVec256), sys.AMD64) addF(simdPackage, "Mask32x8FromBits", simdCvtVToMask(32, 8), sys.AMD64) addF(simdPackage, "Mask32x8.ToBits", simdCvtMaskToV(32, 8), sys.AMD64) - addF(simdPackage, "Mask32x16.AsInt32x16", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask32x16.ToInt32x16", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int32x16.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask32x16.And", opLen2(ssa.OpAndInt32x16, types.TypeVec512), sys.AMD64) addF(simdPackage, "Mask32x16.Or", opLen2(ssa.OpOrInt32x16, types.TypeVec512), sys.AMD64) addF(simdPackage, "Mask32x16FromBits", simdCvtVToMask(32, 16), sys.AMD64) addF(simdPackage, "Mask32x16.ToBits", simdCvtMaskToV(32, 16), sys.AMD64) - addF(simdPackage, "Mask64x2.AsInt64x2", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask64x2.ToInt64x2", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int64x2.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask64x2.And", opLen2(ssa.OpAndInt32x4, types.TypeVec128), sys.AMD64) addF(simdPackage, "Mask64x2.Or", opLen2(ssa.OpOrInt32x4, types.TypeVec128), sys.AMD64) addF(simdPackage, "Mask64x2FromBits", simdCvtVToMask(64, 2), sys.AMD64) addF(simdPackage, "Mask64x2.ToBits", simdCvtMaskToV(64, 2), sys.AMD64) - addF(simdPackage, "Mask64x4.AsInt64x4", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask64x4.ToInt64x4", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int64x4.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask64x4.And", opLen2(ssa.OpAndInt32x8, types.TypeVec256), sys.AMD64) addF(simdPackage, "Mask64x4.Or", opLen2(ssa.OpOrInt32x8, types.TypeVec256), sys.AMD64) addF(simdPackage, "Mask64x4FromBits", simdCvtVToMask(64, 4), sys.AMD64) addF(simdPackage, "Mask64x4.ToBits", simdCvtMaskToV(64, 4), sys.AMD64) - addF(simdPackage, "Mask64x8.AsInt64x8", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) + addF(simdPackage, "Mask64x8.ToInt64x8", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Int64x8.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "Mask64x8.And", opLen2(ssa.OpAndInt32x16, types.TypeVec512), sys.AMD64) addF(simdPackage, "Mask64x8.Or", opLen2(ssa.OpOrInt32x16, types.TypeVec512), sys.AMD64) diff --git a/src/cmd/compile/internal/test/testdata/arith_test.go b/src/cmd/compile/internal/test/testdata/arith_test.go index 34ac73c068dc6cc62102b6c9b3e722ec6880a390..6f53618b59432d4cf5dd3759b5eb7f5f91a00dc1 100644 --- a/src/cmd/compile/internal/test/testdata/arith_test.go +++ b/src/cmd/compile/internal/test/testdata/arith_test.go @@ -223,7 +223,7 @@ t.Errorf("arithConstShift_ssa(1) failed, wanted %d got %d", want, got) } } -// overflowConstShift_ssa verifies that constant folding for shift +// overflowConstShift64_ssa verifies that constant folding for shift // doesn't wrap (i.e. x << MAX_INT << 1 doesn't get folded to x << 0). // //go:noinline @@ -1408,7 +1408,7 @@ var ( // These have to be global to avoid getting constant-folded in the function body: // as locals, prove can see that they are actually constants. sixU, nineteenU uint64 = 6, 19 - sixS, nineteenS int64 = 6, 19 + sixS, nineteenS int64 = 6, 19 ) // testDivisibility confirms that rewrite rules x%c ==0 for c constant are correct. diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index 0162164679287677e716573f3defcaa8a2610a9c..1acb041e357ad7546bb55f8b269b30bc0d3383e2 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -471,11 +471,6 @@ st.floatRegs = 0 } else { st.floatRegs = 1 } - // if st.Sym() != nil { - // base.Warn("Simdify %s, %v, %d", st.Sym().Name, isTag, st.width) - // } else { - // base.Warn("Simdify %v, %v, %d", st, isTag, st.width) - // } } // CalcStructSize calculates the size of t, @@ -491,10 +486,9 @@ switch { case sym.Name == "align64" && isAtomicStdPkg(sym.Pkg): maxAlign = 8 - case buildcfg.Experiment.SIMD && (sym.Pkg.Path == "internal/simd" || sym.Pkg.Path == "simd") && len(t.Fields()) >= 1: + case buildcfg.Experiment.SIMD && (sym.Pkg.Path == "simd/archsimd") && len(t.Fields()) >= 1: // This gates the experiment -- without it, no user-visible types can be "simd". // The SSA-visible SIMD types remain. - // TODO after simd has been moved to package simd, remove internal/simd. switch sym.Name { case "v128": simdify(t, true) diff --git a/src/cmd/compile/internal/types2/cycles.go b/src/cmd/compile/internal/types2/cycles.go index b916219c979801d6d0a5b56b3ea7e75b7eca2e0f..84a05c96474b5666387e2c938c4744b31d4d81f4 100644 --- a/src/cmd/compile/internal/types2/cycles.go +++ b/src/cmd/compile/internal/types2/cycles.go @@ -102,3 +102,51 @@ assert(i < 0) } } } + +// TODO(markfreeman): Can the value cached on Named be used in validType / hasVarSize? + +// finiteSize returns whether a type has finite size. +func (check *Checker) finiteSize(t Type) bool { + switch t := Unalias(t).(type) { + case *Named: + if t.stateHas(hasFinite) { + return t.finite + } + + if i, ok := check.objPathIdx[t.obj]; ok { + cycle := check.objPath[i:] + check.cycleError(cycle, firstInSrc(cycle)) + return false + } + check.push(t.obj) + defer check.pop() + + isFinite := check.finiteSize(t.fromRHS) + + t.mu.Lock() + defer t.mu.Unlock() + // Careful, t.finite has lock-free readers. Since we might be racing + // another call to finiteSize, we have to avoid overwriting t.finite. + // Otherwise, the race detector will be tripped. + if !t.stateHas(hasFinite) { + t.finite = isFinite + t.setState(hasFinite) + } + + return isFinite + + case *Array: + // The array length is already computed. If it was a valid length, it + // is finite; else, an error was reported in the computation. + return check.finiteSize(t.elem) + + case *Struct: + for _, f := range t.fields { + if !check.finiteSize(f.typ) { + return false + } + } + } + + return true +} diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 637cbaee5d3ee63a5f926c9d868932199e90ca19..e3ef1af1ce35ca33f1aedab4bbffbb1a576653d4 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1041,12 +1041,9 @@ func (check *Checker) pendingType(x *operand) { if x.mode == invalid || x.mode == novalue { return } - if n, ok := Unalias(x.typ).(*Named); ok { - if i, ok := check.objPathIdx[n.obj]; ok { - check.cycleError(check.objPath, i) - x.mode = invalid - x.typ = Typ[Invalid] - } + if !check.finiteSize(x.typ) { + x.mode = invalid + x.typ = Typ[Invalid] } } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index edd6357248ec792a48be782ba1764805549a9647..2922fb55eba270d66730c46a635944ddd78269d7 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -117,6 +117,7 @@ state_ uint32 // the current state of this type; must only be accessed atomically or when mu is held fromRHS Type // the declaration RHS this type is derived from tparams *TypeParamList // type parameters, or nil underlying Type // underlying type, or nil + finite bool // whether the type has finite size // methods declared for this type (not the method set of this type) // Signatures are type-checked lazily. @@ -148,10 +149,11 @@ // lazyLoaded // unpacked // └── hasMethods // └── hasUnder +// └── hasFinite // // That is, descent down the tree is mostly linear (initial through unpacked), except upon -// reaching the leaves (hasMethods and hasUnder). A type may occupy any combination of the -// leaf states at once (they are independent states). +// reaching the leaves (hasMethods, hasUnder, and hasFinite). A type may occupy any +// combination of the leaf states at once (they are independent states). // // To represent this independence, the set of active states is represented with a bit set. State // transitions are monotonic. Once a state bit is set, it remains set. @@ -159,12 +161,14 @@ // // The above constraints significantly narrow the possible bit sets for a named type. With bits // set left-to-right, they are: // -// 0000 | initial -// 1000 | lazyLoaded -// 1100 | unpacked, which implies lazyLoaded -// 1110 | hasMethods, which implies unpacked (which in turn implies lazyLoaded) -// 1101 | hasUnder, which implies unpacked ... -// 1111 | both hasMethods and hasUnder which implies unpacked ... +// 00000 | initial +// 10000 | lazyLoaded +// 11000 | unpacked, which implies lazyLoaded +// 11100 | hasMethods, which implies unpacked (which in turn implies lazyLoaded) +// 11010 | hasUnder, which implies unpacked ... +// 11001 | hasFinite, which implies unpacked ... +// 11110 | both hasMethods and hasUnder which implies unpacked ... +// ... | (other combinations of leaf states) // // To read the state of a named type, use [Named.stateHas]; to write, use [Named.setState]. type stateMask uint32 @@ -175,6 +179,7 @@ lazyLoaded stateMask = 1 << iota // methods are available, but constraints might be unexpanded (for generic types) unpacked // methods might be unexpanded (for instances) hasMethods // methods are all expanded (for instances) hasUnder // underlying type is available + hasFinite // size finiteness is available ) // NewNamed returns a new named type for the given type name, underlying type, and associated methods. @@ -302,6 +307,10 @@ assert(u) } // hasUnder => unpacked if m&hasUnder != 0 { + assert(u) + } + // hasFinite => unpacked + if m&hasFinite != 0 { assert(u) } } diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go index f206c12fc3d7a99212519049e43757a7e6432b30..a3697b666c6f8557a9d40d929e64c0b2be20f15a 100644 --- a/src/cmd/compile/internal/types2/sizeof_test.go +++ b/src/cmd/compile/internal/types2/sizeof_test.go @@ -31,7 +31,7 @@ {Union{}, 12, 24}, {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 64, 120}, + {Named{}, 68, 128}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, diff --git a/src/cmd/compile/internal/types2/stdlib_test.go b/src/cmd/compile/internal/types2/stdlib_test.go index ad1974ad85fd78aea25e1f76f01da4f25b3bae17..ee49bbddfabb7f0b14ed5445738080e5e49cb35c 100644 --- a/src/cmd/compile/internal/types2/stdlib_test.go +++ b/src/cmd/compile/internal/types2/stdlib_test.go @@ -361,8 +361,8 @@ var excluded = map[string]bool{ "builtin": true, "cmd/compile/internal/ssa/_gen": true, "runtime/_mkmalloc": true, - "simd/_gen/simdgen": true, - "simd/_gen/unify": true, + "simd/archsimd/_gen/simdgen": true, + "simd/archsimd/_gen/unify": true, } // printPackageMu synchronizes the printing of type-checked package files in diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index f8d19ac34c562f6e71a7c384d58514e3586e1ede..6d3742525c68080885cdeaa0c222b6a977163ea3 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -762,6 +762,15 @@ pkg: "runtime/secret/...", }) } + // Test GOEXPERIMENT=simd on amd64. + if goarch == "amd64" && !strings.Contains(goexperiment, "simd") { + t.registerTest("GOEXPERIMENT=simd go test simd/archsimd/...", &goTest{ + variant: "simd", + env: []string{"GOEXPERIMENT=simd"}, + pkg: "simd/archsimd/...", + }) + } + // Test ios/amd64 for the iOS simulator. if goos == "darwin" && goarch == "amd64" && t.cgoEnabled { t.registerTest("GOOS=ios on darwin/amd64", @@ -1236,7 +1245,7 @@ } return t.internalLinkPIE() && t.extLink() } -// supportedBuildMode reports whether the given build mode is supported. +// supportedBuildmode reports whether the given build mode is supported. func (t *tester) supportedBuildmode(mode string) bool { switch mode { case "c-archive", "c-shared", "shared", "plugin", "pie": diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 90c3717334cd850b2d61af8536f0da1d2bd7b672..c7d3cc6136b5494e04f7a98a83a7f1b94682bb02 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -7,15 +7,15 @@ github.com/google/pprof v0.0.0-20251114195745-4902fdda35c8 golang.org/x/arch v0.23.0 golang.org/x/build v0.0.0-20251128064159-b9bfd88b30e8 golang.org/x/mod v0.30.1-0.20251115032019-269c237cf350 - golang.org/x/sync v0.18.0 - golang.org/x/sys v0.38.1-0.20251125153526-08e54827f670 + golang.org/x/sync v0.19.0 + golang.org/x/sys v0.39.0 golang.org/x/telemetry v0.0.0-20251128220624-abf20d0e57ec - golang.org/x/term v0.37.0 + golang.org/x/term v0.38.0 golang.org/x/tools v0.39.1-0.20251205000126-062ef7b6ced2 ) require ( github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b // indirect - golang.org/x/text v0.31.1-0.20251128220601-087616b6cde9 // indirect + golang.org/x/text v0.32.0 // indirect rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef // indirect ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 774820d54c19bde75d46c95cbe7c18564f3b9037..b02c469a41d244b4b045957c138cf503bb64f20e 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -12,16 +12,16 @@ golang.org/x/build v0.0.0-20251128064159-b9bfd88b30e8 h1:Mp+uRtHbKFW85lGBTOkOOfkPBz7AUKmZGcflkavmGRM= golang.org/x/build v0.0.0-20251128064159-b9bfd88b30e8/go.mod h1:Jx2RBBeTWGRSCwfSZ+w2Hg1f7LjWycsSkx+EciLAmPE= golang.org/x/mod v0.30.1-0.20251115032019-269c237cf350 h1:JGDMsCp8NahDR9HSvwrF6V8tzEf87m7Bo4oZ07vRxdU= golang.org/x/mod v0.30.1-0.20251115032019-269c237cf350/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= -golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= -golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.38.1-0.20251125153526-08e54827f670 h1:s8+qM6u6X24AFOioI7tH2p/6zxCHqt3G7zwUYm7MgUc= -golang.org/x/sys v0.38.1-0.20251125153526-08e54827f670/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20251128220624-abf20d0e57ec h1:dRVkWZl6bUOp+oxnOe4BuyhWSIPmt29N4ooHarm7Ic8= golang.org/x/telemetry v0.0.0-20251128220624-abf20d0e57ec/go.mod h1:hKdjCMrbv9skySur+Nek8Hd0uJ0GuxJIoIX2payrIdQ= -golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= -golang.org/x/text v0.31.1-0.20251128220601-087616b6cde9 h1:IjQf87/qLz2y0SiCc0uY3DwajALXkAgP1Pxal0mmdrM= -golang.org/x/text v0.31.1-0.20251128220601-087616b6cde9/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/tools v0.39.1-0.20251205000126-062ef7b6ced2 h1:2Qqv605Nus9iUp3ErvEU/q92Q3HAzeROztzl9pzAno8= golang.org/x/tools v0.39.1-0.20251205000126-062ef7b6ced2/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8= diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 1722f1a2c34428b2e023d7a217044eaa3f75d842..260c91e800b622944946b225874ab78427ce3d5e 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -972,19 +972,6 @@ tg.run("install", "p1") tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release") } -func TestPackageMainTestCompilerFlags(t *testing.T) { - tg := testgo(t) - defer tg.cleanup() - tg.parallel() - tg.makeTempdir() - tg.setenv("GOPATH", tg.path(".")) - tg.tempFile("src/p1/p1.go", "package main\n") - tg.tempFile("src/p1/p1_test.go", "package main\nimport \"testing\"\nfunc Test(t *testing.T){}\n") - tg.run("test", "-c", "-n", "p1") - tg.grepBothNot(`([\\/]compile|gccgo).* (-p main|-fgo-pkgpath=main).*p1\.go`, "should not have run compile -p main p1.go") - tg.grepStderr(`([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go`, "should have run compile -p p1 p1.go") -} - // Issue 4104. func TestGoTestWithPackageListedMultipleTimes(t *testing.T) { tooSlow(t, "links and runs a test") @@ -1068,43 +1055,6 @@ if tg.stdout.String() != want { t.Fatalf("list -deps math: wrong order\nhave %q\nwant %q", tg.stdout.String(), want) } } -} - -func TestGoListTest(t *testing.T) { - skipIfGccgo(t, "gccgo does not have standard packages") - tg := testgo(t) - defer tg.cleanup() - tg.parallel() - tg.makeTempdir() - tg.setenv("GOCACHE", tg.tempdir) - - tg.run("list", "-test", "-deps", "bytes") - tg.grepStdout(`^bytes.test$`, "missing test main") - tg.grepStdout(`^bytes$`, "missing real bytes") - tg.grepStdout(`^bytes \[bytes.test\]$`, "missing test copy of bytes") - tg.grepStdout(`^testing \[bytes.test\]$`, "missing test copy of testing") - tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing") - - tg.run("list", "-test", "bytes") - tg.grepStdout(`^bytes.test$`, "missing test main") - tg.grepStdout(`^bytes$`, "missing real bytes") - tg.grepStdout(`^bytes \[bytes.test\]$`, "unexpected test copy of bytes") - tg.grepStdoutNot(`^testing \[bytes.test\]$`, "unexpected test copy of testing") - tg.grepStdoutNot(`^testing$`, "unexpected real copy of testing") - - tg.run("list", "-test", "cmd/buildid", "cmd/gofmt") - tg.grepStdout(`^cmd/buildid$`, "missing cmd/buildid") - tg.grepStdout(`^cmd/gofmt$`, "missing cmd/gofmt") - tg.grepStdout(`^cmd/gofmt\.test$`, "missing cmd/gofmt test") - tg.grepStdoutNot(`^cmd/buildid\.test$`, "unexpected cmd/buildid test") - tg.grepStdoutNot(`^testing`, "unexpected testing") - - tg.run("list", "-test", "runtime/cgo") - tg.grepStdout(`^runtime/cgo$`, "missing runtime/cgo") - - tg.run("list", "-deps", "-f", "{{if .DepOnly}}{{.ImportPath}}{{end}}", "sort") - tg.grepStdout(`^internal/reflectlite$`, "missing internal/reflectlite") - tg.grepStdoutNot(`^sort`, "unexpected sort") } func TestGoListCompiledCgo(t *testing.T) { @@ -1526,40 +1476,6 @@ import "C" func main() {} `) tg.run("run", tg.path("bar.go")) -} - -func TestListTemplateContextFunction(t *testing.T) { - t.Parallel() - for _, tt := range []struct { - v string - want string - }{ - {"GOARCH", runtime.GOARCH}, - {"GOOS", runtime.GOOS}, - {"GOROOT", testGOROOT}, - {"GOPATH", os.Getenv("GOPATH")}, - {"CgoEnabled", ""}, - {"UseAllFiles", ""}, - {"Compiler", ""}, - {"BuildTags", ""}, - {"ReleaseTags", ""}, - {"InstallSuffix", ""}, - } { - tt := tt - t.Run(tt.v, func(t *testing.T) { - tg := testgo(t) - tg.parallel() - defer tg.cleanup() - tmpl := "{{context." + tt.v + "}}" - tg.run("list", "-f", tmpl) - if tt.want == "" { - return - } - if got := strings.TrimSpace(tg.getStdout()); got != tt.want { - t.Errorf("go list -f %q: got %q; want %q", tmpl, got, tt.want) - } - }) - } } // Test that you cannot use a local import in a package @@ -2245,23 +2161,6 @@ tg.setenv("GOCACHE", tg.path("c1")) tg.run("test", "-cover", "-short", "strings") tg.run("test", "-cover", "-short", "math", "strings") -} - -func TestIssue22588(t *testing.T) { - // Don't get confused by stderr coming from tools. - tg := testgo(t) - defer tg.cleanup() - tg.parallel() - - tg.wantNotStale("runtime", "", "must be non-stale to compare staleness under -toolexec") - - if _, err := os.Stat("/usr/bin/time"); err != nil { - t.Skip(err) - } - - tg.run("list", "-f={{.Stale}}", "runtime") - tg.run("list", "-toolexec=/usr/bin/time", "-f={{.Stale}}", "runtime") - tg.grepStdout("false", "incorrectly reported runtime as stale") } func TestIssue22531(t *testing.T) { diff --git a/src/cmd/go/internal/doc/doc_test.go b/src/cmd/go/internal/doc/doc_test.go index f91dcd658f247b6b966d9eaa77f7c2e60629de90..21b6da149a6d2f82722d38f32d8c55c5746c41dd 100644 --- a/src/cmd/go/internal/doc/doc_test.go +++ b/src/cmd/go/internal/doc/doc_test.go @@ -629,6 +629,35 @@ []string{ `Has unexported methods`, }, }, + // Interface with comparable constraint. + { + "interface type with comparable", + []string{p, `ExportedComparableInterface`}, + []string{ + `Comment about exported interface with comparable`, // Include comment. + `type ExportedComparableInterface interface`, // Interface definition. + `comparable.*Comment on line with comparable`, // Comparable should be shown. + `ExportedMethod\(\).*Comment on line with exported method`, + `Has unexported methods`, + }, + []string{ + `unexportedMethod`, // No unexported method. + }, + }, + // Interface with only comparable (no unexported methods). + { + "interface type with comparable only", + []string{p, `ExportedComparableOnlyInterface`}, + []string{ + `ExportedComparableOnlyInterface has only comparable`, // Include comment. + `type ExportedComparableOnlyInterface interface`, // Interface definition. + `comparable.*Comment on line with comparable`, // Comparable should be shown. + `ExportedMethod\(\).*Comment on line with exported method`, + }, + []string{ + `Has unexported methods`, // Should NOT appear - no unexported methods. + }, + }, // Interface method. { diff --git a/src/cmd/go/internal/doc/pkg.go b/src/cmd/go/internal/doc/pkg.go index 7b5e00365d04a12cd12de493fea5f270d1af0b25..3c36d0e05cfffcc0c072417def01b82cb66d0564 100644 --- a/src/cmd/go/internal/doc/pkg.go +++ b/src/cmd/go/internal/doc/pkg.go @@ -526,7 +526,7 @@ } } } -// funcsDoc prints all type documentation, if any, including a header. +// typesDoc prints all type documentation, if any, including a header. func (pkg *Package) typesDoc() { var header bool for _, typ := range pkg.doc.Types { @@ -947,10 +947,11 @@ } constraint := false switch ident := ty.(type) { case *ast.Ident: - if isInterface && ident.Name == "error" && ident.Obj == nil { + if isInterface && ident.Obj == nil && + (ident.Name == "error" || ident.Name == "comparable") { // For documentation purposes, we consider the builtin error - // type special when embedded in an interface, such that it - // always gets shown publicly. + // and comparable types special when embedded in an interface, + // such that they always get shown publicly. list = append(list, field) continue } diff --git a/src/cmd/go/internal/doc/testdata/pkg.go b/src/cmd/go/internal/doc/testdata/pkg.go index 4d269ff0a2295908a7df7313b25ac7b88bdb2566..53b018318f3cc738a0025fdacb15a8b69402306a 100644 --- a/src/cmd/go/internal/doc/testdata/pkg.go +++ b/src/cmd/go/internal/doc/testdata/pkg.go @@ -252,3 +252,16 @@ type StructConstraint interface { struct { F int } } + +// Comment about exported interface with comparable. +type ExportedComparableInterface interface { + comparable // Comment on line with comparable. + ExportedMethod() // Comment on line with exported method. + unexportedMethod() // Comment on line with unexported method. +} + +// ExportedComparableOnlyInterface has only comparable and exported method (no unexported). +type ExportedComparableOnlyInterface interface { + comparable // Comment on line with comparable. + ExportedMethod() // Comment on line with exported method. +} diff --git a/src/cmd/go/internal/generate/generate_test.go b/src/cmd/go/internal/generate/generate_test.go index 2eef917e7e275883a22974667145768ffe2e5037..b11ed505450ba8a30adeccc4c92bf7ab086851ce 100644 --- a/src/cmd/go/internal/generate/generate_test.go +++ b/src/cmd/go/internal/generate/generate_test.go @@ -79,7 +79,7 @@ "_PLUGH_": "SomeVal", "_X": "Y", } -// TestGenerateCommandShortHand - similar to TestGenerateCommandParse, +// TestGenerateCommandShorthand - similar to TestGenerateCommandParse, // except: // 1. if the result starts with -command, record that shorthand // before moving on to the next test. diff --git a/src/cmd/go/internal/vet/vet.go b/src/cmd/go/internal/vet/vet.go index 34d904cffc61f85bc495d441e2b0a1a329383540..e7d01782bf2f6c6feebd0ec22fe28a6ffa2461f9 100644 --- a/src/cmd/go/internal/vet/vet.go +++ b/src/cmd/go/internal/vet/vet.go @@ -262,6 +262,15 @@ // We needn't worry about intermediate test variants, as they // will only be executed in VetxOnly mode, for facts but not // diagnostics. for _, p := range pkgs { + // Don't apply fixes to vendored packages, including + // the GOROOT vendor packages that are part of std, + // or to packages from non-main modules (#76479). + if applyFixes { + if p.Standard && strings.HasPrefix(p.ImportPath, "vendor/") || + p.Module != nil && !p.Module.Main { + continue + } + } _, ptest, pxtest, perr := load.TestPackagesFor(moduleLoaderState, ctx, pkgOpts, p, nil) if perr != nil { base.Errorf("%v", perr.Error) diff --git a/src/cmd/go/testdata/script/fix_vendor.txt b/src/cmd/go/testdata/script/fix_vendor.txt new file mode 100644 index 0000000000000000000000000000000000000000..f03f3269221a9812f01bfba6e09736795cb82bef --- /dev/null +++ b/src/cmd/go/testdata/script/fix_vendor.txt @@ -0,0 +1,44 @@ +# Test that go fix skips fixes to non-main and/or vendored packages. +# (It uses the interface{} -> any modernizer.) + +# Create vendor tree programmatically to avoid +# having to hardcode sums in this txtar archive. +go mod vendor + +# Show fixes on two packages, one in the main module +# and one in a vendored dependency. +# Only the main one (a) is shown. +go fix -diff example.com/a example.com/b +stdout 'a[/\\]a.go' +stdout '\-var _ interface\{\}' +stdout '\+var _ any' +! stdout 'b[/\\]b.go' + +# Apply fixes to the same two packages. +# Only the main module was modified. +go fix example.com/a example.com/b +grep 'var _ any' a/a.go +grep 'var _ interface{}' b/b.go +grep 'var _ interface{}' vendor/example.com/b/b.go + +-- go.mod -- +module example.com +go 1.26 + +require "example.com/b" v0.0.0 +replace "example.com/b" => ./b + +-- a/a.go -- +package a + +import _ "example.com/b" + +var _ interface{} + +-- b/go.mod -- +module example.com/b + +-- b/b.go -- +package b + +var _ interface{} diff --git a/src/cmd/go/testdata/script/list_template_context_function.txt b/src/cmd/go/testdata/script/list_template_context_function.txt new file mode 100644 index 0000000000000000000000000000000000000000..70c47c87f8e27c973c3b38db639b39781216ace3 --- /dev/null +++ b/src/cmd/go/testdata/script/list_template_context_function.txt @@ -0,0 +1,15 @@ +# This is a script test conversion of TestListTemplateContextFunction +# originally added in CL 20010, which fixed #14547. +# Test the ability to use the build context in the go list template. + +go list -f '{{context.GOARCH}} {{context.GOOS}} {{context.GOROOT}} {{context.GOPATH}}' +cmpenv stdout want.txt + +go list -f '{{context.CgoEnabled}} {{context.UseAllFiles}} {{context.Compiler}} {{context.BuildTags}} {{context.ReleaseTags}} {{context.InstallSuffix}}' + +-- go.mod -- +module foo +-- foo.go -- +package foo +-- want.txt -- +$GOARCH $GOOS $GOROOT $GOPATH diff --git a/src/cmd/go/testdata/script/list_test.txt b/src/cmd/go/testdata/script/list_test.txt new file mode 100644 index 0000000000000000000000000000000000000000..f65cd80db2b651776e054bfadce90721fa48b4e2 --- /dev/null +++ b/src/cmd/go/testdata/script/list_test.txt @@ -0,0 +1,33 @@ +# This is a script test conversion of TestGoListTest which was added in +# CL 107916, which added support for go list -test. +# Test the behavior of go list -test. + +[compiler:gccgo] skip 'gccgo does not have standard packages' + +go list -test -deps bytes +stdout '^bytes.test$' # test main +stdout '^bytes$' # real bytes +stdout '^bytes \[bytes.test\]$' # test copy of bytes +stdout 'testing \[bytes.test\]$' # test copy of testing +! stdout ^testing$ # should not have real testing + +go list -test bytes +stdout '^bytes.test$' # test main +stdout '^bytes$' # real bytes +stdout '^bytes \[bytes.test\]$' # test copy of bytes +! stdout '^testing \[bytes.test\]$' # should not have test copy of testing +! stdout '^testing$' # should not have real testing + +go list -test cmd/buildid cmd/gofmt +stdout '^cmd/buildid$' # cmd/buildid +stdout '^cmd/gofmt$' # cmd/gofmt +stdout '^cmd/gofmt\.test$' # cmd/gofmt test +! stdout '^cmd/buildid\.test$' # should not have cmd/buildid test +! stdout '^testing' # should not have real testing + +go list -test runtime/cgo +stdout '^runtime/cgo$' # runtime/cgo + +go list -deps -f '{{if .DepOnly}}{{.ImportPath}}{{end}}' sort +stdout '^internal/reflectlite$' # internal/reflectlite +! stdout '^sort' # should not have sort diff --git a/src/cmd/go/testdata/script/list_toolexec_stderr_issue22588.txt b/src/cmd/go/testdata/script/list_toolexec_stderr_issue22588.txt new file mode 100644 index 0000000000000000000000000000000000000000..dd2eaed2a1f1b2ccd7336d405916ba998ed1ef82 --- /dev/null +++ b/src/cmd/go/testdata/script/list_toolexec_stderr_issue22588.txt @@ -0,0 +1,11 @@ +# This is a script test conversion of TestIssue22588 which was added in CL 76017. +# Test that the stderr of a tool run under toolexec doesn't affect caching. + +# Don't get confused by stderr coming from tools. +[!exec:/usr/bin/time] skip + +! stale runtime 'must be non-stale to compare staleness under -toolexec' + +go list -f '{{.Stale}}' runtime +go list -toolexec /usr/bin/time -f '{{.Stale}}' runtime +stdout 'false' # runtime should not be reported as stale \ No newline at end of file diff --git a/src/cmd/go/testdata/script/test_main_compiler_flags.txt b/src/cmd/go/testdata/script/test_main_compiler_flags.txt new file mode 100644 index 0000000000000000000000000000000000000000..e207ecae16ac92905ac977cea8df94e1db0385e8 --- /dev/null +++ b/src/cmd/go/testdata/script/test_main_compiler_flags.txt @@ -0,0 +1,22 @@ +# This is a script test conversion of TestPackageMainTestCompilerFlags +# originally added in CL 86265, which fixed #23180. +# Test that we don't pass the package name 'main' to -p when building the +# test package for a main package. + +go test -c -n p1 +# should not have run compile -p main p1.go +! stdout '([\\/]compile|gccgo).* (-p main|-fgo-pkgpath=main).*p1\.go' +! stderr '([\\/]compile|gccgo).* (-p main|-fgo-pkgpath=main).*p1\.go' +# should have run compile -p p1 p1.go +stderr '([\\/]compile|gccgo).* (-p p1|-fgo-pkgpath=p1).*p1\.go' + +-- go.mod -- +module p1 +-- p1.go -- +package main +-- p1_test.go -- +package main + +import "testing" + +func Test(t *testing.T){} diff --git a/src/cmd/go/testdata/script/vet_asm.txt b/src/cmd/go/testdata/script/vet_asm.txt index c046773a06c0dc122fa0cfeed168255307a110d8..f29e5b7067e1e386ffe4694ff3b5ac617190da37 100644 --- a/src/cmd/go/testdata/script/vet_asm.txt +++ b/src/cmd/go/testdata/script/vet_asm.txt @@ -2,6 +2,7 @@ # Issue 27665. Verify that "go vet" analyzes non-Go files. env GO111MODULE=off env GOARCH=amd64 +env GOOS=linux ! go vet -asmdecl a stderr 'f: invalid MOVW of x' diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go index d9916ae07999cd00bd08a5fbdb9785c63a881156..3900ae065457caf70c105db696d9a58e9da2d76b 100644 --- a/src/cmd/link/dwarf_test.go +++ b/src/cmd/link/dwarf_test.go @@ -156,7 +156,99 @@ } if !strings.HasSuffix(line.File.Name, wantFile) || line.Line != wantLine { t.Errorf("%#x is %s:%d, want %s:%d", addr, line.File.Name, line.Line, filepath.Join("...", wantFile), wantLine) } + + if buildmode != "c-archive" { + testModuledata(t, d) + } }) + } +} + +// testModuledata makes sure that runtime.firstmoduledata exists +// and has a type. Issue #76731. +func testModuledata(t *testing.T, d *dwarf.Data) { + const symName = "runtime.firstmoduledata" + + r := d.Reader() + for { + e, err := r.Next() + if err != nil { + t.Error(err) + return + } + if e == nil { + t.Errorf("did not find DWARF entry for %s", symName) + return + } + + switch e.Tag { + case dwarf.TagVariable: + // carry on after switch + case dwarf.TagCompileUnit, dwarf.TagSubprogram: + continue + default: + r.SkipChildren() + continue + } + + nameIdx, typeIdx := -1, -1 + for i := range e.Field { + f := &e.Field[i] + switch f.Attr { + case dwarf.AttrName: + nameIdx = i + case dwarf.AttrType: + typeIdx = i + } + } + if nameIdx == -1 { + // unnamed variable? + r.SkipChildren() + continue + } + nameStr, ok := e.Field[nameIdx].Val.(string) + if !ok { + // variable name is not a string? + r.SkipChildren() + continue + } + if nameStr != symName { + r.SkipChildren() + continue + } + + if typeIdx == -1 { + t.Errorf("%s has no DWARF type", symName) + return + } + off, ok := e.Field[typeIdx].Val.(dwarf.Offset) + if !ok { + t.Errorf("unexpected Go type %T for DWARF type for %s; expected %T", e.Field[typeIdx].Val, symName, dwarf.Offset(0)) + return + } + + typeInfo, err := d.Type(off) + if err != nil { + t.Error(err) + return + } + + typeName := typeInfo.Common().Name + if want := "runtime.moduledata"; typeName != want { + t.Errorf("type of %s is %s, expected %s", symName, typeName, want) + } + for { + typedef, ok := typeInfo.(*dwarf.TypedefType) + if !ok { + break + } + typeInfo = typedef.Type + } + if _, ok := typeInfo.(*dwarf.StructType); !ok { + t.Errorf("type of %s is %T, expected %T", symName, typeInfo, dwarf.StructType{}) + } + + return } } diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index ff0fa5c377db7c47facba5edb2e98b8dcbbde1bb..5cd39fbc53eb90de0ccd2da365a81d9979c42f7d 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -2036,7 +2036,7 @@ } t := d.ldr.SymType(idx) switch { case t.IsRODATA(), t.IsDATA(), t.IsNOPTRDATA(), - t == sym.STYPE, t == sym.SBSS, t == sym.SNOPTRBSS, t == sym.STLSBSS: + t == sym.STYPE, t == sym.SBSS, t == sym.SNOPTRBSS, t == sym.STLSBSS, t == sym.SMODULEDATA: // ok default: continue diff --git a/src/cmd/link/internal/ld/fips140.go b/src/cmd/link/internal/ld/fips140.go index c1887ee50a337eb5a93a170b564ed481aa4b8f84..8ab6f39910248296ee30b2f513e57f72891ebf62 100644 --- a/src/cmd/link/internal/ld/fips140.go +++ b/src/cmd/link/internal/ld/fips140.go @@ -398,7 +398,7 @@ } return f.Close() } -// machofips updates go:fipsinfo after external linking +// elffips updates go:fipsinfo after external linking // on systems using ELF (most Unix systems). func elffips(ctxt *Link, exe, fipso string) error { // Open executable both for reading ELF and for the fipsObj. diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 22ee13dff87eca7c5768ff9c788e1dc3d2fdc5b1..bcad5add4abe19bc7a533eed16d217eab2b4401e 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -38,6 +38,7 @@ "encoding/base64" "encoding/binary" "fmt" "internal/buildcfg" + "internal/platform" "io" "log" "os" @@ -576,7 +577,8 @@ iscgo = ctxt.LibraryByPkg["runtime/cgo"] != nil // Plugins a require cgo support to function. Similarly, plugins may require additional // internal linker support on some platforms which may not be implemented. - ctxt.canUsePlugins = ctxt.LibraryByPkg["plugin"] != nil && iscgo + ctxt.canUsePlugins = ctxt.LibraryByPkg["plugin"] != nil && iscgo && + platform.BuildModeSupported("gc", "plugin", buildcfg.GOOS, buildcfg.GOARCH) // We now have enough information to determine the link mode. determineLinkMode(ctxt) diff --git a/src/cmd/link/internal/ld/pcln.go b/src/cmd/link/internal/ld/pcln.go index 1eb7112e64415548401cab844d5bb27986cb3a06..08c4d4db830949cbf83d812adaf92d4ca39fa33e 100644 --- a/src/cmd/link/internal/ld/pcln.go +++ b/src/cmd/link/internal/ld/pcln.go @@ -55,13 +55,20 @@ } // addGeneratedSym adds a generator symbol to pclntab, returning the new Sym. // It is the caller's responsibility to save the symbol in state. -func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, f generatorFunc) loader.Sym { +func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, align int32, f generatorFunc) loader.Sym { size = Rnd(size, int64(ctxt.Arch.PtrSize)) state.size += size s := ctxt.createGeneratorSymbol(name, 0, sym.SPCLNTAB, size, f) - ctxt.loader.SetAttrReachable(s, true) - ctxt.loader.SetCarrierSym(s, state.carrier) - ctxt.loader.SetAttrNotInSymbolTable(s, true) + ldr := ctxt.loader + ldr.SetSymAlign(s, align) + ldr.SetAttrReachable(s, true) + ldr.SetCarrierSym(s, state.carrier) + ldr.SetAttrNotInSymbolTable(s, true) + + if align > ldr.SymAlign(state.carrier) { + ldr.SetSymAlign(state.carrier, align) + } + return s } @@ -277,7 +284,7 @@ panic(fmt.Sprintf("pcHeader size: %d != %d", off, size)) } } - state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader) + state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, int32(ctxt.Arch.PtrSize), writeHeader) } // walkFuncs iterates over the funcs, calling a function for each unique @@ -326,7 +333,7 @@ nameOffsets[s] = uint32(size) size += int64(len(ctxt.loader.SymName(s)) + 1) // NULL terminate }) - state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, writeFuncNameTab) + state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, 1, writeFuncNameTab) return nameOffsets } @@ -442,7 +449,7 @@ off = sb.SetUint32(ctxt.Arch, off, fileOffset) } } } - state.cutab = state.addGeneratedSym(ctxt, "runtime.cutab", int64(totalEntries*4), writeCutab) + state.cutab = state.addGeneratedSym(ctxt, "runtime.cutab", int64(totalEntries*4), 4, writeCutab) // Write filetab. writeFiletab := func(ctxt *Link, s loader.Sym) { @@ -454,7 +461,7 @@ sb.AddStringAt(int64(loc), expandFile(filename)) } } state.nfiles = uint32(len(fileOffsets)) - state.filetab = state.addGeneratedSym(ctxt, "runtime.filetab", fileSize, writeFiletab) + state.filetab = state.addGeneratedSym(ctxt, "runtime.filetab", fileSize, 1, writeFiletab) return cuOffsets } @@ -518,7 +525,7 @@ sb.SetBytesAt(ldr.SymValue(sym), ldr.Data(sym)) } } - state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, writePctab) + state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, 1, writePctab) } // generateFuncdata writes out the funcdata information. @@ -647,7 +654,7 @@ resolveRelocs(ldr, fdSym, sb.Data()[off:off+int64(len(fdSymData))]) } } - state.funcdata = state.addGeneratedSym(ctxt, "go:func.*", size, writeFuncData) + state.funcdata = state.addGeneratedSym(ctxt, "go:func.*", size, maxAlign, writeFuncData) // Because the funcdata previously was not in pclntab, // we need to keep the visible symbol so that tools can find it. @@ -703,7 +710,7 @@ // Write the data. writePCToFunc(ctxt, sb, funcs, startLocations) writeFuncs(ctxt, sb, funcs, inlSyms, startLocations, cuOffsets, nameOffsets) } - state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, writePcln) + state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, 4, writePcln) } // funcData returns the funcdata and offsets for the FuncInfo. @@ -967,6 +974,10 @@ ldr.MakeSymbolUpdater(state.carrier).SetType(sym.SPCLNTAB) ldr.SetAttrReachable(state.carrier, true) setCarrierSym(sym.SPCLNTAB, state.carrier) + // Aign pclntab to at least a pointer boundary, + // for pcHeader. This may be raised further by subsymbols. + ldr.SetSymAlign(state.carrier, int32(ctxt.Arch.PtrSize)) + state.generatePCHeader(ctxt) nameOffsets := state.generateFuncnametab(ctxt, funcs) cuOffsets := state.generateFilenameTabs(ctxt, compUnits, funcs) @@ -1076,6 +1087,7 @@ } } state.findfunctab = ctxt.createGeneratorSymbol("runtime.findfunctab", 0, sym.SPCLNTAB, size, writeFindFuncTab) + ldr.SetSymAlign(state.findfunctab, 4) ldr.SetAttrReachable(state.findfunctab, true) ldr.SetAttrLocal(state.findfunctab, true) } diff --git a/src/cmd/link/internal/ld/symtab.go b/src/cmd/link/internal/ld/symtab.go index f9bc7007eda0bbb730423bb6a0ce9e1dd70ef366..67b1f11c60bdd860bee95f742a788d3e8a4c4cec 100644 --- a/src/cmd/link/internal/ld/symtab.go +++ b/src/cmd/link/internal/ld/symtab.go @@ -656,6 +656,7 @@ moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.types", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.etypes", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.rodata", 0)) moduledata.AddAddr(ctxt.Arch, ldr.Lookup("go:func.*", 0)) + moduledata.AddAddr(ctxt.Arch, ldr.Lookup("runtime.epclntab", 0)) if ctxt.IsAIX() && ctxt.IsExternal() { // Add R_XCOFFREF relocation to prevent ld's garbage collection of @@ -672,6 +673,7 @@ } addRef("runtime.rodata") addRef("runtime.erodata") addRef("runtime.epclntab") + addRef("go:func.*") // As we use relative addressing for text symbols in functab, it is // important that the offsets we computed stay unchanged by the external // linker, i.e. all symbols in Textp should not be removed. diff --git a/src/cmd/link/internal/ld/xcoff.go b/src/cmd/link/internal/ld/xcoff.go index 77ae1236c9c0105a147b0a6fabe9e63ff9ec59ad..5f01eb2507dd5e9db15d79d84fa0c3007f2250bb 100644 --- a/src/cmd/link/internal/ld/xcoff.go +++ b/src/cmd/link/internal/ld/xcoff.go @@ -603,14 +603,20 @@ case sym.SGOSTRING: outerSymSize["go:string.*"] = size case sym.SGOFUNC: if !ctxt.DynlinkingGo() { - outerSymSize["go:func.*"] = size + outerSymSize["go:funcdesc"] = size } case sym.SGOFUNCRELRO: - outerSymSize["go:funcrel.*"] = size + outerSymSize["go:funcdescrel"] = size case sym.SGCBITS: outerSymSize["runtime.gcbits.*"] = size case sym.SPCLNTAB: - outerSymSize["runtime.pclntab"] = size + // go:func.* size must be removed from pclntab, + // as it's a real symbol. Same for runtime.findfunctab. + fsize := ldr.SymSize(ldr.Lookup("go:func.*", 0)) + fft := ldr.Lookup("runtime.findfunctab", 0) + fsize = Rnd(fsize, int64(symalign(ldr, fft))) + tsize := ldr.SymSize(fft) + outerSymSize["runtime.pclntab"] = size - (fsize + tsize) } } diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 9ab55643f6313d457f2a11332413496f2cc9fc81..9ac2b9201d3e3b4534c6e41696d4fa7b68d7e754 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -2420,6 +2420,7 @@ "internal/runtime/maps.errNilAssign": {"internal/runtime/maps"}, "internal/runtime/maps.fatal": {"internal/runtime/maps"}, "internal/runtime/maps.newarray": {"internal/runtime/maps"}, "internal/runtime/maps.newobject": {"internal/runtime/maps"}, + "internal/runtime/maps.rand": {"internal/runtime/maps"}, "internal/runtime/maps.typedmemclr": {"internal/runtime/maps"}, "internal/runtime/maps.typedmemmove": {"internal/runtime/maps"}, "internal/sync.fatal": {"internal/sync"}, @@ -2461,14 +2462,34 @@ "runtime/trace.runtime_traceClockUnitsPerSecond": {"runtime/trace"}, "sync_test.runtime_blockUntilEmptyCleanupQueue": {"sync_test"}, "time.runtimeIsBubbled": {"time"}, "unique.runtime_blockUntilEmptyCleanupQueue": {"unique"}, - // Experimental features - "runtime.goroutineLeakGC": {"runtime/pprof"}, - "runtime.goroutineleakcount": {"runtime/pprof"}, - "runtime.freegc": {}, // disallow all packages // Others "net.newWindowsFile": {"net"}, // pushed from os "testing/synctest.testingSynctestTest": {"testing/synctest"}, // pushed from testing - "runtime.addmoduledata": {}, // disallow all packages + // New internal linknames in Go 1.26 + // Pushed from runtime + "crypto/fips140.isBypassed": {"crypto/fips140"}, + "crypto/fips140.setBypass": {"crypto/fips140"}, + "crypto/fips140.unsetBypass": {"crypto/fips140"}, + "crypto/subtle.setDITEnabled": {"crypto/subtle"}, + "crypto/subtle.setDITDisabled": {"crypto/subtle"}, + "internal/cpu.sysctlbynameBytes": {"internal/cpu"}, + "internal/cpu.sysctlbynameInt32": {"internal/cpu"}, + "runtime.pprof_goroutineLeakProfileWithLabels": {"runtime/pprof"}, + "runtime/pprof.runtime_goroutineLeakGC": {"runtime/pprof"}, + "runtime/pprof.runtime_goroutineleakcount": {"runtime/pprof"}, + "runtime/secret.appendSignalStacks": {"runtime/secret"}, + "runtime/secret.count": {"runtime/secret"}, + "runtime/secret.dec": {"runtime/secret"}, + "runtime/secret.eraseSecrets": {"runtime/secret"}, + "runtime/secret.getStack": {"runtime/secret"}, + "runtime/secret.inc": {"runtime/secret"}, + "syscall.rawsyscalln": {"syscall"}, + "syscall.runtimeClearenv": {"syscall"}, + "syscall.syscalln": {"syscall"}, + // Others + "crypto/internal/rand.SetTestingReader": {"testing/cryptotest"}, // pushed from crypto/internal/rand + "testing.checkParallel": {"testing/cryptotest"}, // pushed from testing + "runtime.addmoduledata": {}, // assembly symbol, disallow all packages } // check if a linkname reference to symbol s from pkg is allowed diff --git a/src/cmd/link/internal/loader/loader_test.go b/src/cmd/link/internal/loader/loader_test.go index 541f42b7d1a99a9a674c689aa63cfc2ed42d2159..7f7a75d9f4330b3ce1810cd51f3f843d1a4a944b 100644 --- a/src/cmd/link/internal/loader/loader_test.go +++ b/src/cmd/link/internal/loader/loader_test.go @@ -14,7 +14,7 @@ "fmt" "testing" ) -// dummyAddSym adds the named symbol to the loader as if it had been +// addDummyObjSym adds the named symbol to the loader as if it had been // read from a Go object file. Note that it allocates a global // index without creating an associated object reader, so one can't // do anything interesting with this symbol (such as look at its diff --git a/src/cmd/link/internal/x86/asm.go b/src/cmd/link/internal/x86/asm.go index 036514819a0b0684981dc4f68ef7a8fe381dd4da..2c38473702f646052cb6ca1d1371ee8439b5bfb3 100644 --- a/src/cmd/link/internal/x86/asm.go +++ b/src/cmd/link/internal/x86/asm.go @@ -72,6 +72,9 @@ {"si", 6}, {"di", 7}, } { thunkfunc := ldr.CreateSymForUpdate("__x86.get_pc_thunk."+r.name, 0) + if t := thunkfunc.Type(); t != 0 && t != sym.SXREF && t != sym.SDYNIMPORT && t != sym.SUNDEFEXT { + continue // symbol already exists, probably loaded from a C object + } thunkfunc.SetType(sym.STEXT) ldr.SetAttrLocal(thunkfunc.Sym(), true) o := func(op ...uint8) { diff --git a/src/cmd/link/link_test.go b/src/cmd/link/link_test.go index 0c4cde0399fbd5457b1410735bee06163b1ee04a..bc7504e5b1c39a536a0e5bcf95689b0b015929cc 100644 --- a/src/cmd/link/link_test.go +++ b/src/cmd/link/link_test.go @@ -1960,33 +1960,55 @@ case xf != nil: defer xf.Close() + var moddataSym, gofuncSym, pclntabSym, epclntabSym *xcoff.Symbol for _, sym := range xf.Symbols { switch sym.Name { case moddataSymName: - moddataAddr = sym.Value + moddataSym = sym case gofuncSymName: - gofuncAddr = sym.Value + gofuncSym = sym + case "runtime.pclntab": + pclntabSym = sym + case "runtime.epclntab": + epclntabSym = sym } } - for _, sec := range xf.Sections { - if sec.Name == ".go.pclntab" { - data, err := sec.Data() - if err != nil { - t.Fatal(err) - } - pclntab = data - pclntabAddr = sec.VirtualAddress - pclntabEnd = sec.VirtualAddress + sec.Size - } - if moddataAddr >= sec.VirtualAddress && moddataAddr < sec.VirtualAddress+sec.Size { - data, err := sec.Data() - if err != nil { - t.Fatal(err) - } - moddataBytes = data[moddataAddr-sec.VirtualAddress:] - } + if moddataSym == nil { + t.Fatalf("could not find symbol %s", moddataSymName) } + if gofuncSym == nil { + t.Fatalf("could not find symbol %s", gofuncSymName) + } + if pclntabSym == nil { + t.Fatal("could not find symbol runtime.pclntab") + } + if epclntabSym == nil { + t.Fatal("could not find symbol runtime.epclntab") + } + + sec := xf.Sections[moddataSym.SectionNumber-1] + data, err := sec.Data() + if err != nil { + t.Fatal(err) + } + moddataBytes = data[moddataSym.Value:] + moddataAddr = uint64(sec.VirtualAddress + moddataSym.Value) + + sec = xf.Sections[gofuncSym.SectionNumber-1] + gofuncAddr = uint64(sec.VirtualAddress + gofuncSym.Value) + + if pclntabSym.SectionNumber != epclntabSym.SectionNumber { + t.Fatalf("runtime.pclntab section %d != runtime.epclntab section %d", pclntabSym.SectionNumber, epclntabSym.SectionNumber) + } + sec = xf.Sections[pclntabSym.SectionNumber-1] + data, err = sec.Data() + if err != nil { + t.Fatal(err) + } + pclntab = data[pclntabSym.Value:epclntabSym.Value] + pclntabAddr = uint64(sec.VirtualAddress + pclntabSym.Value) + pclntabEnd = uint64(sec.VirtualAddress + epclntabSym.Value) default: panic("can't happen") @@ -2183,31 +2205,16 @@ break } } - case pf != nil: - defer pf.Close() + case pf != nil, xf != nil: + if pf != nil { + defer pf.Close() + } + if xf != nil { + defer xf.Close() + } - // On Windows all the Go specific sections seem to - // get stuffed into a few Windows sections, + // On Windows and AIX all the Go specific sections + // get stuffed into a few sections, // so there is nothing to test here. - - case xf != nil: - defer xf.Close() - - for _, sym := range xf.Symbols { - if sym.Name == moddataSymName { - if sym.SectionNumber == 0 { - t.Errorf("moduledata not in a section") - } else { - sec := xf.Sections[sym.SectionNumber-1] - if sec.Name != ".go.module" { - t.Errorf("moduledata in section %s, not .go.module", sec.Name) - } - if sym.Value != sec.VirtualAddress { - t.Errorf("moduledata address %#x != section start address %#x", sym.Value, sec.VirtualAddress) - } - } - break - } - } } } diff --git a/src/cmd/nm/nm_test.go b/src/cmd/nm/nm_test.go index f740a3f738a86665d8fad12c661a825250209e9e..424ac72e228db81ba583df66ee023aaf34af240c 100644 --- a/src/cmd/nm/nm_test.go +++ b/src/cmd/nm/nm_test.go @@ -118,11 +118,6 @@ "runtime.epclntab": "R", "runtime.noptrdata": "D", } - if runtime.GOOS == "aix" && iscgo { - // pclntab is moved to .data section on AIX. - runtimeSyms["runtime.epclntab"] = "D" - } - out, err = testenv.Command(t, testenv.Executable(t), exe).CombinedOutput() if err != nil { t.Fatalf("go tool nm: %v\n%s", err, string(out)) diff --git a/src/cmd/vendor/golang.org/x/sync/errgroup/errgroup.go b/src/cmd/vendor/golang.org/x/sync/errgroup/errgroup.go index 2f45dbc86e5381cafc2a7b6226d68d3e1a79dc6c..f69fd754685a44420615b5224b3a351add5a3578 100644 --- a/src/cmd/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/src/cmd/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -144,8 +144,8 @@ if n < 0 { g.sem = nil return } - if len(g.sem) != 0 { - panic(fmt.Errorf("errgroup: modify limit while %v goroutines in the group are still active", len(g.sem))) + if active := len(g.sem); active != 0 { + panic(fmt.Errorf("errgroup: modify limit while %v goroutines in the group are still active", active)) } g.sem = make(chan token, n) } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 7e48798071ff8fd55f77108c1e9148c793a23a99..7c122cd9d171bf957157233cbdb5163a9c4eba38 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -39,11 +39,11 @@ golang.org/x/mod/sumdb/dirhash golang.org/x/mod/sumdb/note golang.org/x/mod/sumdb/tlog golang.org/x/mod/zip -# golang.org/x/sync v0.18.0 +# golang.org/x/sync v0.19.0 ## explicit; go 1.24.0 golang.org/x/sync/errgroup golang.org/x/sync/semaphore -# golang.org/x/sys v0.38.1-0.20251125153526-08e54827f670 +# golang.org/x/sys v0.39.0 ## explicit; go 1.24.0 golang.org/x/sys/plan9 golang.org/x/sys/unix @@ -60,10 +60,10 @@ golang.org/x/telemetry/internal/crashmonitor golang.org/x/telemetry/internal/mmap golang.org/x/telemetry/internal/telemetry golang.org/x/telemetry/internal/upload -# golang.org/x/term v0.37.0 +# golang.org/x/term v0.38.0 ## explicit; go 1.24.0 golang.org/x/term -# golang.org/x/text v0.31.1-0.20251128220601-087616b6cde9 +# golang.org/x/text v0.32.0 ## explicit; go 1.24.0 golang.org/x/text/cases golang.org/x/text/internal diff --git a/src/compress/bzip2/bzip2_test.go b/src/compress/bzip2/bzip2_test.go index e6065cb43fda774e0cf2a03cb6b83f075bb318ef..13e2d3c1fa94e2800cf06b6c4b832c90c3ab457d 100644 --- a/src/compress/bzip2/bzip2_test.go +++ b/src/compress/bzip2/bzip2_test.go @@ -8,8 +8,10 @@ import ( "bytes" "encoding/hex" "fmt" + "internal/obscuretestdata" "io" "os" + "strings" "testing" ) @@ -22,6 +24,14 @@ return b } func mustLoadFile(f string) []byte { + if strings.HasSuffix(f, ".base64") { + tf, err := obscuretestdata.DecodeToTempFile(f) + if err != nil { + panic(fmt.Sprintf("obscuretestdata.DecodeToTempFile(%s): %v", f, err)) + } + f = tf + } + b, err := os.ReadFile(f) if err != nil { panic(err) @@ -106,7 +116,7 @@ return b }(), }, { desc: "RLE2 buffer overrun - issue 5747", - input: mustLoadFile("testdata/fail-issue5747.bz2"), + input: mustLoadFile("testdata/fail-issue5747.bz2.base64"), fail: true, }, { desc: "out-of-range selector - issue 8363", diff --git a/src/compress/bzip2/testdata/fail-issue5747.bz2 b/src/compress/bzip2/testdata/fail-issue5747.bz2 deleted file mode 100644 index 2bf2b6ad99f473b6a1b61c5b049eb5be89c61057..0000000000000000000000000000000000000000 Binary files a/src/compress/bzip2/testdata/fail-issue5747.bz2 and /dev/null differ diff --git a/src/compress/bzip2/testdata/fail-issue5747.bz2.base64 b/src/compress/bzip2/testdata/fail-issue5747.bz2.base64 new file mode 100644 index 0000000000000000000000000000000000000000..a8d510c7a2fd5f02d43aa006adc04b9effbd2029 --- /dev/null +++ b/src/compress/bzip2/testdata/fail-issue5747.bz2.base64 @@ -0,0 +1,127 @@ +QlpoNTFBWSZTWTzyiGcACMP/////////////////////////////////3/7f3///////4N/fCZOD +ak2Xo44GIHZgkGzDRbFAuwAAKoFV7T6AO6qwA6APb6s2rOoAkAADoACUoDtndh0iQAPkAAAAaPWi +hQoCgr5t97Obju21ChQB0NBm3RbA7apXrRoBooAAAhA+IAHWl2Us3O7t9yieb3udvd76+4+fd33n +d3HO1bVvfcGRne6+3vfPvfc++995w7k973eJhasLVec970tzDNXdX28LoPXZ3H3K9z0s5ufWAfes +49d5594c3dUYtI+2+h1dvtpRa+uvrVEAG9bl893RVEN7cWvroSqWjPMGgAQi7Gq8TJSgKKdjKFBI +B9AeLqWxleu715eXe7ml9e5098Z6G1vr7t1QZ6ot76YzPd3j7333t2ql2Chm7XrA9ICQVF77z3rV +BWqkSXtlfb099hyezAr6USbGpICTSCFAaqHrKo+tUnm32rpE4Ue+t2mjbKUeipEqwc93EdhhTwmQ +pOhhesC9iqDSPNTWYNSnUtBdm1nsA0nqqNd7OWwDXtFLONmmA6Ubke26I9UblvWIPR5VOWOnctai +443URunnDy77uVC59OfRvezlDu33Z7Ly3NNuuHW63088xu3t3NHZhkZbG7tXRlj00qOtbaXTJUUd +spTbABR9R6EUwQAEAAAAEMEwRpoAAAABMmhoAAjBNNAaCMhponpoGpgJpk9TEyp6niGKZkAaAEfq +MQ09U80p+pMGSCKngIAAAAgAAg0AAJhGgABGCEaaTyTKeNI1PE0wkj01GajMSNPSZGnqbU9TanlP +UNAHqGQ0DQAMg9TamgAAYRU/IAAICAmjQJgjQBMEwp5DTSaaYmhTeqfplPIDU1T9TynoU82pT1NP +U/VP0j1NHqRpk9TTR7SnqaNNGmmQAaAD1Aeo0PSAAAAaaBiKeBAQBGgIABGQA0AmBNNBoaAgaJmp +glPEyYap6npiTT0agGjJjUaaDTQAAAAAAM1A9QAaAAAADU8iEAQAEyAJk0NNNJgIZTJ5E00YSemi +aZNGm1MpGNJ+lPU9qm9U2RDMoY0EzJB6h6nqDID1NMBDDRpo1AGNAjCMmhkMgaYSJIgAAAQyAAEy +BoATECCNhTT0U/IZAmCM1DSTxkzUE8p6NDaGiZGJqntTFHvUyU9qPQp7Kn5GgKNPU9QAGg9QAAA3 +wz0Pk/g/m/m9P9H4vxv2+dH3gCS8nhbbbbbYxtgNsBsG0m2MbG0NNtsbYNsaY0wbbBibGmm22mxp +tNpsaGNDTY02JsG0MY0xg2MaYNNDbGwG0L5vsK/F9DO+EAA447Kqp7Wdf6Y+5c20T7DfHyMXIzRK +rZexw72uiQI+y55vOe52xpqbCLC2uR20JdER7Zvr7ufuKb6zhiBxLuj0eA27v8RpMLucw9Ohwciz +i2wrpt+yU1FdpM7ZYPcwS3XTef+AWzjxwhdrgw3aH1LeC1eZW900x8V9Nv4hTPXp4l067P/4ANVZ +FF/imOe/d5bdueam/DFFokQWnFaU+ZqLBCM+d0PialJQWnLqRQZk/KhfbbYc2pCUTgffcSYbrCM1 +N+8lHU6gSz+h2GJXs+tbrNviL83M97X0vcTn/F82P8wen8/3/h3sHY+sf9CSej9ThYTV3lQ+FUHp +fpGD4kv7dYMV995dpDX/y3xR8FoXx1bjUxBTNxuutwQ/h/Eedn9wpn6wE3+ND8YhN1HSriIxRE/6 +uFyMv6/oC6Elarw3aHMMqHJkGiiz6tejmvnYLQa+Qm6GdeZ7jXTZV6NlpocgDnRdimS06bTYSkvP +AL/xoWNLkX6N6VljU0dfKSBmm2uZE/xusutQ1EdP7GdjhglIq4xlOFUFEQpmX+xx7R8y6c0GSAaq +usOjNZwxZRudOvmXm1tZT+YnbeB2ir9eiHNrtJNSLD/J/WDyuQpwBUtLKo0krccY/wIILP7f86te +b9Z/9oyzOX05qEWbObfhpRw+9+rCvp/35ML8KX3aHaI0n+tudbFRsV5FLW+Oa8ruLN4peyVLDWjT +HrXNthq/s7zAJYMeFJZkZt5mT9rfpH+5g3nc+piOSZ+J5nHtOnKI7Ff8Xl+j0t76XTNucCHQ6wha +v1OHdF53TY5wuv5OzvrdnxoId8fTyUvERr0ERINu/8XxZZ5fB5/kTZ8bBO0wv54Jp+ED/GQI8lZH +zIQCP3vfQhwnCTj9TvITic7P4mYLDbH3fyzRi+6EajCcpXLWSGf+ZXkOrWspDWDhXtEKas0v3UqW +ksqgY1rTj45krX4KihN+daXspZl5WPlta5p06CX6Xm2SfzqkMw12/3ix1bpnnZ+kFeBNX7A+E9zz +G6OZaN78GOpl9Ht/eZn9PqWdav852zr0zqkDK2H5IjdvNah+b1YVGdQGzwR4Nw+f13yEKnV+y66W +djfq7zWp7m5w+hzfv+Ly8O7oet5Vvd8/wQvO7qzOZ2vjf9X8Tj8PnMb/nc/nKqRR+ml4UEhOOwfC +eJEEI109CMYSh91iAJqPjMyH6KjrPD7W25llZVcREYNCTg6htbQtM38wYoquCWP6tdKYlVIv14xT +NUeUf4El/FunCf6csZkmv+9tfWx7t59wuKIa3saUtZs9M+3HFOZtz3OLg/Unoaj9BYazYqA78xBU +9tZzrtmF/rQL9CGJt90o/oYnSfcSSL3haaw351LXWQ1XOsv1SmH3v6ymuxEpPPnEDmBELaTYsvvM +IWJsmPZFFww++Kd7s/Jo0JFeUU7uNtI+gVosAIpVVuWfI/9tOIycz7I5Z7zjV+NR2OuZbYtW5F08 +KX4o2k/xuJIchcNFPtxPfw9dkDgscRbMckyFMrzuZ3IvrcGzk0J6iI5ytrv37bGpAXMzWK9mMMPe +bepNevmLjjo/QWoM968Sjv7ldlPS5AinHcXwsFv6dmmh8lJt7UOJWoKulMD1cB2ksIGpMdv8iuqR +42Rn/kn+17BhhUZcwDBaUXVdX6bKW7fxlUYbq+mlqIcfa9v8HF87M9ANbi9bq9onf9TD7nQ6Xf6v +Zci8TBPX+/GI0He6j31fTVQYW+NsQxvOJ8xrx+e58CCLQNjxeIyPt+F+qk/QMiXw+LyxGVkV/XcG +QT9X03jSDP6beJ5QG1JW9Q3qLv/YixWI7gPV9Mrhf2oRYTc/9KLFRhkE3SjKOTKuSSBKQ24fI+hE +znamH71D66Hwez8/0et7AtTv9zvamv2OD5He6fMV4k+ePl6+qPfO5CdHtK+eCDZL5+4f5yrlgTcR +Fiq8fXbc5IaI5fbbc1KMM/2T0Mr7+Hwaco6FtXm0fmhCgTZRqY4pKiEIfmazQwHNOOCrtMJ2Vwsy +Mumt7xsOolGnizRev6lILH43qPcczQM7Gc5zRin80YvFt1Qmh/57Z0auR2h0fuX50MBO4XQ+26y5 +l6v4j902R66c0j3z2KHstKQ04J/h6LbuNQE4D6cu/lyfK69DxxX8wb8XaQkMUcJdo1LzqUGDAb3K +fn/A3P/JYc99MO9qv67+SxWbwYTyqKdWTd+1KbR/Rcn0Io5zI/QquX7FA1bxfMytjQ/X+l0fh0Pf ++Hx97meH4fQL7/T8/sdTm9Tn8nELvedyhydLlPPTScINdXyLIq9wgIJr4fWPbp9ZhFh/56fdSgOG +HDXg+gkXsN2Rddr4HQ5P3u+RhLzmSjhzoqY5EsPC4QvRlX9JXjB84rPV5USR66qa/kjw4156GJnz +oXtydKJE53t6PHfZWO+3ujsfI6iAdshc7OFzGXiZB9PtItKodhYqnABkTKdcpu4+TOpf9h5piX5s +lsaBjkeTnj/Ba02ilboQfcDVigxrYn/iTH5ySWUW/lHtg78s5UZM8sErwhNe3N3w+6ZOMnU+5i86 +/xFNtqZfDdXTGy1H3PzGbdtZXYT+Ixx2vpwBYzbPVYHxKosM5rPiVmcTllI9nuoSfeh9ib4foFWa +uOpvdmhBDqpTpKTXu8EO2l2Z195G2RIV7TlKSxGWjR5sl/nALu1uzBeLd9zpSujzMTd1uTX9Qk/Q +1S+rvaW6bm8qqPO4jb6Wx6XIkm321nrIF6Ae25d1+Dpv/P5G4NoLd2j6/EtENC3FeR5zoo7bA+tI +8yEQRhiF0z1FlJXLD5ZbhNNWQm/j/IbzRfh8JtOFZU7ruShLvHXysW9S9V909tr9jn8/E/Hb5N/1 +NVNHnZu2HIUvJvHJiHd2ucmeI9PWUMnppmE65GQ5E9xVZRlGEH0X85EvmHyEupkMrCC0oMv9RCq+ +/H8gcfpe00Hs/S+regT5p58cyYomh93vqvuw/A06BE/wzJESuYbN9pqYpoXqXFemW1NksHEJ2w+P +YMJ27WJyD5FpaXB85VaWqMOhDfO8E3QdH8ybyKt/UgI8/tDGpFbyOlaVdIv1FXJhoLp8soAA4Djg +6/KZ066NZFYuS8WdjpSZGP4/Lw+1yaXlzNznc/k2uHe2uXP3uFuPcHx+Dm44utxldoO1uBPy+jzO +s14+MIgOjOHMVNqAbMd8fUedLlhJMCfMtm4uz01enLNKcMrtLlPIR37Yukh1YEMXYpm7eU4XU+j+ +Jj3pDyaXtXs+p1fWfTN/cy9/Oxs4umUXQ4uHh1kObtayDJ56/QMxiHobjHNKuKfMxsrYEwN+QVIy +VjAwMDYuMjQ1AAA9IwJniiBLRkZDAAAXt0JaaDQxQVkmU1lZtwytAACLf/////////////////// ++//////v//////////bv78///+AXO133uwO2xB2UxIvbKXrCqCoURUBL2ytFI82AFdcOwMhVTHtk +5rD3szEVNYD4aIQINCaMRoTaSn7SbSMJiYmEwieTEp+psqbMCp+VNPaFNpqbBNR7UmanlPUeKfqm +j1PU0/VPU08o9Q9EeKHlPJtKbYqeTCYhN6U9T1NH6mp+lPyoGNTI/Knkyg1MggAgCaMEyQnqZoaa +RtRtJpppppoDaTR6hpphGh6mmgHpMQBpkGTTEAAaAAAA00AZDag0ADIBkGgABqemiRNTI0k8aU0P +RGRoAZlP0UAAAGgAAAyAADQaAAAaAAAAAAAAAAAAAaAAAAM0kgRBJ5MlPFP1Gj0jTTTUaekxNAbU +GjTQMgaZANNAAAAaAADTQAAAAAAAANAA0AAANADQ0QAAAAAAAAAaGgAAAAAAABoA0AAA0AAAAAAA +AAAAAANAAAAAkSEIaTRpomp5DUxNNDTJPTKaep6T09Kemmo2JG0aTQ9ENogaaGhkABo0NHqaBoDT +I0DCGj0gNAMhoDQ9QMQNAGQAaDDwyMPIMlbG1vhRBTFo6JksSupgpAjPbY0ec02IGXjbeS+FBsh0 +1+O4ZOaD+srUZCFaT4DRjVDLx7uKIsFtESIDUg1ZkhyCSYov05C00MtRBdNNa/AYPGOQZWcs+Veg +XOPrkushFbZ3mBoRD6WamClkpBaHZrUhUl02bIfRXX4wb3/9cW9nHDVxh2qFBxqgRKfmq7/Jc/td +Jk05nVrGbckGVy2PnIy30CDhpWmqrSotK2bOnX0NbP1iy2cd0Na0ZmbRstm4MzMzbbMySTd35F7f ++zPP8DC+NJLYcakkkkRdNZlupJt3OMFoDAD2g+N3FAMCydhIpoRHRQAdFI5nNg4ugEXHCYxkMyGC +wtaJmialy0IMlpSYYM/weXNJAhFqS0GNmvaPEtYGjbvaucMdklOTmBX1vfVAkTYB1uXCSK64UNIi +xOqRKLuRCFtqIQtgwqaFrCkIYbbewErWABa+VGADWsJXJjfx5SJViLuwiGXqRu6vCuwmU5CJiJz3 +UiBpmLv0r2wskxUhY4tzPVGQ9RMXJl65eLSNwZVwaSyGZ9CmA3jztQUUpFeUryBTskW95iVwRMFr +hBCwZBAFJBZvhMEMNoDJJlUoIhQkAkjbExp2YZio+ZYeAZUwmH1qUbdQixmxf0+61+aVgJ1hwxsO +1yG3hFx4pfjc09ITVht0pG8uFtVFhPa1KE0gTRUSVXywkITucqk0Waz5Fs6qJpVHYdNrbYRFxnFs +QGY1qmsTLjK64QX5Rddo6krM/Bx9CqIAKq4CzVQYHrmIAd2EBhYmwVYwLvhzKIUrc2EirnGIvyuD +O4YZDSwsVTA0BpVvUOjDErkCraBoSutcKwUSSLGhVvNYHLz3klgZD++wWsa/swLwgvNDY2De+snc +Ov8X2lq4HD95ZdwPuTIMXCwSbg4RrIqv+L0y6F17pqDecyQYPEj3iN/0BBeWZlJAyBMi5U3Q1zAl +sK8IlDhaXGmvZrgISq5CfNjmUgxDeMggOKqxu4sIOrilS49Lkl1J3u3GjXTuH+rX+4ccyFAQnizC +pPClcY77F59j63S6fr5vr+y99tuO7Ox7Wg/ljwhdyaK4xMmXczeJbx7x07htJNtC4xcQfAtvzezn +LrN6MN/ILIBOI65IqIA2D5fHHj1XN4aN6TvOjWDaSbSWqxCSCvXUpzkNJAkWXAuTwF8k5uSJvQj/ +rVo0hAhEMEIYkCRGx9AX+byIuXWlLMbbVeliHNUL5AQYmNwLFu4SkmGD+UWtBMyVHQOQss0ggoVK +SKOBUgnVS6ljt7WE1qXqJJ4QA1pEwYNLEaguEE1LtPNoVr5WzjbSbWPkV9OW3y9IneUDLoIV5pAk +EFTEFGFVjeTFxtpzBBfGgycBxVCdz8eESBIzsamRchAaTQunQH8DHnpfod9QuAuRvc7JBlKUCYmC +jMvynLcxIFohxCaYrDvGw4QbXZB7oWQ7hpoGlz23ayDfB8NrRRzdilsEQyQniu9ASLQg7RrGZnoT +r1ai12IbCEUCGdFq03P5nBnRFAGmisQGcyykV9gKtcVMWLhCuVmXg86dndn7slUpRNSSEAU20oaW +Im1maFTuE0DT4gTbg0nuhjtz3kNOz+i7sBm0bkXjxQWuLqlZEmp60ZTyRZJDUqKSEKg6hqcyERxd +U22CSNOO10RYUUiDVpKhPNdKTOIE1thp02sBNoNTFSht8WJtaBQ09qN3jd5rdOLX4IA5fevRyCCz +DgRXfV4wzik4KROjmxmTMglBySlIMEzcXehnDXCRiZSlvwA20YsIOROcm4UrIRFxJHctJH7OdN5u +1aHVHb5UaLHpv48NgmFRE56KTSoaWunqm2stS0mrAdOiqcR12PWVbdVRJKcQ0DQuhwlAPcRtpxN3 +D4kbXJjToSYJIFw406G2CSaKjQMIJPZGlQmgyFhoCSzeGS1VSq5SKKQQxs5RqKUcVUNY57YUETb4 +mXzV84SPngKinsce0mXByZq5BKUA9puHZWLNwQIYuDaJUNgG+E01E3pDYVNLKYQ0hsVesgV5gZY0 +htDsRdGtm0+iGnkN6+Ea9YJtUZNAkx2GgSoix12nTW0avTUfxR3oYcpvZ7IdtABEUhBcjG4qZtDZ +sS1JQHys243vhLaDTSvvTeBiJA2tmokqECTBcSOCAGkAxMKlVAva4IsLRaBBqhxDbcGtgdw03mFc +LUaFuhtKuuEIEkUleJQwby/zwu9uvvZK4xTV+ECMa8lmzxKmqkBggYK1+xPdbmJclm6tSZhE/OSJ +tCEjs+unJIQkT9hCWgBJqGMS07EhAJNmBiuVEVdTyjkIJkavuZmx2sJF13htgEZUCC23lZFOE6gW +bM9WyYNJTM8yCQrb0Sx3OQvBML5cRATAQkSQkAJOAhoxpQkNi4ZiEVDbdtJAME0RXNDXGHA3M3Q0 +mm1oIEwbWpaM1DQCSMbGRCAu3iRIQiT6RlBpT1n3tfwvUXz3gIVlx3mEximY/kZW1kNGsgEJIrBi +saEoGYPJ+1CQUYFBw+eGEHJQBpNHjErXUJY2iWHQ30hXwFBuMSxQ2lB5bg+/LX3euG6HsHUB1lFv +BvaiaBrITVwkCTa1d0s9CHZCiDZjbWReKyrpPE2oSa7oLPrR4BJvys9ttjUpzETSSMxh8vsr9dXT +wKBtK+1xCTGDQmNIaE29HmHdS5GSxpyaMismcAUSEgSxHBrKtgsZzduG7vHZn16l3kFkVITtENIz +S2JsiBwFTDlhgexsjBHv5HXOYxHBzoSDCcPZ0ctvkY9aS5XpoQuFYkGJgCsqjJZeUMNUEpDSbKcn +Uc1PifIACbR2UoXawBlspkEBr9HBfvUi/MUakZVOf1WKYrqSaIXce62JOyhJLq3qJBloTA0FVbIL +EtM+heFmNRCFt70GJrExVJri0ArYbCRbADSGDBpBXxxb/6fo+s3C7uaL7RjMLV2IQBNrAJrKFeJw +TsPnxbAsemirUx2lk1kaxschzdK4TQNJN5wQnolIFg401OZ42na11LnT3lR+1k1TMJhiAjXMk0F1 +ooHnYlt9LKfJ3ZIOmeY+2l9bUQHWFNGyEyfjEAcu3kpGLq0Ez7XOS+EpAASRQTAYMATfVQibHLTT +30zG732+pNe9za1JNt8sNJYnRjWuJ6jL5ILV0rcd9vT7X9fObvcXitpvJ2XBJE+PhX2HaTkyWeF9 +pwnlQNrTe9hVtzhA+ihZrDrHNmLcQjZbnv/IMubqq8egxY80t5n6vZ6U5TR6U9uZJvai1xtqAyCR +NWkW52m00rDTEuO6BA4q2RHDWwbETF55rRsWLIgNW9qJCyMHPbTM/dMBmWMQSMxz4M2pRzt47SIC +xA327UqSCEERqMFybmYi3nUxePtLgHYplqRiw4ynMbXd/kiQ0LE0PKJSSCXA42ymziCpAxNWflzp +zQdJZusahRFr6t6m+4p273/Taj7k+hZyNgBAgXAY8F7pTts6orLb8IA6o4TOwkwQYmKvKu9VwMrE +7+GUhVIAgY9a8DyQMiDBkEAwh7S1KgCBfao8DK1CwSS8Z3WjL5MEgt93z2koUQCD/YxMBppiCMp7 +SDVSmkkIHptfGpeht+M13Ccv1tavIASFiaQl6rBz3K4N3DSGwNkCibrvEAC0fQirOWnc4NVbcLKp +FG1lNQXF/eqdT79wq1Mvlap3QSCLhcD2D3fCkKVWid4aSjtp9FOX1Uaf7P9eT93zd9Svmj2yNLRU +GzyI/0oONNSzmmkvJ5Cq2X2CdldIWMGZO57RJ8oyATAWTQmRmNkfh0SxuuR/J9oUsomVy1AEntc0 +dlPivkqBkBqrxU3j5PnWkaI3ZRGc0gg9spCQEISh4xEUpMhVrnmDQLfLP8Ouqpx917MAw7hkjQk6 +BJFTAbXDsz3LSHIxo/gB8qrA1vbvdZZhLtR0frJdfdppX8nAQX/TAxOQ8+H6yw8a9i7/zJEfSYIh +op59N/fhcWW2F14cj2XcfyHaZ04lTO4uPnly91jwuFPaREuZVp8AxImIhlkxkAN61tWdWG7tEbaC +gszh6VIzThFnHo2Vi8SQXPrXCN7J9Tc9ZYiAYqoThV/u6SYsea5aZL8deOvKBQCgZZuIxX1z4Enf +cqG176vY4VqMBIC4pMJz0WcHJYqN+j7BiwGoMBwExrIdTB7q4XIFLotcIpS01MqyVsesvoQq7WOb +mGQXdMliMirSLcDuSx8Qy+4pIBgGDIyMp1qbonnGdcHYvU8SO0A8s/iua5oFdNZTWvbVI4FUH9sK +cLiB3/fIAF+sB4n8q6L+UCfmbPcAo/crQ6b3HqhDBMY9J0q/jdz9GNYZ/1fbXdkUqAQKFePhtzJD +RBZba27+LPQNMCcrHMq06F1T4QmLmkHt7LxB2pAczUO+T2O9bHEw/HWw+dYf2MoRDUw= diff --git a/src/crypto/cipher/gcm_fips140v2.0_test.go b/src/crypto/cipher/gcm_fips140v2.0_test.go index c44497d4d820569b875064949728c3094750af6f..d3a8ea5c63bb826a4d6418a36aedf405bc9a37fa 100644 --- a/src/crypto/cipher/gcm_fips140v2.0_test.go +++ b/src/crypto/cipher/gcm_fips140v2.0_test.go @@ -8,15 +8,29 @@ package cipher_test import ( "crypto/cipher" + "crypto/internal/cryptotest" "crypto/internal/fips140" fipsaes "crypto/internal/fips140/aes" "crypto/internal/fips140/aes/gcm" "encoding/binary" + "internal/testenv" "math" "testing" ) func TestGCMNoncesFIPSV2(t *testing.T) { + cryptotest.MustSupportFIPS140(t) + if !fips140.Enabled { + cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestGCMNoncesFIPSV2$", "-test.v") + cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=on") + out, err := cmd.CombinedOutput() + t.Logf("running with GODEBUG=fips140=on:\n%s", out) + if err != nil { + t.Errorf("fips140=on subprocess failed: %v", err) + } + return + } + tryNonce := func(aead cipher.AEAD, nonce []byte) bool { fips140.ResetServiceIndicator() aead.Seal(nil, nonce, []byte("x"), nil) diff --git a/src/crypto/cipher/gcm_test.go b/src/crypto/cipher/gcm_test.go index fe6bf5506e5a1028ca48a44b1c57869f7b15115d..8daa0ded22e1769ae50b84b108c5610bd01da70d 100644 --- a/src/crypto/cipher/gcm_test.go +++ b/src/crypto/cipher/gcm_test.go @@ -17,6 +17,7 @@ "crypto/rand" "encoding/hex" "errors" "fmt" + "internal/testenv" "io" "reflect" "testing" @@ -761,7 +762,19 @@ }) }) } -func TestGCMNonces(t *testing.T) { +func TestGCMNoncesFIPSV1(t *testing.T) { + cryptotest.MustSupportFIPS140(t) + if !fips140.Enabled { + cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestGCMNoncesFIPSV1$", "-test.v") + cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=on") + out, err := cmd.CombinedOutput() + t.Logf("running with GODEBUG=fips140=on:\n%s", out) + if err != nil { + t.Errorf("fips140=on subprocess failed: %v", err) + } + return + } + tryNonce := func(aead cipher.AEAD, nonce []byte) bool { fips140.ResetServiceIndicator() aead.Seal(nil, nonce, []byte("x"), nil) diff --git a/src/crypto/ecdh/ecdh_test.go b/src/crypto/ecdh/ecdh_test.go index 8a3eb87061ad8c90b448c74c6afeaab015e0aea4..cfa919ade97ad06be3096fdbe7fb7fb549a6d0a2 100644 --- a/src/crypto/ecdh/ecdh_test.go +++ b/src/crypto/ecdh/ecdh_test.go @@ -16,7 +16,6 @@ "fmt" "internal/testenv" "io" "os" - "os/exec" "path/filepath" "regexp" "strings" @@ -450,7 +449,6 @@ func TestLinker(t *testing.T) { if testing.Short() { t.Skip("test requires running 'go build'") } - testenv.MustHaveGoBuild(t) dir := t.TempDir() hello := filepath.Join(dir, "hello.go") @@ -460,17 +458,16 @@ t.Fatal(err) } run := func(args ...string) string { - cmd := exec.Command(args[0], args[1:]...) + cmd := testenv.Command(t, args[0], args[1:]...) cmd.Dir = dir - out, err := cmd.CombinedOutput() + out, err := testenv.CleanCmdEnv(cmd).CombinedOutput() if err != nil { t.Fatalf("%v: %v\n%s", args, err, string(out)) } return string(out) } - goBin := testenv.GoToolPath(t) - run(goBin, "build", "-o", "hello.exe", "hello.go") + run(testenv.GoToolPath(t), "build", "-o", "hello.exe", "hello.go") if out := run("./hello.exe"); out != "OK\n" { t.Error("unexpected output:", out) } @@ -478,7 +475,7 @@ // List all text symbols under crypto/... and make sure there are some for // P256, but none for the other curves. var consistent bool - nm := run(goBin, "tool", "nm", "hello.exe") + nm := run(testenv.GoToolPath(t), "tool", "nm", "hello.exe") for _, match := range regexp.MustCompile(`(?m)T (crypto/.*)$`).FindAllStringSubmatch(nm, -1) { symbol := strings.ToLower(match[1]) if strings.Contains(symbol, "p256") { diff --git a/src/crypto/fips140/enforcement_test.go b/src/crypto/fips140/enforcement_test.go index 708c7f7a15ee9e7918d964fd404947932b65566a..c2f66d544bfbd063b28e2d68825ea4d2eaa44553 100644 --- a/src/crypto/fips140/enforcement_test.go +++ b/src/crypto/fips140/enforcement_test.go @@ -5,42 +5,77 @@ package fips140_test import ( + "crypto/des" + "crypto/fips140" "crypto/internal/cryptotest" "internal/testenv" - "path/filepath" - "strings" "testing" ) +func expectAllowed(t *testing.T, why string, expected bool) { + t.Helper() + result := isAllowed() + if result != expected { + t.Fatalf("%v: expected: %v, got: %v", why, expected, result) + } +} + +func isAllowed() bool { + _, err := des.NewCipher(make([]byte, 8)) + return err == nil +} + func TestWithoutEnforcement(t *testing.T) { - testenv.MustHaveExec(t) - testenv.MustHaveGoBuild(t) cryptotest.MustSupportFIPS140(t) + if !fips140.Enforced() { + cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestWithoutEnforcement$", "-test.v") + cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=only") + out, err := cmd.CombinedOutput() + t.Logf("running with GODEBUG=fips140=only:\n%s", out) + if err != nil { + t.Errorf("fips140=only subprocess failed: %v", err) + } + return + } - tool, _ := testenv.GoTool() - tmpdir := t.TempDir() - binFile := filepath.Join(tmpdir, "fips140.test") - cmd := testenv.Command(t, tool, "test", "-c", "-o", binFile, "./testdata") - out, err := cmd.CombinedOutput() - if err != nil { - t.Log(string(out)) - t.Errorf("Could not build enforcement tests") - } - cmd = testenv.Command(t, binFile, "-test.list", ".") - list, err := cmd.CombinedOutput() - if err != nil { - t.Log(string(out)) - t.Errorf("Could not get enforcement test list") - } - for test := range strings.Lines(string(list)) { - test = strings.TrimSpace(test) - t.Run(test, func(t *testing.T) { - cmd = testenv.Command(t, binFile, "-test.run", "^"+test+"$") - cmd.Env = append(cmd.Env, "GODEBUG=fips140=only") - out, err := cmd.CombinedOutput() - if err != nil { - t.Error(string(out)) - } + t.Run("Disabled", func(t *testing.T) { + expectAllowed(t, "before enforcement disabled", false) + fips140.WithoutEnforcement(func() { + expectAllowed(t, "inside WithoutEnforcement", true) + }) + // make sure that bypass doesn't live on after returning + expectAllowed(t, "after WithoutEnforcement", false) + }) + + t.Run("Nested", func(t *testing.T) { + expectAllowed(t, "before enforcement bypass", false) + fips140.WithoutEnforcement(func() { + fips140.WithoutEnforcement(func() { + expectAllowed(t, "inside nested WithoutEnforcement", true) + }) + expectAllowed(t, "inside nested WithoutEnforcement", true) + }) + expectAllowed(t, "after enforcement bypass", false) + }) + + t.Run("GoroutineInherit", func(t *testing.T) { + ch := make(chan bool, 2) + expectAllowed(t, "before enforcement bypass", false) + fips140.WithoutEnforcement(func() { + go func() { + ch <- isAllowed() + }() }) - } + allowed := <-ch + if !allowed { + t.Fatal("goroutine didn't inherit enforcement bypass") + } + go func() { + ch <- isAllowed() + }() + allowed = <-ch + if allowed { + t.Fatal("goroutine inherited bypass after WithoutEnforcement return") + } + }) } diff --git a/src/crypto/fips140/testdata/enforcement_test.go b/src/crypto/fips140/testdata/enforcement_test.go deleted file mode 100644 index a8fde3b5bc622c62a093700b12b654c0e4e16987..0000000000000000000000000000000000000000 --- a/src/crypto/fips140/testdata/enforcement_test.go +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package fips140_test - -import ( - "crypto/des" - "crypto/fips140" - "testing" -) - -func expectAllowed(t *testing.T, why string, expected bool) { - t.Helper() - result := isAllowed() - if result != expected { - t.Fatalf("%v: expected: %v, got: %v", why, expected, result) - } -} - -func isAllowed() bool { - _, err := des.NewCipher(make([]byte, 8)) - return err == nil -} - -func TestDisabled(t *testing.T) { - expectAllowed(t, "before enforcement disabled", false) - fips140.WithoutEnforcement(func() { - expectAllowed(t, "inside WithoutEnforcement", true) - }) - // make sure that bypass doesn't live on after returning - expectAllowed(t, "after WithoutEnforcement", false) -} - -func TestNested(t *testing.T) { - expectAllowed(t, "before enforcement bypass", false) - fips140.WithoutEnforcement(func() { - fips140.WithoutEnforcement(func() { - expectAllowed(t, "inside nested WithoutEnforcement", true) - }) - expectAllowed(t, "inside nested WithoutEnforcement", true) - }) - expectAllowed(t, "after enforcement bypass", false) -} - -func TestGoroutineInherit(t *testing.T) { - ch := make(chan bool, 2) - expectAllowed(t, "before enforcement bypass", false) - fips140.WithoutEnforcement(func() { - go func() { - ch <- isAllowed() - }() - }) - allowed := <-ch - if !allowed { - t.Fatal("goroutine didn't inherit enforcement bypass") - } - go func() { - ch <- isAllowed() - }() - allowed = <-ch - if allowed { - t.Fatal("goroutine inherited bypass after WithoutEnforcement return") - } -} diff --git a/src/crypto/hpke/aead.go b/src/crypto/hpke/aead.go index 1a606c68db627f5c016b62172c9d79736b119665..fb55c97ddf20c9b5f81057974c8559a49515ce0c 100644 --- a/src/crypto/hpke/aead.go +++ b/src/crypto/hpke/aead.go @@ -5,7 +5,6 @@ package hpke import ( - "crypto/aes" "crypto/cipher" "errors" "fmt" @@ -82,14 +81,6 @@ nK: chacha20poly1305.KeySize, nN: chacha20poly1305.NonceSize, new: chacha20poly1305.New, id: 0x0003, -} - -func newAESGCM(key []byte) (cipher.AEAD, error) { - b, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - return cipher.NewGCM(b) } func (a *aead) ID() uint16 { diff --git a/src/crypto/hpke/aead_fipsv1.0.go b/src/crypto/hpke/aead_fipsv1.0.go new file mode 100644 index 0000000000000000000000000000000000000000..986126cbf94702346a084310066c7d86bcc59436 --- /dev/null +++ b/src/crypto/hpke/aead_fipsv1.0.go @@ -0,0 +1,20 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build fips140v1.0 + +package hpke + +import ( + "crypto/aes" + "crypto/cipher" +) + +func newAESGCM(key []byte) (cipher.AEAD, error) { + b, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + return cipher.NewGCM(b) +} diff --git a/src/crypto/hpke/aead_fipsv2.0.go b/src/crypto/hpke/aead_fipsv2.0.go new file mode 100644 index 0000000000000000000000000000000000000000..710eb1c08f8d31ae3540cd6e07ca20a76816af22 --- /dev/null +++ b/src/crypto/hpke/aead_fipsv2.0.go @@ -0,0 +1,21 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !fips140v1.0 + +package hpke + +import ( + "crypto/cipher" + "crypto/internal/fips140/aes" + "crypto/internal/fips140/aes/gcm" +) + +func newAESGCM(key []byte) (cipher.AEAD, error) { + b, err := aes.New(key) + if err != nil { + return nil, err + } + return gcm.NewGCMForHPKE(b) +} diff --git a/src/crypto/hpke/hpke_test.go b/src/crypto/hpke/hpke_test.go index b54a234fe55221d15c5e154fed51e0841b4afff8..ceb33263a6671718fba70172bec104f693b752ee 100644 --- a/src/crypto/hpke/hpke_test.go +++ b/src/crypto/hpke/hpke_test.go @@ -69,6 +69,183 @@ // Output: // Decrypted message: |-()-| } +func TestRoundTrip(t *testing.T) { + kems := []KEM{ + DHKEM(ecdh.P256()), + DHKEM(ecdh.P384()), + DHKEM(ecdh.P521()), + DHKEM(ecdh.X25519()), + MLKEM768(), + MLKEM1024(), + MLKEM768P256(), + MLKEM1024P384(), + MLKEM768X25519(), + } + kdfs := []KDF{ + HKDFSHA256(), + HKDFSHA384(), + HKDFSHA512(), + SHAKE128(), + SHAKE256(), + } + aeads := []AEAD{ + AES128GCM(), + AES256GCM(), + ChaCha20Poly1305(), + } + + for _, kem := range kems { + t.Run(fmt.Sprintf("KEM_%04x", kem.ID()), func(t *testing.T) { + k, err := kem.GenerateKey() + if err != nil { + t.Fatal(err) + } + kb, err := k.Bytes() + if err != nil { + t.Fatal(err) + } + kk, err := kem.NewPrivateKey(kb) + if err != nil { + t.Fatal(err) + } + if got, err := kk.Bytes(); err != nil { + t.Fatal(err) + } else if !bytes.Equal(got, kb) { + t.Errorf("re-serialized key mismatch: got %x, want %x", got, kb) + } + pk, err := kem.NewPublicKey(k.PublicKey().Bytes()) + if err != nil { + t.Fatal(err) + } + if got := pk.Bytes(); !bytes.Equal(got, k.PublicKey().Bytes()) { + t.Errorf("re-serialized public key mismatch: got %x, want %x", got, k.PublicKey().Bytes()) + } + + for _, kdf := range kdfs { + t.Run(fmt.Sprintf("KDF_%04x", kdf.ID()), func(t *testing.T) { + for _, aead := range aeads { + t.Run(fmt.Sprintf("AEAD_%04x", aead.ID()), func(t *testing.T) { + c, err := Seal(pk, kdf, aead, []byte("info"), []byte("plaintext")) + if err != nil { + t.Fatal(err) + } + p, err := Open(kk, kdf, aead, []byte("info"), c) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(p, []byte("plaintext")) { + t.Errorf("unexpected plaintext: got %x, want %x", p, []byte("plaintext")) + } + + p, err = Open(kk, kdf, aead, []byte("wrong"), c) + if err == nil { + t.Errorf("expected error when opening with wrong info, got plaintext %x", p) + } + c[len(c)-1] ^= 0xFF + p, err = Open(kk, kdf, aead, []byte("info"), c) + if err == nil { + t.Errorf("expected error when opening with corrupted ciphertext, got plaintext %x", p) + } + + c, err = Seal(k.PublicKey(), kdf, aead, nil, nil) + if err != nil { + t.Fatal(err) + } + p, err = Open(k, kdf, aead, nil, c) + if err != nil { + t.Fatal(err) + } + if len(p) != 0 { + t.Errorf("unexpected plaintext: got %x, want empty", p) + } + + // Test that Seal and Open don't modify the excess capacity of input + // slices. This is a regression test for a bug where decap would + // append to the enc slice, corrupting the ciphertext if they shared + // a backing array. + padSlice := func(b []byte) []byte { + s := make([]byte, len(b), len(b)+2000) + copy(s, b) + for i := len(b); i < cap(s); i++ { + s[:cap(s)][i] = 0xAA + } + return s[:len(b)] + } + checkSlice := func(name string, s []byte) { + for i := len(s); i < cap(s); i++ { + if s[:cap(s)][i] != 0xAA { + t.Errorf("%s: modified byte at index %d beyond slice length", name, i) + return + } + } + } + + infoS := padSlice([]byte("info")) + plaintextS := padSlice([]byte("plaintext")) + c, err = Seal(pk, kdf, aead, infoS, plaintextS) + if err != nil { + t.Fatal(err) + } + checkSlice("Seal info", infoS) + checkSlice("Seal plaintext", plaintextS) + + infoO := padSlice([]byte("info")) + ciphertextO := padSlice(c) + p, err = Open(kk, kdf, aead, infoO, ciphertextO) + if err != nil { + t.Fatalf("Open with large capacity slices failed: %v", err) + } + if !bytes.Equal(p, []byte("plaintext")) { + t.Errorf("unexpected plaintext: got %x, want %x", p, []byte("plaintext")) + } + checkSlice("Open info", infoO) + checkSlice("Open ciphertext", ciphertextO) + + // Also test the Sender.Seal and Recipient.Open methods. + infoSender := padSlice([]byte("info")) + enc, sender, err := NewSender(pk, kdf, aead, infoSender) + if err != nil { + t.Fatal(err) + } + checkSlice("NewSender info", infoSender) + + aadSeal := padSlice([]byte("aad")) + plaintextSeal := padSlice([]byte("plaintext")) + ct, err := sender.Seal(aadSeal, plaintextSeal) + if err != nil { + t.Fatal(err) + } + checkSlice("Sender.Seal aad", aadSeal) + checkSlice("Sender.Seal plaintext", plaintextSeal) + + infoRecipient := padSlice([]byte("info")) + encPadded := padSlice(enc) + recipient, err := NewRecipient(encPadded, kk, kdf, aead, infoRecipient) + if err != nil { + t.Fatal(err) + } + checkSlice("NewRecipient info", infoRecipient) + checkSlice("NewRecipient enc", encPadded) + + aadOpen := padSlice([]byte("aad")) + ctPadded := padSlice(ct) + p, err = recipient.Open(aadOpen, ctPadded) + if err != nil { + t.Fatalf("Recipient.Open failed: %v", err) + } + if !bytes.Equal(p, []byte("plaintext")) { + t.Errorf("unexpected plaintext: got %x, want %x", p, []byte("plaintext")) + } + checkSlice("Recipient.Open aad", aadOpen) + checkSlice("Recipient.Open ciphertext", ctPadded) + }) + } + }) + } + }) + } +} + func mustDecodeHex(t *testing.T, in string) []byte { t.Helper() b, err := hex.DecodeString(in) diff --git a/src/crypto/hpke/kem.go b/src/crypto/hpke/kem.go index 7633aa2b714ca9ae46f7e1136a07776530538526..132e0a754c63f37e23c2874a2b3ba947df988254 100644 --- a/src/crypto/hpke/kem.go +++ b/src/crypto/hpke/kem.go @@ -9,6 +9,7 @@ "crypto/ecdh" "crypto/internal/rand" "errors" "internal/byteorder" + "slices" ) // A KEM is a Key Encapsulation Mechanism, one of the three components of an @@ -377,6 +378,6 @@ dhVal, err := k.priv.ECDH(pubEph) if err != nil { return nil, err } - kemContext := append(encPubEph, k.priv.PublicKey().Bytes()...) + kemContext := append(slices.Clip(encPubEph), k.priv.PublicKey().Bytes()...) return k.kem.extractAndExpand(dhVal, kemContext) } diff --git a/src/crypto/hpke/pq.go b/src/crypto/hpke/pq.go index f2adbef54ea808053976fcfce54c70c173698246..e8dc80fd23a61a268dde3fd8f3bb4a74cbc62e6d 100644 --- a/src/crypto/hpke/pq.go +++ b/src/crypto/hpke/pq.go @@ -8,6 +8,7 @@ import ( "bytes" "crypto" "crypto/ecdh" + "crypto/fips140" "crypto/internal/fips140/drbg" "crypto/internal/rand" "crypto/mlkem" @@ -168,7 +169,10 @@ pq, err := kem.pqNewPublicKey(data[:kem.pqEncapsKeySize]) if err != nil { return nil, err } - k, err := kem.curve.NewPublicKey(data[kem.pqEncapsKeySize:]) + var k *ecdh.PublicKey + fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved. + k, err = kem.curve.NewPublicKey(data[kem.pqEncapsKeySize:]) + }) if err != nil { return nil, err } @@ -186,14 +190,20 @@ var testingOnlyEncapsulate func() (ss, ct []byte) func (pk *hybridPublicKey) encap() (sharedSecret []byte, encapPub []byte, err error) { - skE, err := pk.t.Curve().GenerateKey(rand.Reader) + var skE *ecdh.PrivateKey + fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved. + skE, err = pk.t.Curve().GenerateKey(rand.Reader) + }) if err != nil { return nil, nil, err } if testingOnlyGenerateKey != nil { skE = testingOnlyGenerateKey() } - ssT, err := skE.ECDH(pk.t) + var ssT []byte + fips140.WithoutEnforcement(func() { + ssT, err = skE.ECDH(pk.t) + }) if err != nil { return nil, nil, err } @@ -259,7 +269,10 @@ seedT := make([]byte, kem.curveSeedSize) for { s.Read(seedT) - k, err := kem.curve.NewPrivateKey(seedT) + var k ecdh.KeyExchanger + fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved. + k, err = kem.curve.NewPrivateKey(seedT) + }) if err != nil { continue } @@ -326,11 +339,17 @@ ssPQ, err := k.pq.Decapsulate(ctPQ) if err != nil { return nil, err } - pub, err := k.t.Curve().NewPublicKey(ctT) + var pub *ecdh.PublicKey + fips140.WithoutEnforcement(func() { // Hybrid of ML-KEM, which is Approved. + pub, err = k.t.Curve().NewPublicKey(ctT) + }) if err != nil { return nil, err } - ssT, err := k.t.ECDH(pub) + var ssT []byte + fips140.WithoutEnforcement(func() { + ssT, err = k.t.ECDH(pub) + }) if err != nil { return nil, err } diff --git a/src/crypto/internal/cryptotest/fetchmodule.go b/src/crypto/internal/cryptotest/fetchmodule.go index 37f2a094972b9d2cebec7cffbb693ca4912ee854..5df340a697531e63a71c6a8000fcfa27bdba21ab 100644 --- a/src/crypto/internal/cryptotest/fetchmodule.go +++ b/src/crypto/internal/cryptotest/fetchmodule.go @@ -18,13 +18,12 @@ // containing its source tree. It skips the test if fetching modules is not // possible in this environment. func FetchModule(t *testing.T, module, version string) string { testenv.MustHaveExternalNetwork(t) - goTool := testenv.GoToolPath(t) // If the default GOMODCACHE doesn't exist, use a temporary directory // instead. (For example, run.bash sets GOPATH=/nonexist-gopath.) - out, err := testenv.Command(t, goTool, "env", "GOMODCACHE").Output() + out, err := testenv.CleanCmdEnv(testenv.Command(t, testenv.GoToolPath(t), "env", "GOMODCACHE")).Output() if err != nil { - t.Errorf("%s env GOMODCACHE: %v\n%s", goTool, err, out) + t.Errorf("%s env GOMODCACHE: %v\n%s", testenv.GoToolPath(t), err, out) if ee, ok := err.(*exec.ExitError); ok { t.Logf("%s", ee.Stderr) } @@ -44,7 +43,7 @@ } t.Logf("fetching %s@%s\n", module, version) - output, err := testenv.Command(t, goTool, "mod", "download", "-json", module+"@"+version).CombinedOutput() + output, err := testenv.Command(t, testenv.GoToolPath(t), "mod", "download", "-json", module+"@"+version).CombinedOutput() if err != nil { t.Fatalf("failed to download %s@%s: %s\n%s\n", module, version, err, output) } diff --git a/src/crypto/internal/fips140/aes/gcm/gcm_nonces.go b/src/crypto/internal/fips140/aes/gcm/gcm_nonces.go index 052349b53356f059f1fd30fb351bcc7abd18a8e2..4ae570d9a5e84c623a3fb258a1fca771a88ce330 100644 --- a/src/crypto/internal/fips140/aes/gcm/gcm_nonces.go +++ b/src/crypto/internal/fips140/aes/gcm/gcm_nonces.go @@ -107,31 +107,33 @@ if len(nonce) != gcmStandardNonceSize { panic("crypto/cipher: incorrect nonce length given to GCM") } - if !g.prefixReady { - // The first invocation sets the fixed prefix. - g.prefixReady = true - g.prefix = byteorder.BEUint32(nonce[:4]) - } - if g.prefix != byteorder.BEUint32(nonce[:4]) { - panic("crypto/cipher: GCM nonce prefix changed") - } + if fips140.Enabled { + if !g.prefixReady { + // The first invocation sets the fixed prefix. + g.prefixReady = true + g.prefix = byteorder.BEUint32(nonce[:4]) + } + if g.prefix != byteorder.BEUint32(nonce[:4]) { + panic("crypto/cipher: GCM nonce prefix changed") + } - counter := byteorder.BEUint64(nonce[len(nonce)-8:]) - if !g.startReady { - // The first invocation sets the starting counter, if not fixed. - g.startReady = true - g.start = counter - } - counter -= g.start + counter := byteorder.BEUint64(nonce[len(nonce)-8:]) + if !g.startReady { + // The first invocation sets the starting counter, if not fixed. + g.startReady = true + g.start = counter + } + counter -= g.start - // Ensure the counter is strictly increasing. - if counter == math.MaxUint64 { - panic("crypto/cipher: counter exhausted") + // Ensure the counter is strictly increasing. + if counter == math.MaxUint64 { + panic("crypto/cipher: counter exhausted") + } + if counter < g.next { + panic("crypto/cipher: counter decreased or remained the same") + } + g.next = counter + 1 } - if counter < g.next { - panic("crypto/cipher: counter decreased or remained the same") - } - g.next = counter + 1 fips140.RecordApproved() return g.g.sealAfterIndicator(dst, nonce, plaintext, data) @@ -172,6 +174,18 @@ } return &GCMWithXORCounterNonce{g: *g}, nil } +// NewGCMForHPKE returns a new AEAD that works like GCM, but enforces the +// construction of nonces as specified in RFC 9180, Section 5.2. +// +// This complies with FIPS 140-3 IG C.H Scenario 5. +func NewGCMForHPKE(cipher *aes.Block) (*GCMWithXORCounterNonce, error) { + g, err := newGCM(&GCM{}, cipher, gcmStandardNonceSize, gcmTagSize) + if err != nil { + return nil, err + } + return &GCMWithXORCounterNonce{g: *g}, nil +} + // NewGCMForQUIC returns a new AEAD that works like GCM, but enforces the // construction of nonces as specified in RFC 9001, Section 5.3. // @@ -238,28 +252,30 @@ if len(nonce) != gcmStandardNonceSize { panic("crypto/cipher: incorrect nonce length given to GCM") } - counter := byteorder.BEUint64(nonce[len(nonce)-8:]) - if !g.ready { - // In the first call, if [GCMWithXORCounterNonce.SetNoncePrefixAndMask] - // wasn't used, we assume the counter is zero to learn the XOR mask and - // fixed prefix. - g.ready = true - g.mask = counter - g.prefix = byteorder.BEUint32(nonce[:4]) - } - if g.prefix != byteorder.BEUint32(nonce[:4]) { - panic("crypto/cipher: GCM nonce prefix changed") - } - counter ^= g.mask + if fips140.Enabled { + counter := byteorder.BEUint64(nonce[len(nonce)-8:]) + if !g.ready { + // In the first call, if [GCMWithXORCounterNonce.SetNoncePrefixAndMask] + // wasn't used, we assume the counter is zero to learn the XOR mask and + // fixed prefix. + g.ready = true + g.mask = counter + g.prefix = byteorder.BEUint32(nonce[:4]) + } + if g.prefix != byteorder.BEUint32(nonce[:4]) { + panic("crypto/cipher: GCM nonce prefix changed") + } + counter ^= g.mask - // Ensure the counter is strictly increasing. - if counter == math.MaxUint64 { - panic("crypto/cipher: counter exhausted") - } - if counter < g.next { - panic("crypto/cipher: counter decreased or remained the same") + // Ensure the counter is strictly increasing. + if counter == math.MaxUint64 { + panic("crypto/cipher: counter exhausted") + } + if counter < g.next { + panic("crypto/cipher: counter decreased or remained the same") + } + g.next = counter + 1 } - g.next = counter + 1 fips140.RecordApproved() return g.g.sealAfterIndicator(dst, nonce, plaintext, data) diff --git a/src/crypto/internal/fips140deps/fipsdeps_test.go b/src/crypto/internal/fips140deps/fipsdeps_test.go index 29a56047c3c5fd3f36f48a7d9d059027cdb9e672..e2d1d1836c836ffd43f594a75a5a17ef55dbdca8 100644 --- a/src/crypto/internal/fips140deps/fipsdeps_test.go +++ b/src/crypto/internal/fips140deps/fipsdeps_test.go @@ -44,7 +44,7 @@ {{end -}} {{range .XTestImports -}} {{$path}} {{.}} {{end -}}`, "crypto/internal/fips140/...") - bout, err := cmd.CombinedOutput() + bout, err := testenv.CleanCmdEnv(cmd).CombinedOutput() if err != nil { t.Fatalf("go list: %v\n%s", err, bout) } diff --git a/src/crypto/internal/fips140test/acvp_test.go b/src/crypto/internal/fips140test/acvp_test.go index 05dde352191ff44874827e9101bc2b542292619c..e94bab74fd5774df09541e050dce130709f42569 100644 --- a/src/crypto/internal/fips140test/acvp_test.go +++ b/src/crypto/internal/fips140test/acvp_test.go @@ -23,7 +23,7 @@ "bufio" "bytes" "crypto/elliptic" "crypto/internal/cryptotest" - "crypto/internal/entropy/v1.0.0" + entropy "crypto/internal/entropy/v1.0.0" "crypto/internal/fips140" "crypto/internal/fips140/aes" "crypto/internal/fips140/aes/gcm" @@ -2108,8 +2108,8 @@ const ( bsslModule = "boringssl.googlesource.com/boringssl.git" bsslVersion = "v0.0.0-20251111011041-baaf868e6e8f" - goAcvpModule = "github.com/cpu/go-acvp" - goAcvpVersion = "v0.0.0-20251111204335-5c8bf7f5cac1" + goAcvpModule = "github.com/geomys/acvp-testdata" + goAcvpVersion = "v0.0.0-20251201200548-d893de8b8b1c" ) // In crypto/tls/bogo_shim_test.go the test is skipped if run on a builder with runtime.GOOS == "windows" @@ -2128,16 +2128,13 @@ t.Log("building acvptool") // Build the acvptool binary. toolPath := filepath.Join(t.TempDir(), "acvptool.exe") - goTool := testenv.GoToolPath(t) - cmd := testenv.Command(t, goTool, + cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", toolPath, "./util/fipstools/acvp/acvptool") cmd.Dir = bsslDir - out := &strings.Builder{} - cmd.Stderr = out - if err := cmd.Run(); err != nil { - t.Fatalf("failed to build acvptool: %s\n%s", err, out.String()) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("failed to build acvptool: %s\n%s", err, out) } // Similarly, fetch the ACVP data module that has vectors/expected answers. @@ -2163,17 +2160,17 @@ // Note: module prefix must match Wrapper value in testConfigFile. "-module-wrappers", "go:" + os.Args[0], "-tests", configPath, } - cmd = testenv.Command(t, goTool, args...) + cmd = testenv.Command(t, testenv.GoToolPath(t), args...) cmd.Dir = dataDir cmd.Env = append(os.Environ(), "ACVP_WRAPPER=1", "GODEBUG=fips140=on", ) - output, err := cmd.CombinedOutput() + out, err := cmd.CombinedOutput() + t.Logf("\n%s", out) if err != nil { - t.Fatalf("failed to run acvp tests: %s\n%s", err, string(output)) + t.Fatalf("failed to run acvp tests: %s", err) } - t.Log(string(output)) } func TestTooFewArgs(t *testing.T) { diff --git a/src/crypto/internal/fips140test/cast_test.go b/src/crypto/internal/fips140test/cast_test.go index 1978356ea5d8e3b17d9357d8380453cd2bbd371e..5a80006622c4c2b30fe1116822b98e7990453af4 100644 --- a/src/crypto/internal/fips140test/cast_test.go +++ b/src/crypto/internal/fips140test/cast_test.go @@ -78,7 +78,7 @@ // Ask "go list" for the location of the crypto/internal/fips140 tree, as it // might be the unpacked frozen tree selected with GOFIPS140. cmd := testenv.Command(t, testenv.GoToolPath(t), "list", "-f", `{{.Dir}}`, "crypto/internal/fips140") - out, err := cmd.CombinedOutput() + out, err := testenv.CleanCmdEnv(cmd).CombinedOutput() if err != nil { t.Fatalf("go list: %v\n%s", err, out) } @@ -161,13 +161,12 @@ } func TestCASTPasses(t *testing.T) { moduleStatus(t) - testenv.MustHaveExec(t) cryptotest.MustSupportFIPS140(t) cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestConditionals$", "-test.v") - cmd.Env = append(cmd.Env, "GODEBUG=fips140=debug") + cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=debug") out, err := cmd.CombinedOutput() - t.Logf("%s", out) + t.Logf("running with GODEBUG=fips140=debug:\n%s", out) if err != nil || !strings.Contains(string(out), "completed successfully") { t.Errorf("TestConditionals did not complete successfully") } @@ -185,7 +184,6 @@ } func TestCASTFailures(t *testing.T) { moduleStatus(t) - testenv.MustHaveExec(t) cryptotest.MustSupportFIPS140(t) for _, name := range allCASTs { @@ -197,11 +195,12 @@ t.Parallel() } t.Logf("Testing CAST/PCT failure...") cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestConditionals$", "-test.v") - cmd.Env = append(cmd.Env, fmt.Sprintf("GODEBUG=failfipscast=%s,fips140=on", name)) + GODEBUG := fmt.Sprintf("GODEBUG=failfipscast=%s,fips140=on", name) + cmd.Env = append(cmd.Environ(), GODEBUG) out, err := cmd.CombinedOutput() - t.Logf("%s", out) + t.Logf("running with %s:\n%s", GODEBUG, out) if err == nil { - t.Fatal("Test did not fail as expected") + t.Fatal("test did not fail as expected") } if strings.Contains(string(out), "completed successfully") { t.Errorf("CAST/PCT %s failure did not stop the program", name) diff --git a/src/crypto/internal/fips140test/check_test.go b/src/crypto/internal/fips140test/check_test.go index 2ceef6dd883d0ab8244eb2254c62f04b44498e76..8aef1f9b9b609e55ae7097ee36d7b38dc8ce80df 100644 --- a/src/crypto/internal/fips140test/check_test.go +++ b/src/crypto/internal/fips140test/check_test.go @@ -44,7 +44,6 @@ } func TestIntegrityCheckFailure(t *testing.T) { moduleStatus(t) - testenv.MustHaveExec(t) cryptotest.MustSupportFIPS140(t) bin, err := os.ReadFile(os.Args[0]) @@ -73,7 +72,7 @@ t.Logf("running modified binary...") cmd := testenv.Command(t, binPath, "-test.v", "-test.run=^TestIntegrityCheck$") cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=on") out, err := cmd.CombinedOutput() - t.Logf("%s", out) + t.Logf("running with GODEBUG=fips140=on:\n%s", out) if err == nil { t.Errorf("modified binary did not fail as expected") } diff --git a/src/crypto/internal/sysrand/rand_linux_test.go b/src/crypto/internal/sysrand/rand_linux_test.go index ee28ebe1350349cc699b122a18b2f620ab200d2b..8dca4b6efd65479a9186ae63deeac1f0fe88aec8 100644 --- a/src/crypto/internal/sysrand/rand_linux_test.go +++ b/src/crypto/internal/sysrand/rand_linux_test.go @@ -34,7 +34,7 @@ if testing.Short() { t.Skip("skipping test in short mode") } - testenv.MustHaveExec(t) + testenv.MustHaveExec(t) // testenv.Command can't skip from a goroutine done := make(chan struct{}) go func() { @@ -52,8 +52,9 @@ cmd := testenv.Command(t, testenv.Executable(t), "-test.v") cmd.Env = append(os.Environ(), "GO_GETRANDOM_DISABLED=1") out, err := cmd.CombinedOutput() + t.Logf("running with GO_GETRANDOM_DISABLED=1:\n%s", out) if err != nil { - t.Errorf("subprocess failed: %v\n%s", err, out) + t.Errorf("subprocess failed: %v", err) return } diff --git a/src/crypto/internal/sysrand/rand_test.go b/src/crypto/internal/sysrand/rand_test.go index 1d8eb00f5669358bb7c5e430b1d21c03db084696..1e81974b2f43ac6c78226d659dae3e51b6d5abfd 100644 --- a/src/crypto/internal/sysrand/rand_test.go +++ b/src/crypto/internal/sysrand/rand_test.go @@ -95,7 +95,6 @@ func TestReadError(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode") } - testenv.MustHaveExec(t) // We run this test in a subprocess because it's expected to crash. if os.Getenv("GO_TEST_READ_ERROR") == "1" { @@ -105,7 +104,7 @@ t.Error("Read did not crash") return } - cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestReadError$") + cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestReadError$", "-test.v") cmd.Env = append(os.Environ(), "GO_TEST_READ_ERROR=1") out, err := cmd.CombinedOutput() if err == nil { diff --git a/src/crypto/mlkem/mlkemtest/mlkemtest.go b/src/crypto/mlkem/mlkemtest/mlkemtest.go index 39e3994ea9beb2c995dbd329720f2d4bd3aa8fc8..40f64862bd49eb1fa6760f6e14e630fd5d97aea5 100644 --- a/src/crypto/mlkem/mlkemtest/mlkemtest.go +++ b/src/crypto/mlkem/mlkemtest/mlkemtest.go @@ -7,6 +7,7 @@ package mlkemtest import ( fips140mlkem "crypto/internal/fips140/mlkem" + "crypto/internal/fips140only" "crypto/mlkem" "errors" ) @@ -19,6 +20,9 @@ // It must only be used for known-answer tests. func Encapsulate768(ek *mlkem.EncapsulationKey768, random []byte) (sharedKey, ciphertext []byte, err error) { if len(random) != 32 { return nil, nil, errors.New("mlkemtest: Encapsulate768: random must be 32 bytes") + } + if fips140only.Enforced() { + return nil, nil, errors.New("crypto/mlkem/mlkemtest: use of derandomized encapsulation is not allowed in FIPS 140-only mode") } k, err := fips140mlkem.NewEncapsulationKey768(ek.Bytes()) if err != nil { @@ -36,6 +40,9 @@ // It must only be used for known-answer tests. func Encapsulate1024(ek *mlkem.EncapsulationKey1024, random []byte) (sharedKey, ciphertext []byte, err error) { if len(random) != 32 { return nil, nil, errors.New("mlkemtest: Encapsulate1024: random must be 32 bytes") + } + if fips140only.Enforced() { + return nil, nil, errors.New("crypto/mlkem/mlkemtest: use of derandomized encapsulation is not allowed in FIPS 140-only mode") } k, err := fips140mlkem.NewEncapsulationKey1024(ek.Bytes()) if err != nil { diff --git a/src/crypto/purego_test.go b/src/crypto/purego_test.go index 62be347e0c6822f8f879326d266850c116da80b0..ebc9110cecee82bcaea66d2a95987f309a36e633 100644 --- a/src/crypto/purego_test.go +++ b/src/crypto/purego_test.go @@ -9,7 +9,6 @@ "go/build" "internal/testenv" "log" "os" - "os/exec" "strings" "testing" ) @@ -19,8 +18,9 @@ // packages don't require any assembly. This is used by alternative compilers // such as TinyGo. See also the "crypto/...:purego" test in cmd/dist, which // ensures the packages build correctly. func TestPureGoTag(t *testing.T) { - cmd := exec.Command(testenv.GoToolPath(t), "list", "-e", "crypto/...", "math/big") - cmd.Env = append(cmd.Env, "GOOS=linux") + cmd := testenv.Command(t, testenv.GoToolPath(t), "list", "-e", "crypto/...", "math/big") + cmd = testenv.CleanCmdEnv(cmd) + cmd.Env = append(cmd.Environ(), "GOOS=linux", "GOFIPS140=off") cmd.Stderr = os.Stderr out, err := cmd.Output() if err != nil { @@ -28,9 +28,9 @@ log.Fatalf("loading package list: %v\n%s", err, out) } pkgs := strings.Split(strings.TrimSpace(string(out)), "\n") - cmd = exec.Command(testenv.GoToolPath(t), "tool", "dist", "list") + cmd = testenv.Command(t, testenv.GoToolPath(t), "tool", "dist", "list") cmd.Stderr = os.Stderr - out, err = cmd.Output() + out, err = testenv.CleanCmdEnv(cmd).Output() if err != nil { log.Fatalf("loading architecture list: %v\n%s", err, out) } diff --git a/src/crypto/rand/rand_test.go b/src/crypto/rand/rand_test.go index 22ccb8a35334c9f509282021ce10277248fdc176..3bb3d5f1acda25ccf123ffa0990782cc8f6e513d 100644 --- a/src/crypto/rand/rand_test.go +++ b/src/crypto/rand/rand_test.go @@ -180,7 +180,7 @@ t.Error("Read did not crash") return } - cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestReadError$") + cmd := testenv.Command(t, testenv.Executable(t), "-test.run=^TestReadError$", "-test.v") cmd.Env = append(os.Environ(), "GO_TEST_READ_ERROR=1") out, err := cmd.CombinedOutput() if err == nil { diff --git a/src/crypto/subtle/dit.go b/src/crypto/subtle/dit.go index c23df971f0bd71fca0c82030e6b654f114111380..733261c3b09d2f99c7d85af19ec812d75bd27f5c 100644 --- a/src/crypto/subtle/dit.go +++ b/src/crypto/subtle/dit.go @@ -6,19 +6,29 @@ package subtle import ( "internal/runtime/sys" - "runtime" + _ "unsafe" ) // WithDataIndependentTiming enables architecture specific features which ensure // that the timing of specific instructions is independent of their inputs // before executing f. On f returning it disables these features. // +// Any goroutine spawned by f will also have data independent timing enabled for +// its lifetime, as well as any of their descendant goroutines. +// +// Any C code called via cgo from within f, or from a goroutine spawned by f, will +// also have data independent timing enabled for the duration of the call. If the +// C code disables data independent timing, it will be re-enabled on return to Go. +// +// If C code called via cgo, from f or elsewhere, enables or disables data +// independent timing then calling into Go will preserve that state for the +// duration of the call. +// // WithDataIndependentTiming should only be used when f is written to make use // of constant-time operations. WithDataIndependentTiming does not make // variable-time code constant-time. // -// WithDataIndependentTiming may lock the current goroutine to the OS thread for -// the duration of f. Calls to WithDataIndependentTiming may be nested. +// Calls to WithDataIndependentTiming may be nested. // // On Arm64 processors with FEAT_DIT, WithDataIndependentTiming enables // PSTATE.DIT. See https://developer.arm.com/documentation/ka005181/1-0/?lang=en. @@ -33,18 +43,21 @@ f() return } - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - alreadyEnabled := sys.EnableDIT() + alreadyEnabled := setDITEnabled() // disableDIT is called in a deferred function so that if f panics we will // still disable DIT, in case the panic is recovered further up the stack. defer func() { if !alreadyEnabled { - sys.DisableDIT() + setDITDisabled() } }() f() } + +//go:linkname setDITEnabled +func setDITEnabled() bool + +//go:linkname setDITDisabled +func setDITDisabled() diff --git a/src/crypto/subtle/dit_test.go b/src/crypto/subtle/dit_test.go index 29779683b57c06b2c5cd86721b84a2ac74afbf03..952a18db1f66cd3b0a4bd53cf49e070dbf1fde57 100644 --- a/src/crypto/subtle/dit_test.go +++ b/src/crypto/subtle/dit_test.go @@ -63,3 +63,25 @@ panic("bad") }) } + +func TestDITGoroutineInheritance(t *testing.T) { + if !cpu.ARM64.HasDIT { + t.Skip("CPU does not support DIT") + } + + ditAlreadyEnabled := sys.DITEnabled() + + WithDataIndependentTiming(func() { + done := make(chan struct{}) + go func() { + if !sys.DITEnabled() { + t.Error("DIT not enabled in new goroutine") + } + close(done) + }() + <-done + if !ditAlreadyEnabled && !sys.DITEnabled() { + t.Fatal("dit unset after returning from goroutine started in WithDataIndependentTiming closure") + } + }) +} diff --git a/src/crypto/tls/bogo_shim_test.go b/src/crypto/tls/bogo_shim_test.go index a14386a61c23f45eed67f711af4f158b11751f09..1b5fc49c4f319cbfa0a0a0c5e49fd11328158815 100644 --- a/src/crypto/tls/bogo_shim_test.go +++ b/src/crypto/tls/bogo_shim_test.go @@ -542,7 +542,6 @@ tcpConn.CloseRead() } func TestBogoSuite(t *testing.T) { - testenv.MustHaveGoBuild(t) if testing.Short() { t.Skip("skipping in short mode") } @@ -589,10 +588,8 @@ args = append(args, fmt.Sprintf("-test=%s", *bogoFilter)) } cmd := testenv.Command(t, testenv.GoToolPath(t), args...) - out := &strings.Builder{} - cmd.Stderr = out cmd.Dir = filepath.Join(bogoDir, "ssl/test/runner") - err = cmd.Run() + out, err := cmd.CombinedOutput() // NOTE: we don't immediately check the error, because the failure could be either because // the runner failed for some unexpected reason, or because a test case failed, and we // cannot easily differentiate these cases. We check if the JSON results file was written, @@ -707,7 +704,6 @@ t.Fatalf("git checkout failed: %v", err) } t.Logf("using fresh local bogo checkout from %q", localBogoDir) - return } func generateReport(results bogoResults, outPath string) error { diff --git a/src/crypto/tls/link_test.go b/src/crypto/tls/link_test.go index 454d370c8852bb875504dd68385e645205e6eae0..cc681d1dfbd0d0a5f5aaf9f151f79b4f3900cbe1 100644 --- a/src/crypto/tls/link_test.go +++ b/src/crypto/tls/link_test.go @@ -8,7 +8,6 @@ import ( "bytes" "internal/testenv" "os" - "os/exec" "path/filepath" "testing" ) @@ -19,8 +18,6 @@ if testing.Short() { t.Skip("skipping in short mode") } t.Parallel() - goBin := testenv.GoToolPath(t) - testenv.MustHaveGoBuild(t) tests := []struct { name string @@ -80,17 +77,17 @@ if err := os.WriteFile(goFile, []byte(tt.program), 0644); err != nil { t.Fatal(err) } os.Remove(exeFile) - cmd := exec.Command(goBin, "build", "-o", "x.exe", "x.go") + cmd := testenv.Command(t, testenv.GoToolPath(t), "build", "-o", "x.exe", "x.go") cmd.Dir = tmpDir if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("compile: %v, %s", err, out) + t.Fatalf("compile: %v\n%s", err, out) } - cmd = exec.Command(goBin, "tool", "nm", "x.exe") + cmd = testenv.Command(t, testenv.GoToolPath(t), "tool", "nm", "x.exe") cmd.Dir = tmpDir - nm, err := cmd.CombinedOutput() + nm, err := testenv.CleanCmdEnv(cmd).CombinedOutput() if err != nil { - t.Fatalf("nm: %v, %s", err, nm) + t.Fatalf("nm: %v\n%s", err, nm) } for _, sym := range tt.want { if !bytes.Contains(nm, []byte(sym)) { diff --git a/src/crypto/x509/bettertls_test.go b/src/crypto/x509/bettertls_test.go index 3a0b98cd74c13bb7dc50d58e230ba1ee67ba65c6..3ef67b05a91753ed2b1ea52e3c7486a5b69fac05 100644 --- a/src/crypto/x509/bettertls_test.go +++ b/src/crypto/x509/bettertls_test.go @@ -148,13 +148,9 @@ "run", "./test-suites/cmd/bettertls", "export-tests", "--out", testsJSONPath) cmd.Dir = bettertlsDir - t.Log("running bettertls export-tests command") - output, err := cmd.CombinedOutput() - if err != nil { - t.Fatalf( - "failed to run bettertls export-tests: %v\nOutput: %s", - err, output) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("failed to run bettertls export-tests: %v\n%s", err, out) } jsonData, err := os.ReadFile(testsJSONPath) diff --git a/src/crypto/x509/name_constraints_test.go b/src/crypto/x509/name_constraints_test.go index 32b6823c4ce67cc6f8705cc5367448acecab2f29..9a796e100d4719f8cc8b47873344a43ce61f3bea 100644 --- a/src/crypto/x509/name_constraints_test.go +++ b/src/crypto/x509/name_constraints_test.go @@ -14,6 +14,7 @@ "encoding/asn1" "encoding/hex" "encoding/pem" "fmt" + "internal/testenv" "math/big" "net" "net/url" @@ -2044,13 +2045,9 @@ defer os.Remove(leafFile.Name()) } args = append(args, leafFile.Name()) - var output bytes.Buffer - cmd := exec.Command("openssl", args...) - cmd.Stdout = &output - cmd.Stderr = &output - - err := cmd.Run() - return output.String(), err + cmd := testenv.Command(t, "openssl", args...) + out, err := cmd.CombinedOutput() + return string(out), err } var rfc2821Tests = []struct { diff --git a/src/crypto/x509/root_linux_test.go b/src/crypto/x509/root_linux_test.go index d4f92e0972b123bedb8d2c2f99ebf3cd7165f8ab..8b8a29beeadcaf9096ebd72e89b142348d63d2da 100644 --- a/src/crypto/x509/root_linux_test.go +++ b/src/crypto/x509/root_linux_test.go @@ -11,7 +11,6 @@ "encoding/pem" "fmt" "internal/testenv" "os" - "os/exec" "syscall" "testing" ) @@ -20,13 +19,12 @@ func TestSetFallbackRoots(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode") } - testenv.MustHaveExec(t) test := func(t *testing.T, name string, f func(t *testing.T)) { t.Run(name, func(t *testing.T) { if os.Getenv("CRYPTO_X509_SETFALLBACKROOTS_TEST") != "1" { // Execute test in a separate process with CRYPTO_X509_SETFALBACKROOTS_TEST env. - cmd := exec.Command(os.Args[0], fmt.Sprintf("-test.run=^%v$", t.Name())) + cmd := testenv.Command(t, testenv.Executable(t), fmt.Sprintf("-test.run=^%v$", t.Name()), "-test.v") cmd.Env = append(os.Environ(), "CRYPTO_X509_SETFALLBACKROOTS_TEST=1") cmd.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: syscall.CLONE_NEWNS | syscall.CLONE_NEWUSER, @@ -34,11 +32,12 @@ UidMappings: []syscall.SysProcIDMap{{ContainerID: 0, HostID: os.Getuid(), Size: 1}}, GidMappings: []syscall.SysProcIDMap{{ContainerID: 0, HostID: os.Getgid(), Size: 1}}, } out, err := cmd.CombinedOutput() + if testenv.SyscallIsNotSupported(err) { + t.Skipf("skipping: could not start process with CLONE_NEWNS and CLONE_NEWUSER: %v", err) + } + t.Logf("running with CRYPTO_X509_SETFALLBACKROOTS_TEST=1:\n%s", out) if err != nil { - if testenv.SyscallIsNotSupported(err) { - t.Skipf("skipping: could not start process with CLONE_NEWNS and CLONE_NEWUSER: %v", err) - } - t.Errorf("%v\n%s", err, out) + t.Errorf("CRYPTO_X509_SETFALLBACKROOTS_TEST=1 subprocess failed: %v", err) } return } diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index 183ee303faec985e961edb564f3e45734ce37985..dd53168559ad426ad979d672f106a27457a38aa0 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -30,7 +30,6 @@ "math" "math/big" "net" "net/url" - "os/exec" "reflect" "runtime" "slices" @@ -1461,9 +1460,7 @@ func TestImports(t *testing.T) { if testing.Short() { t.Skip("skipping in -short mode") } - testenv.MustHaveGoRun(t) - - if out, err := exec.Command(testenv.GoToolPath(t), "run", "x509_test_import.go").CombinedOutput(); err != nil { + if out, err := testenv.Command(t, testenv.GoToolPath(t), "run", "x509_test_import.go").CombinedOutput(); err != nil { t.Errorf("failed to run x509_test_import.go: %s\n%s", err, out) } } diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go index 487870be63209ebb711c97983e5a9c55db2b66ab..d0892e80fc28d5e54275751e2861306f926698bd 100644 --- a/src/database/sql/driver/driver.go +++ b/src/database/sql/driver/driver.go @@ -515,18 +515,6 @@ Rows ColumnTypePrecisionScale(index int) (precision, scale int64, ok bool) } -// RowsColumnScanner may be implemented by [Rows]. It allows the driver to completely -// take responsibility for how values are scanned and replace the normal [database/sql]. -// scanning path. This allows drivers to directly support types that do not implement -// [database/sql.Scanner]. -type RowsColumnScanner interface { - Rows - - // ScanColumn copies the column in the current row into the value pointed at by - // dest. It returns [ErrSkip] to fall back to the normal [database/sql] scanning path. - ScanColumn(dest any, index int) error -} - // Tx is a transaction. type Tx interface { Commit() error diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index 85b9ffc37d9445c469cad271f7fa76686cad6657..4be450ca87687728797bafdb10e976adc5a71f58 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -3396,16 +3396,7 @@ return fmt.Errorf("sql: expected %d destination arguments in Scan, not %d", len(rs.lastcols), len(dest)) } for i, sv := range rs.lastcols { - err := driver.ErrSkip - - if rcs, ok := rs.rowsi.(driver.RowsColumnScanner); ok { - err = rcs.ScanColumn(dest[i], i) - } - - if err == driver.ErrSkip { - err = convertAssignRows(dest[i], sv, rs) - } - + err := convertAssignRows(dest[i], sv, rs) if err != nil { return fmt.Errorf(`sql: Scan error on column index %d, name %q: %w`, i, rs.rowsi.Columns()[i], err) } diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go index 6ee850585589e4d4099f6043fa6c43ba637dc8d4..e8a65600973ba72b3960bb2a193999f414f3f2fa 100644 --- a/src/database/sql/sql_test.go +++ b/src/database/sql/sql_test.go @@ -4200,102 +4200,6 @@ t.Fatalf("expected error with bad argument, got %v", err) } } -type rcsDriver struct { - fakeDriver -} - -func (d *rcsDriver) Open(dsn string) (driver.Conn, error) { - c, err := d.fakeDriver.Open(dsn) - fc := c.(*fakeConn) - fc.db.allowAny = true - return &rcsConn{fc}, err -} - -type rcsConn struct { - *fakeConn -} - -func (c *rcsConn) PrepareContext(ctx context.Context, q string) (driver.Stmt, error) { - stmt, err := c.fakeConn.PrepareContext(ctx, q) - if err != nil { - return stmt, err - } - return &rcsStmt{stmt.(*fakeStmt)}, nil -} - -type rcsStmt struct { - *fakeStmt -} - -func (s *rcsStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { - rows, err := s.fakeStmt.QueryContext(ctx, args) - if err != nil { - return rows, err - } - return &rcsRows{rows.(*rowsCursor)}, nil -} - -type rcsRows struct { - *rowsCursor -} - -func (r *rcsRows) ScanColumn(dest any, index int) error { - switch d := dest.(type) { - case *int64: - *d = 42 - return nil - } - - return driver.ErrSkip -} - -func TestRowsColumnScanner(t *testing.T) { - Register("RowsColumnScanner", &rcsDriver{}) - db, err := Open("RowsColumnScanner", "") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - _, err = db.ExecContext(ctx, "CREATE|t|str=string,n=int64") - if err != nil { - t.Fatal("exec create", err) - } - - _, err = db.ExecContext(ctx, "INSERT|t|str=?,n=?", "foo", int64(1)) - if err != nil { - t.Fatal("exec insert", err) - } - var ( - str string - i64 int64 - i int - f64 float64 - ui uint - ) - err = db.QueryRowContext(ctx, "SELECT|t|str,n,n,n,n|").Scan(&str, &i64, &i, &f64, &ui) - if err != nil { - t.Fatal("select", err) - } - - list := []struct{ got, want any }{ - {str, "foo"}, - {i64, int64(42)}, - {i, int(1)}, - {f64, float64(1)}, - {ui, uint(1)}, - } - - for index, item := range list { - if !reflect.DeepEqual(item.got, item.want) { - t.Errorf("got %#v wanted %#v for index %d", item.got, item.want, index) - } - } -} - func TestOpenConnector(t *testing.T) { Register("testctx", &fakeDriverCtx{}) db, err := Open("testctx", "people") diff --git a/src/encoding/json/jsontext/decode.go b/src/encoding/json/jsontext/decode.go index 511832f2ae087970600a4d30d1e5d3e408ad50aa..48d66fb1d4875b378ef0ba07ecbf41a3225e89c1 100644 --- a/src/encoding/json/jsontext/decode.go +++ b/src/encoding/json/jsontext/decode.go @@ -306,7 +306,7 @@ } // PeekKind retrieves the next token kind, but does not advance the read offset. // -// It returns 0 if an error occurs. Any such error is cached until +// It returns [KindInvalid] if an error occurs. Any such error is cached until // the next read call and it is the caller's responsibility to eventually // follow up a PeekKind call with a read call. func (d *Decoder) PeekKind() Kind { @@ -1154,9 +1154,9 @@ // StackIndex returns information about the specified stack level. // It must be a number between 0 and [Decoder.StackDepth], inclusive. // For each level, it reports the kind: // -// - 0 for a level of zero, -// - '{' for a level representing a JSON object, and -// - '[' for a level representing a JSON array. +// - [KindInvalid] for a level of zero, +// - [KindBeginObject] for a level representing a JSON object, and +// - [KindBeginArray] for a level representing a JSON array. // // It also reports the length of that JSON object or array. // Each name and value in a JSON object is counted separately, diff --git a/src/encoding/json/jsontext/decode_test.go b/src/encoding/json/jsontext/decode_test.go index 209ff65ec8191bbdd6fd51ccb9fd33f644015210..3f48cae2d1d09377e0c6697b3b098dee41361efd 100644 --- a/src/encoding/json/jsontext/decode_test.go +++ b/src/encoding/json/jsontext/decode_test.go @@ -193,8 +193,8 @@ }{{ name: jsontest.Name("InvalidStart"), in: ` #`, calls: []decoderMethodCall{ - {'#', zeroToken, newInvalidCharacterError("#", "at start of value").withPos(" ", ""), ""}, - {'#', zeroValue, newInvalidCharacterError("#", "at start of value").withPos(" ", ""), ""}, + {0, zeroToken, newInvalidCharacterError("#", "at start of value").withPos(" ", ""), ""}, + {0, zeroValue, newInvalidCharacterError("#", "at start of value").withPos(" ", ""), ""}, }, }, { name: jsontest.Name("StreamN0"), diff --git a/src/encoding/json/jsontext/encode.go b/src/encoding/json/jsontext/encode.go index e3b9c04ca615a0803156c691ca4a2dbb1bb90043..20f020700b810c9715db46147bdc67e8f1208b9b 100644 --- a/src/encoding/json/jsontext/encode.go +++ b/src/encoding/json/jsontext/encode.go @@ -946,9 +946,9 @@ // StackIndex returns information about the specified stack level. // It must be a number between 0 and [Encoder.StackDepth], inclusive. // For each level, it reports the kind: // -// - 0 for a level of zero, -// - '{' for a level representing a JSON object, and -// - '[' for a level representing a JSON array. +// - [KindInvalid] for a level of zero, +// - [KindBeginObject] for a level representing a JSON object, and +// - [KindBeginArray] for a level representing a JSON array. // // It also reports the length of that JSON object or array. // Each name and value in a JSON object is counted separately, diff --git a/src/encoding/json/jsontext/token.go b/src/encoding/json/jsontext/token.go index e78c3f84d8650fec92a739f7d7016f4b881447c4..6d9ad4b499888d96eddc1af2706f115d6c48df96 100644 --- a/src/encoding/json/jsontext/token.go +++ b/src/encoding/json/jsontext/token.go @@ -472,29 +472,33 @@ return invalidKind } } +// A Kind represents the kind of a JSON token. +// // Kind represents each possible JSON token kind with a single byte, // which is conveniently the first byte of that kind's grammar -// with the restriction that numbers always be represented with '0': -// -// - 'n': null -// - 'f': false -// - 't': true -// - '"': string -// - '0': number -// - '{': object begin -// - '}': object end -// - '[': array begin -// - ']': array end -// -// An invalid kind is usually represented using 0, -// but may be non-zero due to invalid JSON data. +// with the restriction that numbers always be represented with '0'. type Kind byte +const ( + KindInvalid Kind = 0 // invalid kind + KindNull Kind = 'n' // null + KindFalse Kind = 'f' // false + KindTrue Kind = 't' // true + KindString Kind = '"' // string + KindNumber Kind = '0' // number + KindBeginObject Kind = '{' // begin object + KindEndObject Kind = '}' // end object + KindBeginArray Kind = '[' // begin array + KindEndArray Kind = ']' // end array +) + const invalidKind Kind = 0 // String prints the kind in a humanly readable fashion. func (k Kind) String() string { switch k { + case 0: + return "invalid" case 'n': return "null" case 'f': @@ -518,10 +522,31 @@ return "" } } -// normalize coalesces all possible starting characters of a number as just '0'. +var normKind = [256]Kind{ + 'n': 'n', + 'f': 'f', + 't': 't', + '"': '"', + '{': '{', + '}': '}', + '[': '[', + ']': ']', + '-': '0', + '0': '0', + '1': '0', + '2': '0', + '3': '0', + '4': '0', + '5': '0', + '6': '0', + '7': '0', + '8': '0', + '9': '0', +} + +// normalize coalesces all possible starting characters of a number as just '0', +// and converts all invalid kinds to 0. func (k Kind) normalize() Kind { - if k == '-' || ('0' <= k && k <= '9') { - return '0' - } - return k + // A lookup table keeps the inlining cost as low as possible. + return normKind[k] } diff --git a/src/encoding/json/jsontext/value.go b/src/encoding/json/jsontext/value.go index a4b06b2a947de74ceae27752b2a5603c271154bc..84c919b9dc591e160382457ff3f42f517c35adbd 100644 --- a/src/encoding/json/jsontext/value.go +++ b/src/encoding/json/jsontext/value.go @@ -236,7 +236,7 @@ return nil } // Kind returns the starting token kind. -// For a valid value, this will never include '}' or ']'. +// For a valid value, this will never include [KindEndObject] or [KindEndArray]. func (v Value) Kind() Kind { if v := v[jsonwire.ConsumeWhitespace(v):]; len(v) > 0 { return Kind(v[0]).normalize() diff --git a/src/encoding/json/stream_test.go b/src/encoding/json/stream_test.go index 0e937cfaa13c783387a8468a5a0ecc6ccff62f98..ba3bc4002b1ceb25c8cc148cf2d1d519fff2adb0 100644 --- a/src/encoding/json/stream_test.go +++ b/src/encoding/json/stream_test.go @@ -459,6 +459,9 @@ }}, {CaseName: Name(""), json: ` \a`, expTokens: []any{ &SyntaxError{"invalid character '\\\\' looking for beginning of value", 1}, }}, + {CaseName: Name(""), json: `,`, expTokens: []any{ + &SyntaxError{"invalid character ',' looking for beginning of value", 0}, + }}, } for _, tt := range tests { t.Run(tt.Name, func(t *testing.T) { @@ -466,6 +469,15 @@ dec := NewDecoder(strings.NewReader(tt.json)) for i, want := range tt.expTokens { var got any var err error + + wantMore := true + switch want { + case Delim(']'), Delim('}'): + wantMore = false + } + if got := dec.More(); got != wantMore { + t.Fatalf("%s:\n\tinput: %s\n\tdec.More() = %v, want %v (next token: %T(%v))", tt.Where, tt.json, got, wantMore, want, want) + } if dt, ok := want.(decodeThis); ok { want = dt.v diff --git a/src/encoding/json/v2_stream.go b/src/encoding/json/v2_stream.go index dcee553ee13336e20548d2324fd40c22e3357636..ca0822cb7336cba4d5ddd87b6c58d1475ac4cae4 100644 --- a/src/encoding/json/v2_stream.go +++ b/src/encoding/json/v2_stream.go @@ -197,6 +197,9 @@ // number, and null—along with delimiters [ ] { } of type [Delim] // to mark the start and end of arrays and objects. // Commas and colons are elided. func (dec *Decoder) Token() (Token, error) { + if dec.err != nil { + return nil, dec.err + } tok, err := dec.dec.ReadToken() if err != nil { // Historically, v1 would report just [io.EOF] if @@ -238,7 +241,20 @@ // current array or object being parsed. func (dec *Decoder) More() bool { dec.hadPeeked = true k := dec.dec.PeekKind() - return k > 0 && k != ']' && k != '}' + if k == 0 { + if dec.err == nil { + // PeekKind doesn't distinguish between EOF and error, + // so read the next token to see which we get. + _, err := dec.dec.ReadToken() + if err == nil { + // This is only possible if jsontext violates its documentation. + err = errors.New("json: successful read after failed peek") + } + dec.err = transformSyntacticError(err) + } + return dec.err != io.EOF + } + return k != ']' && k != '}' } // InputOffset returns the input stream byte offset of the current decoder position. diff --git a/src/encoding/json/v2_stream_test.go b/src/encoding/json/v2_stream_test.go index 0885631fb5937fb663b6886a18b74c38a83ee83f..d7f9f110848add592652adb40f43eab909f3b640 100644 --- a/src/encoding/json/v2_stream_test.go +++ b/src/encoding/json/v2_stream_test.go @@ -439,6 +439,9 @@ }}, {CaseName: Name(""), json: ` \a`, expTokens: []any{ &SyntaxError{"invalid character '\\\\' looking for beginning of value", len64(` `)}, }}, + {CaseName: Name(""), json: `,`, expTokens: []any{ + &SyntaxError{"invalid character ',' looking for beginning of value", 0}, + }}, } for _, tt := range tests { t.Run(tt.Name, func(t *testing.T) { @@ -446,6 +449,15 @@ dec := NewDecoder(strings.NewReader(tt.json)) for i, want := range tt.expTokens { var got any var err error + + wantMore := true + switch want { + case Delim(']'), Delim('}'): + wantMore = false + } + if got := dec.More(); got != wantMore { + t.Fatalf("%s:\n\tinput: %s\n\tdec.More() = %v, want %v (next token: %T(%v)) rem:%q", tt.Where, tt.json, got, wantMore, want, want, tt.json[dec.InputOffset():]) + } if dt, ok := want.(decodeThis); ok { want = dt.v diff --git a/src/go.mod b/src/go.mod index f79455c970ecb29269adbefb2b14512889740eb2..efc07451b534487f5f3f8c13a91343e5e530e9af 100644 --- a/src/go.mod +++ b/src/go.mod @@ -3,11 +3,11 @@ go 1.26 require ( - golang.org/x/crypto v0.45.0 + golang.org/x/crypto v0.46.1-0.20251210140736-7dacc380ba00 golang.org/x/net v0.47.1-0.20251128220604-7c360367ab7e ) require ( - golang.org/x/sys v0.38.1-0.20251125153526-08e54827f670 // indirect - golang.org/x/text v0.31.1-0.20251128220601-087616b6cde9 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect ) diff --git a/src/go.sum b/src/go.sum index e2cf9591bc56dc01ed616739059d8f612d5f4a38..b6b841b44d8e387982485c61444eefb6fc9893b4 100644 --- a/src/go.sum +++ b/src/go.sum @@ -1,8 +1,8 @@ -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.46.1-0.20251210140736-7dacc380ba00 h1:JgcPM1rzpSOZS8y69FQvnY0xN0ciHlpQqwTXJcuZIA4= +golang.org/x/crypto v0.46.1-0.20251210140736-7dacc380ba00/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= golang.org/x/net v0.47.1-0.20251128220604-7c360367ab7e h1:PAAT9cIDvIAIRQVz2txQvUFRt3jOlhiO84ihd8XMGlg= golang.org/x/net v0.47.1-0.20251128220604-7c360367ab7e/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= -golang.org/x/sys v0.38.1-0.20251125153526-08e54827f670 h1:s8+qM6u6X24AFOioI7tH2p/6zxCHqt3G7zwUYm7MgUc= -golang.org/x/sys v0.38.1-0.20251125153526-08e54827f670/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.31.1-0.20251128220601-087616b6cde9 h1:IjQf87/qLz2y0SiCc0uY3DwajALXkAgP1Pxal0mmdrM= -golang.org/x/text v0.31.1-0.20251128220601-087616b6cde9/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index d58bd294cd103c116a2c436617be4357a858e5ca..f4b7e9dae5f3aef8314060f24fa618b66eb2d18b 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -73,7 +73,7 @@ internal/goarch < internal/abi; internal/byteorder, internal/cpu, internal/goarch < internal/chacha8rand; internal/goarch, math/bits < internal/strconv; - internal/cpu, internal/strconv < simd; + internal/cpu, internal/strconv < simd/archsimd; # RUNTIME is the core runtime group of packages, all of them very light-weight. internal/abi, @@ -709,7 +709,7 @@ FMT, DEBUG, flag, runtime/trace, internal/sysinfo, math/rand < testing; testing, math - < simd/internal/test_helpers; + < simd/archsimd/internal/test_helpers; log/slog, testing < testing/slogtest; diff --git a/src/go/doc/example.go b/src/go/doc/example.go index 228bdf58f81949ae9ae2f624690fa45047d42ea1..ba1f863df0a2858ac8bed64c8f7c94de4a311261 100644 --- a/src/go/doc/example.go +++ b/src/go/doc/example.go @@ -11,7 +11,6 @@ "cmp" "go/ast" "go/token" "internal/lazyregexp" - "path" "slices" "strconv" "strings" @@ -221,7 +220,7 @@ // We don't support examples that import syscall/js, // because the package syscall/js is not available in the playground. return nil } - n := path.Base(p) + n := assumedPackageName(p) if s.Name != nil { n = s.Name.Name switch n { diff --git a/src/go/doc/testdata/examples/major_version.go b/src/go/doc/testdata/examples/major_version.go new file mode 100644 index 0000000000000000000000000000000000000000..6d91874a8913d51346b8c77bce0617d6f1652618 --- /dev/null +++ b/src/go/doc/testdata/examples/major_version.go @@ -0,0 +1,14 @@ +package foo_test + +import ( + "example.com/foo/v3" + "example.com/go-bar" +) + +func Example() { + foo.Print("hello") + bar.Print("world") + // Output: + // hello + // world +} diff --git a/src/go/doc/testdata/examples/major_version.golden b/src/go/doc/testdata/examples/major_version.golden new file mode 100644 index 0000000000000000000000000000000000000000..7cf2f2f32a74f156f78a3bde3abd6c3abd10ed17 --- /dev/null +++ b/src/go/doc/testdata/examples/major_version.golden @@ -0,0 +1,15 @@ +-- .Play -- +package main + +import ( + "example.com/foo/v3" + "example.com/go-bar" +) + +func main() { + foo.Print("hello") + bar.Print("world") +} +-- .Output -- +hello +world diff --git a/src/go/types/cycles.go b/src/go/types/cycles.go index bd894258b121902c90a1fa1dfcc54d62e8c9c493..9f1e0e8b58879a946e63709c40161bd91d46323f 100644 --- a/src/go/types/cycles.go +++ b/src/go/types/cycles.go @@ -105,3 +105,51 @@ assert(i < 0) } } } + +// TODO(markfreeman): Can the value cached on Named be used in validType / hasVarSize? + +// finiteSize returns whether a type has finite size. +func (check *Checker) finiteSize(t Type) bool { + switch t := Unalias(t).(type) { + case *Named: + if t.stateHas(hasFinite) { + return t.finite + } + + if i, ok := check.objPathIdx[t.obj]; ok { + cycle := check.objPath[i:] + check.cycleError(cycle, firstInSrc(cycle)) + return false + } + check.push(t.obj) + defer check.pop() + + isFinite := check.finiteSize(t.fromRHS) + + t.mu.Lock() + defer t.mu.Unlock() + // Careful, t.finite has lock-free readers. Since we might be racing + // another call to finiteSize, we have to avoid overwriting t.finite. + // Otherwise, the race detector will be tripped. + if !t.stateHas(hasFinite) { + t.finite = isFinite + t.setState(hasFinite) + } + + return isFinite + + case *Array: + // The array length is already computed. If it was a valid length, it + // is finite; else, an error was reported in the computation. + return check.finiteSize(t.elem) + + case *Struct: + for _, f := range t.fields { + if !check.finiteSize(f.typ) { + return false + } + } + } + + return true +} diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 09f7cdda802bad365d68f3556ce2b67ec8e9c68e..6ff5695390d1c549922c55b04ac64b235749d85d 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1033,12 +1033,9 @@ func (check *Checker) pendingType(x *operand) { if x.mode == invalid || x.mode == novalue { return } - if n, ok := Unalias(x.typ).(*Named); ok { - if i, ok := check.objPathIdx[n.obj]; ok { - check.cycleError(check.objPath, i) - x.mode = invalid - x.typ = Typ[Invalid] - } + if !check.finiteSize(x.typ) { + x.mode = invalid + x.typ = Typ[Invalid] } } diff --git a/src/go/types/named.go b/src/go/types/named.go index be6a0f54267c0268a6aa2d1132541109f0f813f4..3b618f403dc629d11e23e36ff08c1388807e418d 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -120,6 +120,7 @@ state_ uint32 // the current state of this type; must only be accessed atomically or when mu is held fromRHS Type // the declaration RHS this type is derived from tparams *TypeParamList // type parameters, or nil underlying Type // underlying type, or nil + finite bool // whether the type has finite size // methods declared for this type (not the method set of this type) // Signatures are type-checked lazily. @@ -151,10 +152,11 @@ // lazyLoaded // unpacked // └── hasMethods // └── hasUnder +// └── hasFinite // // That is, descent down the tree is mostly linear (initial through unpacked), except upon -// reaching the leaves (hasMethods and hasUnder). A type may occupy any combination of the -// leaf states at once (they are independent states). +// reaching the leaves (hasMethods, hasUnder, and hasFinite). A type may occupy any +// combination of the leaf states at once (they are independent states). // // To represent this independence, the set of active states is represented with a bit set. State // transitions are monotonic. Once a state bit is set, it remains set. @@ -162,12 +164,14 @@ // // The above constraints significantly narrow the possible bit sets for a named type. With bits // set left-to-right, they are: // -// 0000 | initial -// 1000 | lazyLoaded -// 1100 | unpacked, which implies lazyLoaded -// 1110 | hasMethods, which implies unpacked (which in turn implies lazyLoaded) -// 1101 | hasUnder, which implies unpacked ... -// 1111 | both hasMethods and hasUnder which implies unpacked ... +// 00000 | initial +// 10000 | lazyLoaded +// 11000 | unpacked, which implies lazyLoaded +// 11100 | hasMethods, which implies unpacked (which in turn implies lazyLoaded) +// 11010 | hasUnder, which implies unpacked ... +// 11001 | hasFinite, which implies unpacked ... +// 11110 | both hasMethods and hasUnder which implies unpacked ... +// ... | (other combinations of leaf states) // // To read the state of a named type, use [Named.stateHas]; to write, use [Named.setState]. type stateMask uint32 @@ -178,6 +182,7 @@ lazyLoaded stateMask = 1 << iota // methods are available, but constraints might be unexpanded (for generic types) unpacked // methods might be unexpanded (for instances) hasMethods // methods are all expanded (for instances) hasUnder // underlying type is available + hasFinite // size finiteness is available ) // NewNamed returns a new named type for the given type name, underlying type, and associated methods. @@ -305,6 +310,10 @@ assert(u) } // hasUnder => unpacked if m&hasUnder != 0 { + assert(u) + } + // hasFinite => unpacked + if m&hasFinite != 0 { assert(u) } } diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go index 694ab32462238ee6d50569a795a3dbdfa91b97a2..2f1859551709df987509625097b2740dcd99878e 100644 --- a/src/go/types/sizeof_test.go +++ b/src/go/types/sizeof_test.go @@ -30,7 +30,7 @@ {Union{}, 12, 24}, {Interface{}, 40, 80}, {Map{}, 16, 32}, {Chan{}, 12, 24}, - {Named{}, 64, 120}, + {Named{}, 68, 128}, {TypeParam{}, 28, 48}, {term{}, 12, 24}, diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index da2b38403fe920106a71ba2bb95dbb39e7213c1d..6b72bbf44db79dfba02e07d4556060b13979468c 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -361,8 +361,8 @@ var excluded = map[string]bool{ "builtin": true, "cmd/compile/internal/ssa/_gen": true, "runtime/_mkmalloc": true, - "simd/_gen/simdgen": true, - "simd/_gen/unify": true, + "simd/archsimd/_gen/simdgen": true, + "simd/archsimd/_gen/unify": true, } // printPackageMu synchronizes the printing of type-checked package files in diff --git a/src/internal/buildcfg/cfg.go b/src/internal/buildcfg/cfg.go index a75960b8e6c0345c0224cbba8ac5f2e3995940a0..89fd74eb823162fc35850925acb7774ac79d3bfc 100644 --- a/src/internal/buildcfg/cfg.go +++ b/src/internal/buildcfg/cfg.go @@ -80,32 +80,42 @@ } if isFIPSVersion(v) { return v } - Error = fmt.Errorf("invalid GOFIPS140: must be off, latest, inprocess, certified, or vX.Y.Z") + Error = fmt.Errorf("invalid GOFIPS140: must be off, latest, inprocess, certified, or v1.Y.Z") return DefaultGOFIPS140 } // isFIPSVersion reports whether v is a valid FIPS version, -// of the form vX.Y.Z or vX.Y.Z-hash. +// of the form v1.Y.Z or v1.Y.Z-hhhhhhhh or v1.Y.Z-rcN. func isFIPSVersion(v string) bool { - if !strings.HasPrefix(v, "v") { + v, ok := strings.CutPrefix(v, "v1.") + if !ok { return false } - v, ok := skipNum(v[len("v"):]) - if !ok || !strings.HasPrefix(v, ".") { + if v, ok = cutNum(v); !ok { return false } - v, ok = skipNum(v[len("."):]) - if !ok || !strings.HasPrefix(v, ".") { + if v, ok = strings.CutPrefix(v, "."); !ok { return false } - v, ok = skipNum(v[len("."):]) - hasHash := strings.HasPrefix(v, "-") && len(v) == len("-")+8 - return ok && (v == "" || hasHash) + if v, ok = cutNum(v); !ok { + return false + } + if v == "" { + return true + } + if v, ok = strings.CutPrefix(v, "-rc"); ok { + v, ok = cutNum(v) + return ok && v == "" + } + if v, ok = strings.CutPrefix(v, "-"); ok { + return len(v) == 8 + } + return false } -// skipNum skips the leading text matching [0-9]+ +// cutNum skips the leading text matching [0-9]+ // in s, returning the rest and whether such text was found. -func skipNum(s string) (rest string, ok bool) { +func cutNum(s string) (rest string, ok bool) { i := 0 for i < len(s) && '0' <= s[i] && s[i] <= '9' { i++ diff --git a/src/internal/runtime/gc/scan/filter_amd64.s b/src/internal/runtime/gc/scan/filter_amd64.s index 47330b62eeaa02bb1c0dd8fbed85935d6defdee8..2897d3c026f79325df16a59787e1f7709d158553 100644 --- a/src/internal/runtime/gc/scan/filter_amd64.s +++ b/src/internal/runtime/gc/scan/filter_amd64.s @@ -16,6 +16,7 @@ MOVL R9, R12 // R12 = n SUBL R10, R12 // R12 = n - scanned CMPL R12, $8 // Compare (n - scanned) with 8 JLT scalar_loop // If (n - scanned) < 8, jump to the scalar cleanup + VPXOR X15, X15, X15 // Zero the high bits of Z15 vector_loop: LEAQ (R8)(R10*8), R13 // R13 = buf[scanned:] address @@ -61,4 +62,5 @@ JL scalar_next_i // if scanned < n, continue end: MOVL R11, ret+16(FP) + VZEROUPPER RET diff --git a/src/internal/trace/reader_test.go b/src/internal/trace/reader_test.go index c03d0676a07c7a03c12452b24706d9793cdfc14b..264cc51569605f3ba315165d917e223187c21552 100644 --- a/src/internal/trace/reader_test.go +++ b/src/internal/trace/reader_test.go @@ -20,6 +20,7 @@ var ( logEvents = flag.Bool("log-events", false, "whether to log high-level events; significantly slows down tests") dumpTraces = flag.Bool("dump-traces", false, "dump traces even on success") + allocFree = flag.Bool("alloc-free", false, "run alloc/free trace experiment tests") ) func TestReaderGolden(t *testing.T) { diff --git a/src/internal/trace/summary.go b/src/internal/trace/summary.go index f31439feb8ff0b1efce565bc5470e2ccf144e232..68a924e6b9a89200d07fc1cbf63d79d23e281b98 100644 --- a/src/internal/trace/summary.go +++ b/src/internal/trace/summary.go @@ -321,16 +321,47 @@ // Handle transition out. g := s.gs[id] switch old { - case GoUndetermined, GoNotExist: + case GoUndetermined: g = &GoroutineSummary{ID: id, goroutineSummary: &goroutineSummary{}} + + // The goroutine is being named for the first time. // If we're coming out of GoUndetermined, then the creation time is the // time of the last sync. - if old == GoUndetermined { - g.CreationTime = s.syncTs - } else { - g.CreationTime = ev.Time() + g.CreationTime = s.syncTs + g.lastRangeTime = make(map[string]Time) + g.BlockTimeByReason = make(map[string]time.Duration) + g.RangeTime = make(map[string]time.Duration) + + // Accumulate all the time we spent in new as if it was old. + // + // Note that we still handle "new" again below because the time until + // the *next* event still needs to be accumulated (even though it's + // probably going to come immediately after this event). + stateTime := ev.Time().Sub(s.syncTs) + switch new { + case GoRunning: + g.ExecTime += stateTime + case GoWaiting: + g.BlockTimeByReason[st.Reason] += stateTime + case GoRunnable: + g.SchedWaitTime += stateTime + case GoSyscall: + // For a syscall, we're not going to be 'naming' this P from afar. + // It's "executing" somewhere. If we've got a P, then that means + // we've had that P since the start, so this is regular syscall time. + // Otherwise, this is syscall block time (no P). + if ev.Proc() == NoProc { + g.SyscallBlockTime += stateTime + } else { + g.SyscallTime += stateTime + } } - // The goroutine is being created, or it's being named for the first time. + s.gs[g.ID] = g + case GoNotExist: + g = &GoroutineSummary{ID: id, goroutineSummary: &goroutineSummary{}} + + // The goroutine is being created. + g.CreationTime = ev.Time() g.lastRangeTime = make(map[string]Time) g.BlockTimeByReason = make(map[string]time.Duration) g.RangeTime = make(map[string]time.Duration) diff --git a/src/internal/trace/summary_test.go b/src/internal/trace/summary_test.go index c5f1910262cb2acbc9c793c54c787d17b2bcc652..74bffefd70844a6089d89115d74cdee388aab0b1 100644 --- a/src/internal/trace/summary_test.go +++ b/src/internal/trace/summary_test.go @@ -17,6 +17,7 @@ var ( hasSchedWaitTime bool hasSyncBlockTime bool hasGCMarkAssistTime bool + hasUnknownTime bool ) assertContainsGoroutine(t, summaries, "runtime.gcBgMarkWorker") @@ -31,6 +32,7 @@ } if dt, ok := summary.RangeTime["GC mark assist"]; ok && dt > 0 { hasGCMarkAssistTime = true } + hasUnknownTime = hasUnknownTime || summary.UnknownTime() > 0 } if !hasSchedWaitTime { t.Error("missing sched wait time") @@ -40,6 +42,9 @@ t.Error("missing sync block time") } if !hasGCMarkAssistTime { t.Error("missing GC mark assist time") + } + if hasUnknownTime { + t.Error("has time that is unaccounted for") } } diff --git a/src/internal/trace/trace_test.go b/src/internal/trace/trace_test.go index 479411548f22b25c945811dc760b5ec61b63ed06..bfbd5315115305e58a9aa45a63968a5ce97ea5cf 100644 --- a/src/internal/trace/trace_test.go +++ b/src/internal/trace/trace_test.go @@ -697,6 +697,9 @@ } runTest(t, true, "") }) t.Run("AllocFree", func(t *testing.T) { + if !*allocFree { + t.Skip("skipping trace alloc/free tests by default; too flaky (see go.dev/issue/70838)") + } if testing.Short() { t.Skip("skipping trace alloc/free tests in short mode") } diff --git a/src/internal/types/testdata/fixedbugs/issue52915.go b/src/internal/types/testdata/fixedbugs/issue52915.go index 70dc6643759d54688088098161b57b98201c3cd6..e60c1767e98aefc6a8831913eac08d0dc60f9332 100644 --- a/src/internal/types/testdata/fixedbugs/issue52915.go +++ b/src/internal/types/testdata/fixedbugs/issue52915.go @@ -18,6 +18,4 @@ _ = unsafe.Sizeof(T[P]{}) _ = unsafe.Sizeof(struct{ T[P] }{}) } -// TODO(gri) This is a follow-on error due to T[int] being invalid. -// We should try to avoid it. -const _ = unsafe /* ERROR "not constant" */ .Sizeof(T[int]{}) +const _ = unsafe.Sizeof(T /* ERROR "invalid recursive type" */ [int]{}) diff --git a/src/internal/types/testdata/fixedbugs/issue75918.go b/src/internal/types/testdata/fixedbugs/issue75918.go new file mode 100644 index 0000000000000000000000000000000000000000..373db4a21bb16f2a0ee1f441985246deee1dfde1 --- /dev/null +++ b/src/internal/types/testdata/fixedbugs/issue75918.go @@ -0,0 +1,13 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type A /* ERROR "invalid recursive type" */ [unsafe.Sizeof(S{})]byte + +type S struct { + a A +} diff --git a/src/internal/types/testdata/fixedbugs/issue76478.go b/src/internal/types/testdata/fixedbugs/issue76478.go new file mode 100644 index 0000000000000000000000000000000000000000..f16b40e04ea1c4775c91a0c55971e8c9860e422c --- /dev/null +++ b/src/internal/types/testdata/fixedbugs/issue76478.go @@ -0,0 +1,25 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +type A /* ERROR "invalid recursive type" */ [unsafe.Sizeof(B{})]int +type B A + +type C /* ERROR "invalid recursive type" */ [unsafe.Sizeof(f())]int +func f() D { + return D{} +} +type D C + +type E /* ERROR "invalid recursive type" */ [unsafe.Sizeof(g[F]())]int +func g[P any]() P { + panic(0) +} +type F struct { + f E +} + diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index bf208a4d2914a0d67616f77aaa6b378d44bbd2d8..391d9bcd22ded1f21030b8532e108551ddd4248f 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -1093,11 +1093,6 @@ // takes no arguments and doesn't return any values so // there's no need to handle that. Clear R14 so that there's // a bad value in there, in case needm tries to use it. XORPS X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif XORQ R14, R14 MOVQ $runtime·needAndBindM(SB), AX CALL AX @@ -1795,11 +1790,6 @@ TEXT ·sigpanic0(SB),NOSPLIT,$0-0 get_tls(R14) MOVQ g(R14), R14 XORPS X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif JMP ·sigpanic(SB) // gcWriteBarrier informs the GC about heap pointer writes. diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index aaa2e4346c7a411b7d8ac38ca019722b6e4cd747..ffc4b005cb0b328b7023e82e7ba9ccd390804179 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -30,9 +30,6 @@ // Synchronous initialization. MOVD $runtime·reginit(SB), R12 MOVD R12, CTR BL (CTR) - MOVD $runtime·libpreinit(SB), R12 - MOVD R12, CTR - BL (CTR) #ifdef GOOS_aix // See runtime/cgo/gcc_aix_ppc64.c @@ -40,6 +37,10 @@ MOVBZ runtime·isarchive(SB), R3 // Check buildmode = c-archive CMP $0, R3 BEQ done #endif + + MOVD $runtime·libpreinit(SB), R12 + MOVD R12, CTR + BL (CTR) // Create a new thread to do the runtime initialization and return. // _cgo_sys_thread_create is a C function. diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index 55e7bdbdb55f7956e8ae5bd4cc24d8c3b9edda02..b36da2f12b7264baf48f5efca70d79236e8eda75 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -205,6 +205,18 @@ if raceenabled { raceacquire(unsafe.Pointer(&racecgosync)) } + if sys.DITSupported { + // C code may have enabled or disabled DIT on this thread, restore + // our state to the expected one. + ditEnabled := sys.DITEnabled() + gp := getg() + if !gp.ditWanted && ditEnabled { + sys.DisableDIT() + } else if gp.ditWanted && !ditEnabled { + sys.EnableDIT() + } + } + // From the garbage collector's perspective, time can move // backwards in the sequence above. If there's a callback into // Go code, GC will see this function at the call to @@ -427,11 +439,19 @@ // Add entry to defer stack in case of panic. restore := true defer unwindm(&restore) - var ditAlreadySet bool + var ditStateM, ditStateG bool if debug.dataindependenttiming == 1 && gp.m.isextra { // We only need to enable DIT for threads that were created by C, as it // should already by enabled on threads that were created by Go. - ditAlreadySet = sys.EnableDIT() + ditStateM = sys.EnableDIT() + } else if sys.DITSupported && debug.dataindependenttiming != 1 { + // C code may have enabled or disabled DIT on this thread. Set the flag + // on the M and G accordingly, saving their previous state to restore + // on return from the callback. + ditStateM, ditStateG = gp.m.ditEnabled, gp.ditWanted + ditEnabled := sys.DITEnabled() + gp.ditWanted = ditEnabled + gp.m.ditEnabled = ditEnabled } if raceenabled { @@ -449,9 +469,16 @@ if raceenabled { racereleasemerge(unsafe.Pointer(&racecgosync)) } - if debug.dataindependenttiming == 1 && !ditAlreadySet { + if debug.dataindependenttiming == 1 && !ditStateM { // Only unset DIT if it wasn't already enabled when cgocallback was called. sys.DisableDIT() + } else if sys.DITSupported && debug.dataindependenttiming != 1 { + // Restore DIT state on M and G. + gp.ditWanted = ditStateG + gp.m.ditEnabled = ditStateM + if !ditStateM { + sys.DisableDIT() + } } // Do not unwind m->g0->sched.sp. diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index 91f9740616f04ab178f42edf94e8e4e1cb144e5b..77afdc069005d4c52c01bc124fd64321ff1c6b98 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -1173,75 +1173,76 @@ if useCleanup { progName = "Cleanup" want = "runtime.runCleanups" } + t.Run(progName, func(t *testing.T) { + // The runtime.runFinalizers/runtime.runCleanups frame should appear in panics, even if + // runtime frames are normally hidden (GOTRACEBACK=all). + t.Run("Panic", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GOTRACEBACK=all", "GO_TEST_FINALIZER_DEADLOCK=panic") + want := want + "()" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } + }) - // The runtime.runFinalizers/runtime.runCleanups frame should appear in panics, even if - // runtime frames are normally hidden (GOTRACEBACK=all). - t.Run("Panic", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GOTRACEBACK=all", "GO_TEST_FINALIZER_DEADLOCK=panic") - want := want + "()" - if !strings.Contains(output, want) { - t.Errorf("output does not contain %q:\n%s", want, output) - } - }) + // The runtime.runFinalizers/runtime.Cleanups frame should appear in runtime.Stack, + // even though runtime frames are normally hidden. + t.Run("Stack", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=stack") + want := want + "()" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } + }) - // The runtime.runFinalizers/runtime.Cleanups frame should appear in runtime.Stack, - // even though runtime frames are normally hidden. - t.Run("Stack", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=stack") - want := want + "()" - if !strings.Contains(output, want) { - t.Errorf("output does not contain %q:\n%s", want, output) - } - }) + // The runtime.runFinalizers/runtime.Cleanups frame should appear in goroutine + // profiles. + t.Run("PprofProto", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_proto") - // The runtime.runFinalizers/runtime.Cleanups frame should appear in goroutine - // profiles. - t.Run("PprofProto", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_proto") - - p, err := profile.Parse(strings.NewReader(output)) - if err != nil { - // Logging the binary proto data is not very nice, but it might - // be a text error message instead. - t.Logf("Output: %s", output) - t.Fatalf("Error parsing proto output: %v", err) - } - for _, s := range p.Sample { - for _, loc := range s.Location { - for _, line := range loc.Line { - if line.Function.Name == want { - // Done! - return + p, err := profile.Parse(strings.NewReader(output)) + if err != nil { + // Logging the binary proto data is not very nice, but it might + // be a text error message instead. + t.Logf("Output: %s", output) + t.Fatalf("Error parsing proto output: %v", err) + } + for _, s := range p.Sample { + for _, loc := range s.Location { + for _, line := range loc.Line { + if line.Function.Name == want { + // Done! + return + } } } } - } - t.Errorf("Profile does not contain %q:\n%s", want, p) - }) + t.Errorf("Profile does not contain %q:\n%s", want, p) + }) - // The runtime.runFinalizers/runtime.runCleanups frame should appear in goroutine - // profiles (debug=1). - t.Run("PprofDebug1", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug1") - want := want + "+" - if !strings.Contains(output, want) { - t.Errorf("output does not contain %q:\n%s", want, output) - } - }) + // The runtime.runFinalizers/runtime.runCleanups frame should appear in goroutine + // profiles (debug=1). + t.Run("PprofDebug1", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug1") + want := want + "+" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } + }) - // The runtime.runFinalizers/runtime.runCleanups frame should appear in goroutine - // profiles (debug=2). - t.Run("PprofDebug2", func(t *testing.T) { - t.Parallel() - output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug2") - want := want + "()" - if !strings.Contains(output, want) { - t.Errorf("output does not contain %q:\n%s", want, output) - } + // The runtime.runFinalizers/runtime.runCleanups frame should appear in goroutine + // profiles (debug=2). + t.Run("PprofDebug2", func(t *testing.T) { + t.Parallel() + output := runTestProg(t, "testprog", progName+"Deadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug2") + want := want + "()" + if !strings.Contains(output, want) { + t.Errorf("output does not contain %q:\n%s", want, output) + } + }) }) } } diff --git a/src/runtime/dit.go b/src/runtime/dit.go new file mode 100644 index 0000000000000000000000000000000000000000..c234b0247b7449896e18b59450aecb0fe5565a25 --- /dev/null +++ b/src/runtime/dit.go @@ -0,0 +1,26 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime + +import ( + "internal/runtime/sys" + _ "unsafe" +) + +//go:linkname dit_setEnabled crypto/subtle.setDITEnabled +func dit_setEnabled() bool { + g := getg() + g.ditWanted = true + g.m.ditEnabled = true + return sys.EnableDIT() +} + +//go:linkname dit_setDisabled crypto/subtle.setDITDisabled +func dit_setDisabled() { + g := getg() + g.ditWanted = false + g.m.ditEnabled = false + sys.DisableDIT() +} diff --git a/src/runtime/metrics_cgo_test.go b/src/runtime/metrics_cgo_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6cc9d231959ce5f265089beb3f26feba9f2ffa49 --- /dev/null +++ b/src/runtime/metrics_cgo_test.go @@ -0,0 +1,32 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build cgo + +package runtime_test + +import ( + "internal/race" + "runtime" + "testing" +) + +func TestNotInGoMetricCallback(t *testing.T) { + switch runtime.GOOS { + case "windows", "plan9": + t.Skip("unsupported on Windows and Plan9") + case "freebsd": + if race.Enabled { + t.Skipf("race + cgo freebsd not supported. See https://go.dev/issue/73788.") + } + } + + // This test is run in a subprocess to prevent other tests from polluting the metrics + // and because we need to make some cgo callbacks. + output := runTestProg(t, "testprogcgo", "NotInGoMetricCallback") + want := "OK\n" + if output != want { + t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want) + } +} diff --git a/src/runtime/metrics_test.go b/src/runtime/metrics_test.go index efd2c2adb9bd851407e148c8fc2d0f5c794b6ef7..92cec75465ce4cc2c93ccfaf699c092e05982026 100644 --- a/src/runtime/metrics_test.go +++ b/src/runtime/metrics_test.go @@ -1584,18 +1584,3 @@ if output != want { t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want) } } - -func TestNotInGoMetricCallback(t *testing.T) { - switch runtime.GOOS { - case "windows", "plan9": - t.Skip("unsupported on Windows and Plan9") - } - - // This test is run in a subprocess to prevent other tests from polluting the metrics - // and because we need to make some cgo callbacks. - output := runTestProg(t, "testprogcgo", "NotInGoMetricCallback") - want := "OK\n" - if output != want { - t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want) - } -} diff --git a/src/runtime/os_wasm.go b/src/runtime/os_wasm.go index 15137cc13f3329c31e674fcc86cc386fb04768ca..e7a9a13d29e5e3539f6b76ce9df87f7edab4419a 100644 --- a/src/runtime/os_wasm.go +++ b/src/runtime/os_wasm.go @@ -142,6 +142,8 @@ } // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } func setProcessCPUProfiler(hz int32) {} diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index e46e4f9d273f8dd00c694623ec7ef0f32775f96e..a037e735e5a9c7a1b803b71a3bd8e7803d3c4c40 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -1590,14 +1590,30 @@ // the two profile types. goroutineProf := Lookup("goroutine") goroutineLeakProf := goroutineLeakProfile - // Check that a profile with debug information contains - includesLeak := func(t *testing.T, name, s string) { - if !strings.Contains(s, "runtime/pprof.goroutineLeakExample") { - t.Errorf("%s profile does not contain expected leaked goroutine (runtime/pprof.goroutineLeakExample): %s", name, s) + // We use this helper to count the total number of leaked goroutines in a text profile. + countLeaks := func(t *testing.T, profText string) int64 { + t.Helper() + + // Strip the profile header + parts := regexLeakCount.Split(profText, -1) + if len(parts) < 2 { + t.Fatalf("goroutineleak profile does not contain 'goroutineleak profile: total ': %s\nparts: %v", profText, parts) + } + + parts = whiteSpace.Split(parts[1], -1) + + count, err := strconv.ParseInt(parts[0], 10, 64) + if err != nil { + t.Fatalf("goroutineleak profile count is not a number: %s\nerror: %v", profText, err) } + return count } - checkFrame := func(i int, j int, locations []*profile.Location, expectedFunctionName string) { + // checkFrame looks for a specific frame in the stack. + // + // i is the location index in the profile and j is the location line index for the location. + // (Inlining may cause aliasing to the same location.) + checkFrame := func(t *testing.T, i int, j int, locations []*profile.Location, funcName string) { if len(locations) <= i { t.Errorf("leaked goroutine stack locations: out of range index %d, length %d", i, len(locations)) return @@ -1607,47 +1623,13 @@ if len(location.Line) <= j { t.Errorf("leaked goroutine stack location lines: out of range index %d, length %d", j, len(location.Line)) return } - if location.Line[j].Function.Name != expectedFunctionName { - t.Errorf("leaked goroutine stack expected %s as the location[%d].Line[%d] but found %s (%s:%d)", expectedFunctionName, i, j, location.Line[j].Function.Name, location.Line[j].Function.Filename, location.Line[j].Line) - } - } - - // We use this helper to count the total number of leaked goroutines in the profile. - // - // NOTE(vsaioc): This value should match for the number of leaks produced in this test, - // but other tests could also leak goroutines, in which case we would have a mismatch - // when bulk-running tests. - // - // The two mismatching outcomes are therefore: - // - More leaks than expected, which is a correctness issue with other tests. - // In this case, this test effectively checks other tests wrt - // goroutine leaks during bulk executions (e.g., running all.bash). - // - // - Fewer leaks than expected; this is an unfortunate symptom of scheduling - // non-determinism, which may occur once in a blue moon. We make - // a best-effort attempt to allow the expected leaks to occur, by yielding - // the main thread, but it is never a guarantee. - countLeaks := func(t *testing.T, number int, s string) { - // Strip the profile header - parts := regexLeakCount.Split(s, -1) - if len(parts) < 2 { - t.Fatalf("goroutineleak profile does not contain 'goroutineleak profile: total ': %s\nparts: %v", s, parts) - return - } - - parts = whiteSpace.Split(parts[1], -1) - - count, err := strconv.ParseInt(parts[0], 10, 64) - if err != nil { - t.Fatalf("goroutineleak profile count is not a number: %s\nerror: %v", s, err) - } - - // Check that the total number of leaked goroutines is exactly the expected number. - if count != int64(number) { - t.Errorf("goroutineleak profile does not contain exactly %d leaked goroutines: %d", number, count) + if location.Line[j].Function.Name != funcName { + t.Errorf("leaked goroutine stack expected %s as location[%d].Line[%d] but found %s (%s:%d)", funcName, i, j, location.Line[j].Function.Name, location.Line[j].Function.Filename, location.Line[j].Line) } } + // checkLeakStack hooks into profile parsing and performs validation, looking for specific stacks for + // the goroutines we'll leak in this test. checkLeakStack := func(t *testing.T) func(pc uintptr, locations []*profile.Location, _ map[string][]string) { return func(pc uintptr, locations []*profile.Location, _ map[string][]string) { if pc != leakCount { @@ -1665,16 +1647,18 @@ t.Errorf("%s", message) return } // We expect a receive operation. This is the typical stack. - checkFrame(0, 0, locations, "runtime.gopark") - checkFrame(1, 0, locations, "runtime.chanrecv") - checkFrame(2, 0, locations, "runtime.chanrecv1") - checkFrame(3, 0, locations, "runtime/pprof.goroutineLeakExample") + checkFrame(t, 0, 0, locations, "runtime.gopark") + checkFrame(t, 1, 0, locations, "runtime.chanrecv") + checkFrame(t, 2, 0, locations, "runtime.chanrecv1") + checkFrame(t, 3, 0, locations, "runtime/pprof.goroutineLeakExample") if len(locations) == 5 { - checkFrame(4, 0, locations, "runtime/pprof.TestGoroutineLeakProfileConcurrency.func5") + checkFrame(t, 4, 0, locations, "runtime/pprof.TestGoroutineLeakProfileConcurrency.func4") } } } + // Leak some goroutines that will feature in the goroutine leak profile + const totalLeaked = leakCount * 2 for i := 0; i < leakCount; i++ { go goroutineLeakExample() go func() { @@ -1683,13 +1667,36 @@ // This includes the frame runtime/pprof.TestGoroutineLeakProfileConcurrency.func1. goroutineLeakExample() panic("unreachable") }() - // Yield several times to allow the goroutines to leak. - runtime.Gosched() - runtime.Gosched() } - // Give all goroutines a chance to leak. - time.Sleep(time.Second) + // Wait for the goroutines to leak. We might wait here until the timeout, + // but this is better than intermittent flakes because we didn't wait long + // enough. If we actually time out, then there's likely a bug. + attempts := 0 + startTime := time.Now() + waitFor := 10 * time.Millisecond + for { + // + // If they never get detected, we'll get a timeout. + time.Sleep(waitFor) + + var w strings.Builder + goroutineLeakProf.WriteTo(&w, 1) + n := countLeaks(t, w.String()) + if n >= totalLeaked { + break + } + + // Log some messages so if a timeout is seen + attempts++ + t.Logf("waiting for leak: attempt %d (t=%s): found %d leaked goroutines", attempts, time.Since(startTime), n) + + // Wait a little longer to avoid spamming the log. + waitFor *= 2 + if waitFor > time.Second { + waitFor = time.Second + } + } t.Run("profile contains leak", func(t *testing.T) { var w strings.Builder @@ -1707,6 +1714,11 @@ }) // Concurrent calls to the goroutine leak profiler should not trigger data races // or corruption. + quickCheckForGoroutine := func(t *testing.T, profType, leak, profText string) { + if !strings.Contains(profText, leak) { + t.Errorf("%s profile does not contain expected leaked goroutine %s: %s", profType, leak, profText) + } + } t.Run("overlapping profile requests", func(t *testing.T) { ctx := context.Background() ctx, cancel := context.WithTimeout(ctx, time.Second) @@ -1721,8 +1733,10 @@ defer wg.Done() for ctx.Err() == nil { var w strings.Builder goroutineLeakProf.WriteTo(&w, 1) - countLeaks(t, 2*leakCount, w.String()) - includesLeak(t, "goroutineleak", w.String()) + if n := countLeaks(t, w.String()); n != totalLeaked { + t.Errorf("expected %d goroutines leaked, got %d: %s", totalLeaked, n, w.String()) + } + quickCheckForGoroutine(t, "goroutineleak", "runtime/pprof.goroutineLeakExample", w.String()) } }() }) @@ -1746,8 +1760,10 @@ defer wg.Done() for ctx.Err() == nil { var w strings.Builder goroutineLeakProf.WriteTo(&w, 1) - countLeaks(t, 2*leakCount, w.String()) - includesLeak(t, "goroutineleak", w.String()) + if n := countLeaks(t, w.String()); n != totalLeaked { + t.Errorf("expected %d goroutines leaked, got %d: %s", totalLeaked, n, w.String()) + } + quickCheckForGoroutine(t, "goroutineleak", "runtime/pprof.goroutineLeakExample", w.String()) } }() go func() { @@ -1758,7 +1774,7 @@ goroutineProf.WriteTo(&w, 1) // The regular goroutine profile should see the leaked // goroutines. We simply check that the goroutine leak // profile does not corrupt the goroutine profile state. - includesLeak(t, "goroutine", w.String()) + quickCheckForGoroutine(t, "goroutine", "runtime/pprof.goroutineLeakExample", w.String()) } }() }) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 52def488ffca42f8a9cf3547020a709c551050f3..5ea96f03f5d125c8359478708b21e534d05d0580 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -3342,6 +3342,23 @@ if !inheritTime { mp.p.ptr().schedtick++ } + if sys.DITSupported && debug.dataindependenttiming != 1 { + if gp.ditWanted && !mp.ditEnabled { + // The current M doesn't have DIT enabled, but the goroutine we're + // executing does need it, so turn it on. + sys.EnableDIT() + mp.ditEnabled = true + } else if !gp.ditWanted && mp.ditEnabled { + // The current M has DIT enabled, but the goroutine we're executing does + // not need it, so turn it off. + // NOTE: turning off DIT here means that the scheduler will have DIT enabled + // when it runs after this goroutine yields or is preempted. This may have + // a minor performance impact on the scheduler. + sys.DisableDIT() + mp.ditEnabled = false + } + } + // Check whether the profiler needs to be turned on or off. hz := sched.profilehz if mp.profilehz != hz { @@ -4368,7 +4385,6 @@ // something could claim this G before we've fully cleaned it // up. Hence, we set the scan bit to lock down further // transitions until we can dropg. casGToPreemptScan(gp, _Grunning, _Gscan|_Gpreempted) - dropg() // Be careful about ownership as we trace this next event. // @@ -4394,10 +4410,19 @@ trace := traceAcquire() if trace.ok() { trace.GoPark(traceBlockPreempted, 0) } + + // Drop the goroutine from the M. Only do this after the tracer has + // emitted an event, because it needs the association for GoPark to + // work correctly. + dropg() + + // Drop the scan bit and release the trace locker if necessary. casfrom_Gscanstatus(gp, _Gscan|_Gpreempted, _Gpreempted) if trace.ok() { traceRelease(trace) } + + // All done. schedule() } @@ -5261,10 +5286,6 @@ // Put it on the queue of g's waiting to run. // The compiler turns a go statement into a call to this. func newproc(fn *funcval) { gp := getg() - if goexperiment.RuntimeSecret && gp.secret > 0 { - panic("goroutine spawned while running in secret mode") - } - pc := sys.GetCallerPC() systemstack(func() { newg := newproc1(fn, gp, pc, false, waitReasonZero) @@ -5377,6 +5398,9 @@ } // fips140 bubble newg.fipsOnlyBypass = callergp.fipsOnlyBypass + + // dit bubble + newg.ditWanted = callergp.ditWanted // Set up race context. if raceenabled { diff --git a/src/runtime/profbuf_test.go b/src/runtime/profbuf_test.go index 2f068ac386ded861d83fae4a6e89ed0677f298b4..470c23dd419561af74cfcbb9e03db3c0924fdabd 100644 --- a/src/runtime/profbuf_test.go +++ b/src/runtime/profbuf_test.go @@ -232,11 +232,14 @@ // NB: this writes 6 words not 4. Fine for the test. // The reader shouldn't wake up for this b.Write(nil, 1, []uint64{1, 2}, []uintptr{3, 4}) - // The reader should still be blocked - // - // TODO(nick): this is racy. We could Gosched and still have the reader - // blocked in a buggy implementation because it just didn't get a chance - // to run + // The reader should still be blocked. The awaitBlockedGoroutine here + // checks that and also gives a buggy implementation a chance to + // actually wake up (it calls Gosched) before the next write. There is a + // small chance that a buggy implementation would have woken up but + // doesn't get scheduled by the time we do the next write. In that case + // the reader will see a more-than-half-full buffer and the test will + // pass. But if the implementation is broken, this test should fail + // regularly, even if not 100% of the time. awaitBlockedGoroutine(waitStatus, "TestProfBufWakeup.func1") b.Write(nil, 1, []uint64{5, 6}, []uintptr{7, 8}) b.Close() @@ -247,7 +250,8 @@ } // see also runtime/pprof tests func awaitBlockedGoroutine(state, fName string) { - re := fmt.Sprintf(`(?m)^goroutine \d+ \[%s\]:\n(?:.+\n\t.+\n)*runtime_test\.%s`, regexp.QuoteMeta(state), fName) + // NB: this matches [state] as well as [state, n minutes] + re := fmt.Sprintf(`(?m)^goroutine \d+ \[%s.*\]:\n(?:.+\n\t.+\n)*runtime_test\.%s`, regexp.QuoteMeta(state), fName) r := regexp.MustCompile(re) buf := make([]byte, 64<<10) diff --git a/src/runtime/race_amd64.s b/src/runtime/race_amd64.s index ade29bc5f1f8fdd56320204e2759e54c122a3b9d..e19118bd54e6eebf906f548605a975b16b9cafdd 100644 --- a/src/runtime/race_amd64.s +++ b/src/runtime/race_amd64.s @@ -456,11 +456,6 @@ MOVQ R12, SP // Back to Go world, set special registers. // The g register (R14) is preserved in C. XORPS X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif RET // C->Go callback thunk that allows to call runtime·racesymbolize from C code. diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index fde378ff25ce540dfecd06510a225c93e3adb919..be33932b24d16010920a8f9abb97e87c121ec49f 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -546,6 +546,7 @@ runnableTime int64 // the amount of time spent runnable, cleared when running, only used when tracking lockedm muintptr fipsIndicator uint8 fipsOnlyBypass bool + ditWanted bool // set if g wants to be executed with DIT enabled syncSafePoint bool // set if g is stopped at a synchronous safe point. runningCleanups atomic.Bool sig uint32 @@ -674,6 +675,7 @@ createstack [32]uintptr // stack that created this thread, it's used for StackRecord.Stack0, so it must align with it. lockedExt uint32 // tracking for external LockOSThread lockedInt uint32 // tracking for internal lockOSThread mWaitList mWaitList // list of runtime lock waiters + ditEnabled bool // set if DIT is currently enabled on this M mLockProfile mLockProfile // fields relating to runtime.lock contention profStack []uintptr // used for memory/block/mutex stack traces diff --git a/src/runtime/secret/export.go b/src/runtime/secret/export.go index 34f3c378f3ea8cfbeeea10e857491e2450e35d8a..f7d8cd4e2b138ff9b4212db218b491e4993c9894 100644 --- a/src/runtime/secret/export.go +++ b/src/runtime/secret/export.go @@ -2,6 +2,8 @@ // Copyright 2025 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build goexperiment.runtimesecret + package secret import ( diff --git a/src/runtime/secret/secret.go b/src/runtime/secret/secret.go index f669b98828d0d16adae4bbdfb84f4c4e4dffe332..9eae22605fba0b1ee967b6307ee59f6bff4dd6b2 100644 --- a/src/runtime/secret/secret.go +++ b/src/runtime/secret/secret.go @@ -28,7 +28,7 @@ // Limitations: // - Currently only supported on linux/amd64 and linux/arm64. On unsupported // platforms, Do will invoke f directly. // - Protection does not extend to any global variables written by f. -// - Any attempt to launch a goroutine by f will result in a panic. +// - Protection does not extend to any new goroutines made by f. // - If f calls runtime.Goexit, erasure can be delayed by defers // higher up on the call stack. // - Heap allocations will only be erased if the program drops all diff --git a/src/runtime/secret/stubs_noasm.go b/src/runtime/secret/stubs_noasm.go index f8091ff393fd16d211e8bd78d62c9fad4e598f00..8302642cdf85b7f64aaa296f9ebbc44bc1bf50a4 100644 --- a/src/runtime/secret/stubs_noasm.go +++ b/src/runtime/secret/stubs_noasm.go @@ -2,7 +2,7 @@ // Copyright 2025 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !arm64 && !amd64 +//go:build goexperiment.runtimesecret && !arm64 && !amd64 package secret diff --git a/src/runtime/sizeof_test.go b/src/runtime/sizeof_test.go index 9dde0da9636a48eab297bf3b5b9c20818e69eba4..219bcb92598c3a0a0e0ee80ca7b547552ee56fa9 100644 --- a/src/runtime/sizeof_test.go +++ b/src/runtime/sizeof_test.go @@ -21,7 +21,7 @@ val any // type as a value _32bit uintptr // size on 32bit platforms _64bit uintptr // size on 64bit platforms }{ - {runtime.G{}, 284 + xreg, 448 + xreg}, // g, but exported for testing + {runtime.G{}, 288 + xreg, 448 + xreg}, // g, but exported for testing {runtime.Sudog{}, 64, 104}, // sudog, but exported for testing } diff --git a/src/runtime/stack.go b/src/runtime/stack.go index d1c80276a5c46947bf81793ba3f6fce1c31ef262..6f89cc142c39f07c8a41d4b5ca0275cb1ead9330 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1357,7 +1357,13 @@ func (r *stackObjectRecord) gcdata() (uintptr, *byte) { ptr := uintptr(unsafe.Pointer(r)) var mod *moduledata for datap := &firstmoduledata; datap != nil; datap = datap.next { - if datap.gofunc <= ptr && ptr < datap.end { + // The normal case: stackObjectRecord is in funcdata. + if datap.gofunc <= ptr && ptr < datap.epclntab { + mod = datap + break + } + // A special case: methodValueCallFrameObjs. + if datap.noptrbss <= ptr && ptr < datap.enoptrbss { mod = datap break } diff --git a/src/runtime/stkframe.go b/src/runtime/stkframe.go index d6e7e0371c0bf64ce6fb4adfdb75b743beefca37..b63c0b4519337d515e73a03449e99f211166b5db 100644 --- a/src/runtime/stkframe.go +++ b/src/runtime/stkframe.go @@ -259,7 +259,7 @@ return } -var methodValueCallFrameObjs [1]stackObjectRecord // initialized in stackobjectinit +var methodValueCallFrameObjs [1]stackObjectRecord // initialized in stkobjinit func stkobjinit() { var abiRegArgsEface any = abi.RegArgs{} @@ -269,7 +269,7 @@ // stackObjectRecord.gcdata() will work correctly with it. ptr := uintptr(unsafe.Pointer(&methodValueCallFrameObjs[0])) var mod *moduledata for datap := &firstmoduledata; datap != nil; datap = datap.next { - if datap.gofunc <= ptr && ptr < datap.end { + if datap.noptrbss <= ptr && ptr < datap.enoptrbss { mod = datap break } diff --git a/src/runtime/stubs_386.go b/src/runtime/stubs_386.go index a1dd023974a0c6fc41159a759ead4b5ed8ab84c6..7db27cce87b69752150a6cc6072e588fe5a94765 100644 --- a/src/runtime/stubs_386.go +++ b/src/runtime/stubs_386.go @@ -21,4 +21,6 @@ func asmcgocall_no_g(fn, arg unsafe.Pointer) // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } diff --git a/src/runtime/stubs_arm.go b/src/runtime/stubs_arm.go index e19f1a87b2526a817e78661bd18e22a8e838df34..49bfd9ef0441a3a56532309115679842188f9cf2 100644 --- a/src/runtime/stubs_arm.go +++ b/src/runtime/stubs_arm.go @@ -26,4 +26,6 @@ func asmcgocall_no_g(fn, arg unsafe.Pointer) // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } diff --git a/src/runtime/stubs_loong64.go b/src/runtime/stubs_loong64.go index 4576089b0b38a658856f6ba9dfd2d166e7cd818b..88d5985db0ac1e537f078c3a01de35dfea1ad97b 100644 --- a/src/runtime/stubs_loong64.go +++ b/src/runtime/stubs_loong64.go @@ -19,4 +19,6 @@ func unspillArgs() // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } diff --git a/src/runtime/stubs_mips64x.go b/src/runtime/stubs_mips64x.go index f0cf0886203d139e9809d4f61899832728437d2f..fb5220b0de1359d377712e2bcb18230f61c88280 100644 --- a/src/runtime/stubs_mips64x.go +++ b/src/runtime/stubs_mips64x.go @@ -17,4 +17,6 @@ func asmcgocall_no_g(fn, arg unsafe.Pointer) // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } diff --git a/src/runtime/stubs_mipsx.go b/src/runtime/stubs_mipsx.go index 84ba147b85c58cca662c68de5a2b9e3f1996699a..175d4f974184c5110518b49c491c130828cd0a0d 100644 --- a/src/runtime/stubs_mipsx.go +++ b/src/runtime/stubs_mipsx.go @@ -12,4 +12,6 @@ func save_g() // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } diff --git a/src/runtime/stubs_ppc64x.go b/src/runtime/stubs_ppc64x.go index 36b01a72b15197975c13f939d2eecea7d13c46f6..dbc82c845352e98588f9cdb73d198b259adc4036 100644 --- a/src/runtime/stubs_ppc64x.go +++ b/src/runtime/stubs_ppc64x.go @@ -23,4 +23,6 @@ func unspillArgs() // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } diff --git a/src/runtime/stubs_riscv64.go b/src/runtime/stubs_riscv64.go index 61a6e33bd47a87875b9e29db8076bce678078a94..2306ba878b025303de7ef4753cb6c5f56f61b6eb 100644 --- a/src/runtime/stubs_riscv64.go +++ b/src/runtime/stubs_riscv64.go @@ -22,4 +22,6 @@ func unspillArgs() // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } diff --git a/src/runtime/stubs_s390x.go b/src/runtime/stubs_s390x.go index 6d704e820037a53e76172e3cf7d1af595d5a1c2b..144e3cdf919d87ef70323960006d9f91e8c877cf 100644 --- a/src/runtime/stubs_s390x.go +++ b/src/runtime/stubs_s390x.go @@ -17,4 +17,6 @@ func unspillArgs() // getfp returns the frame pointer register of its caller or 0 if not implemented. // TODO: Make this a compiler intrinsic +// +//go:nosplit func getfp() uintptr { return 0 } diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index c1643c1b39615889648eed6715427ff91ac7338a..058165553023411764fb2e2ed49539e23ebb1441 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -422,6 +422,7 @@ end, gcdata, gcbss uintptr types, etypes uintptr rodata uintptr gofunc uintptr // go.func.* + epclntab uintptr textsectmap []textsect typelinks []int32 // offsets from types diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index e033e8b7021e047acdb9f7b7866f323a9d26c7ab..99d67a9cfd2d6e3a8aa5dac36c50e95a68b64ec2 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -177,11 +177,6 @@ // Set up ABIInternal environment: g in R14, cleared X15. get_tls(R12) MOVQ g(R12), R14 PXOR X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif // Reserve space for spill slots. NOP SP // disable vet stack checking diff --git a/src/runtime/sys_dragonfly_amd64.s b/src/runtime/sys_dragonfly_amd64.s index e417d4b8a814f1c9d586ebabe4d8dcf6d8247b12..a223c2cf76bd1def59c8282c179a58b51c679963 100644 --- a/src/runtime/sys_dragonfly_amd64.s +++ b/src/runtime/sys_dragonfly_amd64.s @@ -228,11 +228,6 @@ // Set up ABIInternal environment: g in R14, cleared X15. get_tls(R12) MOVQ g(R12), R14 PXOR X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif // Reserve space for spill slots. NOP SP // disable vet stack checking diff --git a/src/runtime/sys_freebsd_amd64.s b/src/runtime/sys_freebsd_amd64.s index bab275cc7262dd23faca149243d1096d213e56fd..977ea093d247ac367b3239ba3f2af492359bae1a 100644 --- a/src/runtime/sys_freebsd_amd64.s +++ b/src/runtime/sys_freebsd_amd64.s @@ -265,11 +265,6 @@ // Set up ABIInternal environment: g in R14, cleared X15. get_tls(R12) MOVQ g(R12), R14 PXOR X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif // Reserve space for spill slots. NOP SP // disable vet stack checking @@ -295,11 +290,6 @@ // Set up ABIInternal environment: g in R14, cleared X15. get_tls(R12) MOVQ g(R12), R14 PXOR X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif // Reserve space for spill slots. NOP SP // disable vet stack checking diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s index 618553b1969fadde7a62f9a7f799aad746fe1b43..878f834748e943071df264cea0db3f62c7387108 100644 --- a/src/runtime/sys_linux_amd64.s +++ b/src/runtime/sys_linux_amd64.s @@ -352,11 +352,6 @@ // Set up ABIInternal environment: g in R14, cleared X15. get_tls(R12) MOVQ g(R12), R14 PXOR X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif // Reserve space for spill slots. NOP SP // disable vet stack checking @@ -382,11 +377,6 @@ // Set up ABIInternal environment: g in R14, cleared X15. get_tls(R12) MOVQ g(R12), R14 PXOR X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif // Reserve space for spill slots. NOP SP // disable vet stack checking diff --git a/src/runtime/sys_netbsd_amd64.s b/src/runtime/sys_netbsd_amd64.s index 946b1fbe22cc76f893cacaec5cc53cf446b9e9da..2f1ddcdc89755cd00f144d0b6dcd1d22a723ea8b 100644 --- a/src/runtime/sys_netbsd_amd64.s +++ b/src/runtime/sys_netbsd_amd64.s @@ -310,11 +310,6 @@ // Set up ABIInternal environment: g in R14, cleared X15. get_tls(R12) MOVQ g(R12), R14 PXOR X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif // Reserve space for spill slots. NOP SP // disable vet stack checking diff --git a/src/runtime/sys_openbsd_amd64.s b/src/runtime/sys_openbsd_amd64.s index 7766fa5194ec47e579204179c48ae0f3e7272fb2..ff0bc2416aa4bcc225c72573f32bee1c62e87a98 100644 --- a/src/runtime/sys_openbsd_amd64.s +++ b/src/runtime/sys_openbsd_amd64.s @@ -64,11 +64,6 @@ // Set up ABIInternal environment: g in R14, cleared X15. get_tls(R12) MOVQ g(R12), R14 PXOR X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif // Reserve space for spill slots. NOP SP // disable vet stack checking diff --git a/src/runtime/sys_windows_amd64.s b/src/runtime/sys_windows_amd64.s index 52a21ba89bbdc92154d769a9216daae85c09d05d..e438599910f4ee06de9714f4b41d6581ffcacd80 100644 --- a/src/runtime/sys_windows_amd64.s +++ b/src/runtime/sys_windows_amd64.s @@ -32,11 +32,6 @@ // Set up ABIInternal environment: cleared X15 and R14. // R14 is cleared in case there's a non-zero value in there // if called from a non-go thread. XORPS X15, X15 -#ifdef GOEXPERIMENT_simd - CMPB internal∕cpu·X86+const_offsetX86HasAVX(SB), $1 - JNE 2(PC) - VXORPS X15, X15, X15 -#endif XORQ R14, R14 get_tls(AX) diff --git a/src/runtime/testdata/testprogcgo/notingo.go b/src/runtime/testdata/testprogcgo/notingo.go index e5b1062e9e3eab339efb28e8c0e2f487a10a8d14..5af4c00e1fb9c26bbae4ab373b19dcee7b7e4a13 100644 --- a/src/runtime/testdata/testprogcgo/notingo.go +++ b/src/runtime/testdata/testprogcgo/notingo.go @@ -3,7 +3,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build !plan9 && !windows -// +build !plan9,!windows package main @@ -14,8 +13,8 @@ #include extern void Ready(); -static int spinning; -static int released; +static _Atomic int spinning; +static _Atomic int released; static void* enterGoThenSpinTwice(void* arg __attribute__ ((unused))) { Ready(); diff --git a/src/runtime/trace.go b/src/runtime/trace.go index 0fdc829f71e143603d97f776978991251855c7fb..a7e8937a05647a43adffbd12a53fbf3c49285451 100644 --- a/src/runtime/trace.go +++ b/src/runtime/trace.go @@ -440,11 +440,6 @@ } // Record the heap goal so we have it at the very beginning of the trace. tl.HeapGoal() - - // Make sure a ProcStatus is emitted for every P, while we're here. - for _, pp := range allp { - tl.writer().writeProcStatusForP(pp, pp == tl.mp.p.ptr()).end() - } traceRelease(tl) unlock(&sched.sysmonlock) @@ -553,14 +548,41 @@ // N.B. This may block for quite a while to get a frequency estimate. Do it // here to minimize the time that we prevent the world from stopping. frequency := traceClockUnitsPerSecond() - // Now that we've done some of the heavy stuff, prevent the world from stopping. + // Prevent the world from stopping. + // // This is necessary to ensure the consistency of the STW events. If we're feeling // adventurous we could lift this restriction and add a STWActive event, but the - // cost of maintaining this consistency is low. We're not going to hold this semaphore - // for very long and most STW periods are very short. - // Once we hold worldsema, prevent preemption as well so we're not interrupted partway - // through this. We want to get this done as soon as possible. + // cost of maintaining this consistency is low. + // + // This is also a good time to preempt all the Ps and ensure they had a status traced. semacquire(&worldsema) + + // Go over each P and emit a status event for it if necessary. + // + // TODO(mknyszek): forEachP is very heavyweight. We could do better by integrating + // the statusWasTraced check into it, to avoid preempting unnecessarily. + forEachP(waitReasonTraceProcStatus, func(pp *p) { + tl := traceAcquire() + if !pp.trace.statusWasTraced(tl.gen) { + tl.writer().writeProcStatusForP(pp, false).end() + } + traceRelease(tl) + }) + + // While we're still holding worldsema (preventing a STW and thus a + // change in the number of Ps), reset the status on dead Ps. + // They just appear as idle. + // + // TODO(mknyszek): Consider explicitly emitting ProcCreate and ProcDestroy + // events to indicate whether a P exists, rather than just making its + // existence implicit. + for _, pp := range allp[len(allp):cap(allp)] { + pp.trace.readyNextGen(gen) + } + + // Prevent preemption to make sure we're not interrupted. + // + // We want to get through the rest as soon as possible. mp := acquirem() // Advance the generation or stop the trace. @@ -742,20 +764,6 @@ trace.flushedGen.Store(gen) unlock(&trace.lock) }) - // Perform status reset on dead Ps because they just appear as idle. - // - // Preventing preemption is sufficient to access allp safely. allp is only - // mutated by GOMAXPROCS calls, which require a STW. - // - // TODO(mknyszek): Consider explicitly emitting ProcCreate and ProcDestroy - // events to indicate whether a P exists, rather than just making its - // existence implicit. - mp = acquirem() - for _, pp := range allp[len(allp):cap(allp)] { - pp.trace.readyNextGen(traceNextGen(gen)) - } - releasem(mp) - if stopTrace { // Acquire the shutdown sema to begin the shutdown process. semacquire(&traceShutdownSema) @@ -772,23 +780,6 @@ if trace.enabledWithAllocFree { trace.enabledWithAllocFree = false debug.malloc = trace.debugMalloc } - } else { - // Go over each P and emit a status event for it if necessary. - // - // We do this at the beginning of the new generation instead of the - // end like we do for goroutines because forEachP doesn't give us a - // hook to skip Ps that have already been traced. Since we have to - // preempt all Ps anyway, might as well stay consistent with StartTrace - // which does this during the STW. - semacquire(&worldsema) - forEachP(waitReasonTraceProcStatus, func(pp *p) { - tl := traceAcquire() - if !pp.trace.statusWasTraced(tl.gen) { - tl.writer().writeProcStatusForP(pp, false).end() - } - traceRelease(tl) - }) - semrelease(&worldsema) } // Block until the trace reader has finished processing the last generation. diff --git a/src/runtime/trace/subscribe_test.go b/src/runtime/trace/subscribe_test.go index 0e6c57cbc6d3520bbd70ec37288e2693b67585d9..2822094a026dd27fbdd5ff3999261c8f2a3b1f58 100644 --- a/src/runtime/trace/subscribe_test.go +++ b/src/runtime/trace/subscribe_test.go @@ -16,11 +16,18 @@ "testing" ) func TestSubscribers(t *testing.T) { - validate := func(t *testing.T, source string, tr io.Reader) { + validate := func(t *testing.T, source string, tr []byte) { + t.Log("validating", source) + defer func() { + if t.Failed() { + testtrace.Dump(t, "TestSubscribers."+source, tr, *dumpTraces) + } + }() + // Prepare to read the trace snapshot. - r, err := inttrace.NewReader(tr) + r, err := inttrace.NewReader(bytes.NewReader(tr)) if err != nil { - t.Fatalf("unexpected error creating trace reader for %s: %v", source, err) + t.Errorf("unexpected error creating trace reader for %s: %v", source, err) return } @@ -38,26 +45,30 @@ if err == io.EOF { break } if err != nil { - t.Fatalf("unexpected error reading trace for %s: %v", source, err) + t.Errorf("unexpected error reading trace for %s: %v", source, err) + break } if err := v.Event(ev); err != nil { - t.Fatalf("event validation failed: %s", err) + t.Errorf("event validation failed: %s", err) + break } if ev.Kind() == inttrace.EventSync { syncs = append(syncs, evs) } evs++ } - ends := []int{syncs[0], syncs[len(syncs)-1]} - if wantEnds := []int{0, evs - 1}; !slices.Equal(wantEnds, ends) { - t.Errorf("expected a sync event at each end of the trace, found sync events at %d instead of %d for %s", - ends, wantEnds, source) + if !t.Failed() { + ends := []int{syncs[0], syncs[len(syncs)-1]} + if wantEnds := []int{0, evs - 1}; !slices.Equal(wantEnds, ends) { + t.Errorf("expected a sync event at each end of the trace, found sync events at %d instead of %d for %s", + ends, wantEnds, source) + } } } - validateTraces := func(t *testing.T, tReader, frReader io.Reader) { - validate(t, "tracer", tReader) - validate(t, "flightRecorder", frReader) + validateTraces := func(t *testing.T, trace, frTrace *bytes.Buffer) { + validate(t, "tracer", trace.Bytes()) + validate(t, "flightRecorder", frTrace.Bytes()) } startFlightRecorder := func(t *testing.T) *trace.FlightRecorder { fr := trace.NewFlightRecorder(trace.FlightRecorderConfig{}) diff --git a/src/simd/_gen/go.mod b/src/simd/archsimd/_gen/go.mod rename from src/simd/_gen/go.mod rename to src/simd/archsimd/_gen/go.mod index fa360f560a4e0f9935aba23fa09ecaa9ee7d6d79..1ea88518aa4281eea64f3ff22c3cddeadbc88000 100644 --- a/src/simd/_gen/go.mod +++ b/src/simd/archsimd/_gen/go.mod @@ -1,4 +1,4 @@ -module simd/_gen +module simd/archsimd/_gen go 1.24 diff --git a/src/simd/_gen/go.sum b/src/simd/archsimd/_gen/go.sum rename from src/simd/_gen/go.sum rename to src/simd/archsimd/_gen/go.sum diff --git a/src/simd/_gen/main.go b/src/simd/archsimd/_gen/main.go rename from src/simd/_gen/main.go rename to src/simd/archsimd/_gen/main.go diff --git a/src/simd/_gen/simdgen/.gitignore b/src/simd/_gen/simdgen/.gitignore deleted file mode 100644 index de579f6b9bf8dc53cbafcc335283d35f0fb6b041..0000000000000000000000000000000000000000 --- a/src/simd/_gen/simdgen/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -testdata/* -.gemini/* -.gemini* diff --git a/src/simd/_gen/simdgen/categories.yaml b/src/simd/archsimd/_gen/simdgen/categories.yaml rename from src/simd/_gen/simdgen/categories.yaml rename to src/simd/archsimd/_gen/simdgen/categories.yaml diff --git a/src/simd/_gen/simdgen/etetest.sh b/src/simd/_gen/simdgen/etetest.sh deleted file mode 100755 index f6559fcfff91975b435cab1c17135c72f9c8d26a..0000000000000000000000000000000000000000 --- a/src/simd/_gen/simdgen/etetest.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash - -# This is an end-to-end test of Go SIMD. It updates all generated -# files in this repo and then runs several tests. - -XEDDATA="${XEDDATA:-xeddata}" -if [[ ! -d "$XEDDATA" ]]; then - echo >&2 "Must either set \$XEDDATA or symlink xeddata/ to the XED obj/dgen directory." - exit 1 -fi - -which go >/dev/null || exit 1 -goroot="$(go env GOROOT)" -if [[ ! ../../../.. -ef "$goroot" ]]; then - # We might be able to make this work but it's SO CONFUSING. - echo >&2 "go command in path has GOROOT $goroot" - exit 1 -fi - -if [[ $(go env GOEXPERIMENT) != simd ]]; then - echo >&2 "GOEXPERIMENT=$(go env GOEXPERIMENT), expected simd" - exit 1 -fi - -set -ex - -# Regenerate SIMD files -go run . -o godefs -goroot "$goroot" -xedPath "$XEDDATA" go.yaml types.yaml categories.yaml -# Regenerate SSA files from SIMD rules -go run -C "$goroot"/src/cmd/compile/internal/ssa/_gen . - -# Rebuild compiler -cd "$goroot"/src -go install cmd/compile - -# Tests -GOARCH=amd64 go run -C simd/testdata . -GOARCH=amd64 go test -v simd -go test go/doc go/build -go test cmd/api -v -check -run ^TestCheck$ -go test cmd/compile/internal/ssagen -simd=0 - -# Check tests without the GOEXPERIMENT -GOEXPERIMENT= go test go/doc go/build -GOEXPERIMENT= go test cmd/api -v -check -run ^TestCheck$ -GOEXPERIMENT= go test cmd/compile/internal/ssagen -simd=0 - -# TODO: Add some tests of SIMD itself diff --git a/src/simd/_gen/simdgen/gen_simdGenericOps.go b/src/simd/archsimd/_gen/simdgen/gen_simdGenericOps.go rename from src/simd/_gen/simdgen/gen_simdGenericOps.go rename to src/simd/archsimd/_gen/simdgen/gen_simdGenericOps.go diff --git a/src/simd/_gen/simdgen/gen_simdIntrinsics.go b/src/simd/archsimd/_gen/simdgen/gen_simdIntrinsics.go rename from src/simd/_gen/simdgen/gen_simdIntrinsics.go rename to src/simd/archsimd/_gen/simdgen/gen_simdIntrinsics.go index 04344dc8315b65f73318aa7c2833096a7ebc8e81..18722cdfa322281d5a5beadd1f1c73a3eda7a52e 100644 --- a/src/simd/_gen/simdgen/gen_simdIntrinsics.go +++ b/src/simd/archsimd/_gen/simdgen/gen_simdIntrinsics.go @@ -78,7 +78,7 @@ {{define "maskedLoadStore"}} addF(simdPackage, "LoadMasked{{.Name}}", simdMaskedLoad(ssa.OpLoadMasked{{.ElemBits}}), sys.AMD64) addF(simdPackage, "{{.Name}}.StoreMasked", simdMaskedStore(ssa.OpStoreMasked{{.ElemBits}}), sys.AMD64) {{end}} -{{define "mask"}} addF(simdPackage, "{{.Name}}.As{{.VectorCounterpart}}", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) +{{define "mask"}} addF(simdPackage, "{{.Name}}.To{{.VectorCounterpart}}", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "{{.VectorCounterpart}}.asMask", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64) addF(simdPackage, "{{.Name}}.And", opLen2(ssa.OpAnd{{.ReshapedVectorWithAndOr}}, types.TypeVec{{.Size}}), sys.AMD64) addF(simdPackage, "{{.Name}}.Or", opLen2(ssa.OpOr{{.ReshapedVectorWithAndOr}}, types.TypeVec{{.Size}}), sys.AMD64) diff --git a/src/simd/_gen/simdgen/gen_simdMachineOps.go b/src/simd/archsimd/_gen/simdgen/gen_simdMachineOps.go rename from src/simd/_gen/simdgen/gen_simdMachineOps.go rename to src/simd/archsimd/_gen/simdgen/gen_simdMachineOps.go diff --git a/src/simd/_gen/simdgen/gen_simdTypes.go b/src/simd/archsimd/_gen/simdgen/gen_simdTypes.go rename from src/simd/_gen/simdgen/gen_simdTypes.go rename to src/simd/archsimd/_gen/simdgen/gen_simdTypes.go index f98795e1b0b7c2066abd4ec92fcd86796eb24fa7..ca4f73c7389b1aaba944c061853ff68dd4669f42 100644 --- a/src/simd/_gen/simdgen/gen_simdTypes.go +++ b/src/simd/archsimd/_gen/simdgen/gen_simdTypes.go @@ -123,7 +123,7 @@ const simdPackageHeader = generatedHeader + ` //go:build goexperiment.simd -package simd +package archsimd ` const simdTypesTemplates = ` @@ -400,8 +400,8 @@ func (from {{.Tsrc.Name}}) As{{.Tdst.Name}}() (to {{.Tdst.Name}}) {{end}} {{define "mask"}} -// As{{.VectorCounterpart}} converts from {{.Name}} to {{.VectorCounterpart}} -func (from {{.Name}}) As{{.VectorCounterpart}}() (to {{.VectorCounterpart}}) +// To{{.VectorCounterpart}} converts from {{.Name}} to {{.VectorCounterpart}} +func (from {{.Name}}) To{{.VectorCounterpart}}() (to {{.VectorCounterpart}}) // asMask converts from {{.VectorCounterpart}} to {{.Name}} func (from {{.VectorCounterpart}}) asMask() (to {{.Name}}) diff --git a/src/simd/_gen/simdgen/gen_simdrules.go b/src/simd/archsimd/_gen/simdgen/gen_simdrules.go rename from src/simd/_gen/simdgen/gen_simdrules.go rename to src/simd/archsimd/_gen/simdgen/gen_simdrules.go diff --git a/src/simd/_gen/simdgen/gen_simdssa.go b/src/simd/archsimd/_gen/simdgen/gen_simdssa.go rename from src/simd/_gen/simdgen/gen_simdssa.go rename to src/simd/archsimd/_gen/simdgen/gen_simdssa.go diff --git a/src/simd/_gen/simdgen/gen_utility.go b/src/simd/archsimd/_gen/simdgen/gen_utility.go rename from src/simd/_gen/simdgen/gen_utility.go rename to src/simd/archsimd/_gen/simdgen/gen_utility.go diff --git a/src/simd/_gen/simdgen/go.yaml b/src/simd/archsimd/_gen/simdgen/go.yaml rename from src/simd/_gen/simdgen/go.yaml rename to src/simd/archsimd/_gen/simdgen/go.yaml diff --git a/src/simd/_gen/simdgen/godefs.go b/src/simd/archsimd/_gen/simdgen/godefs.go rename from src/simd/_gen/simdgen/godefs.go rename to src/simd/archsimd/_gen/simdgen/godefs.go index fb43116576b51794b7914081d5b0170e62f03df5..2c10377420e686516aac8649f0a8717cc7a96342 100644 --- a/src/simd/_gen/simdgen/godefs.go +++ b/src/simd/archsimd/_gen/simdgen/godefs.go @@ -13,7 +13,7 @@ "strconv" "strings" "unicode" - "simd/_gen/unify" + "simd/archsimd/_gen/unify" ) type Operation struct { diff --git a/src/simd/_gen/simdgen/main.go b/src/simd/archsimd/_gen/simdgen/main.go rename from src/simd/_gen/simdgen/main.go rename to src/simd/archsimd/_gen/simdgen/main.go index ca75cff55d794be0d029ce8779a9c5ab6c8c34be..3df95c81cbdac62667efafbaa52796922cae11de 100644 --- a/src/simd/_gen/simdgen/main.go +++ b/src/simd/archsimd/_gen/simdgen/main.go @@ -92,7 +92,7 @@ "runtime/pprof" "slices" "strings" - "simd/_gen/unify" + "simd/archsimd/_gen/unify" "gopkg.in/yaml.v3" ) @@ -117,7 +117,7 @@ flagCPUProfile = flag.String("cpuprofile", "", "write CPU profile to `file`") flagMemProfile = flag.String("memprofile", "", "write memory profile to `file`") ) -const simdPackage = "simd" +const simdPackage = "simd/archsimd" func main() { flag.Parse() diff --git a/src/simd/_gen/simdgen/ops/AddSub/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/AddSub/categories.yaml rename from src/simd/_gen/simdgen/ops/AddSub/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/AddSub/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/AddSub/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/AddSub/go.yaml rename from src/simd/_gen/simdgen/ops/AddSub/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/AddSub/go.yaml diff --git a/src/simd/_gen/simdgen/ops/BitwiseLogic/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/categories.yaml rename from src/simd/_gen/simdgen/ops/BitwiseLogic/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/BitwiseLogic/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/go.yaml rename from src/simd/_gen/simdgen/ops/BitwiseLogic/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/go.yaml diff --git a/src/simd/_gen/simdgen/ops/Compares/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/Compares/categories.yaml rename from src/simd/_gen/simdgen/ops/Compares/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Compares/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/Compares/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/Compares/go.yaml rename from src/simd/_gen/simdgen/ops/Compares/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Compares/go.yaml diff --git a/src/simd/_gen/simdgen/ops/Converts/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/Converts/categories.yaml rename from src/simd/_gen/simdgen/ops/Converts/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Converts/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/Converts/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/Converts/go.yaml rename from src/simd/_gen/simdgen/ops/Converts/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Converts/go.yaml diff --git a/src/simd/_gen/simdgen/ops/FPonlyArith/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/FPonlyArith/categories.yaml rename from src/simd/_gen/simdgen/ops/FPonlyArith/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/FPonlyArith/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/FPonlyArith/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/FPonlyArith/go.yaml rename from src/simd/_gen/simdgen/ops/FPonlyArith/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/FPonlyArith/go.yaml diff --git a/src/simd/_gen/simdgen/ops/GaloisField/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/GaloisField/categories.yaml rename from src/simd/_gen/simdgen/ops/GaloisField/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/GaloisField/categories.yaml index 258246253447e26196ecd74661c79112d05afc90..bf394ee1c7588736601e099c71e65729bb1bc4b8 100644 --- a/src/simd/_gen/simdgen/ops/GaloisField/categories.yaml +++ b/src/simd/archsimd/_gen/simdgen/ops/GaloisField/categories.yaml @@ -19,3 +19,5 @@ commutative: false documentation: !string |- // NAME computes element-wise GF(2^8) multiplication with // reduction polynomial x^8 + x^4 + x^3 + x + 1. +- go: carrylessMultiply + commutative: false diff --git a/src/simd/_gen/simdgen/ops/GaloisField/go.yaml b/src/simd/_gen/simdgen/ops/GaloisField/go.yaml deleted file mode 100644 index e86211cb46aebad192433d833bfe34dd010f7058..0000000000000000000000000000000000000000 --- a/src/simd/_gen/simdgen/ops/GaloisField/go.yaml +++ /dev/null @@ -1,32 +0,0 @@ -!sum -- go: GaloisFieldAffineTransform - asm: VGF2P8AFFINEQB - operandOrder: 2I # 2nd operand, then immediate - in: &AffineArgs - - &uint8 - go: $t - base: uint - - &uint8x8 - go: $t2 - base: uint - - &pureImmVar - class: immediate - immOffset: 0 - name: b - out: - - *uint8 - -- go: GaloisFieldAffineTransformInverse - asm: VGF2P8AFFINEINVQB - operandOrder: 2I # 2nd operand, then immediate - in: *AffineArgs - out: - - *uint8 - -- go: GaloisFieldMul - asm: VGF2P8MULB - in: - - *uint8 - - *uint8 - out: - - *uint8 diff --git a/src/simd/_gen/simdgen/ops/IntOnlyArith/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/IntOnlyArith/categories.yaml rename from src/simd/_gen/simdgen/ops/IntOnlyArith/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/IntOnlyArith/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/IntOnlyArith/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/IntOnlyArith/go.yaml rename from src/simd/_gen/simdgen/ops/IntOnlyArith/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/IntOnlyArith/go.yaml diff --git a/src/simd/_gen/simdgen/ops/MLOps/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/MLOps/categories.yaml rename from src/simd/_gen/simdgen/ops/MLOps/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/MLOps/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/MLOps/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/MLOps/go.yaml rename from src/simd/_gen/simdgen/ops/MLOps/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/MLOps/go.yaml diff --git a/src/simd/_gen/simdgen/ops/MinMax/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/MinMax/categories.yaml rename from src/simd/_gen/simdgen/ops/MinMax/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/MinMax/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/MinMax/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/MinMax/go.yaml rename from src/simd/_gen/simdgen/ops/MinMax/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/MinMax/go.yaml diff --git a/src/simd/_gen/simdgen/ops/Moves/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/Moves/categories.yaml rename from src/simd/_gen/simdgen/ops/Moves/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Moves/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/Moves/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/Moves/go.yaml rename from src/simd/_gen/simdgen/ops/Moves/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Moves/go.yaml diff --git a/src/simd/_gen/simdgen/ops/Mul/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/Mul/categories.yaml rename from src/simd/_gen/simdgen/ops/Mul/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Mul/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/Mul/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/Mul/go.yaml rename from src/simd/_gen/simdgen/ops/Mul/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Mul/go.yaml diff --git a/src/simd/_gen/simdgen/ops/Others/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/Others/categories.yaml rename from src/simd/_gen/simdgen/ops/Others/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Others/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/Others/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/Others/go.yaml rename from src/simd/_gen/simdgen/ops/Others/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/Others/go.yaml diff --git a/src/simd/_gen/simdgen/ops/ShiftRotate/categories.yaml b/src/simd/archsimd/_gen/simdgen/ops/ShiftRotate/categories.yaml rename from src/simd/_gen/simdgen/ops/ShiftRotate/categories.yaml rename to src/simd/archsimd/_gen/simdgen/ops/ShiftRotate/categories.yaml diff --git a/src/simd/_gen/simdgen/ops/ShiftRotate/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/ShiftRotate/go.yaml rename from src/simd/_gen/simdgen/ops/ShiftRotate/go.yaml rename to src/simd/archsimd/_gen/simdgen/ops/ShiftRotate/go.yaml diff --git a/src/simd/_gen/simdgen/pprint.go b/src/simd/archsimd/_gen/simdgen/pprint.go rename from src/simd/_gen/simdgen/pprint.go rename to src/simd/archsimd/_gen/simdgen/pprint.go diff --git a/src/simd/_gen/simdgen/sort_test.go b/src/simd/archsimd/_gen/simdgen/sort_test.go rename from src/simd/_gen/simdgen/sort_test.go rename to src/simd/archsimd/_gen/simdgen/sort_test.go diff --git a/src/simd/_gen/simdgen/types.yaml b/src/simd/archsimd/_gen/simdgen/types.yaml rename from src/simd/_gen/simdgen/types.yaml rename to src/simd/archsimd/_gen/simdgen/types.yaml index 9dccd1e76415a86c6317bbc1ffe3cde53eb0aaef..54b08c8fb163cb90965822895858feda2da86d4e 100644 --- a/src/simd/_gen/simdgen/types.yaml +++ b/src/simd/archsimd/_gen/simdgen/types.yaml @@ -83,6 +83,9 @@ - {class: vreg, go: Uint32x8, base: "uint", elemBits: 128, bits: 256, lanes: 8} - {class: vreg, go: Int64x4, base: "int", elemBits: 128, bits: 256, lanes: 4} - {class: vreg, go: Uint64x4, base: "uint", elemBits: 128, bits: 256, lanes: 4} +# Special for carryless multiply + - {class: vreg, go: Uint64x8, base: "uint", elemBits: 128, bits: 512, lanes: 8} + # Special shapes just to make VAES(ENC|DEC)(LAST)?512 work. # The elemBits field of these shapes are wrong, it would be overwritten by overwriteElemBits. - {class: vreg, go: Int8x32, base: "int", elemBits: 128, bits: 512, lanes: 32} diff --git a/src/simd/_gen/simdgen/xed.go b/src/simd/archsimd/_gen/simdgen/xed.go rename from src/simd/_gen/simdgen/xed.go rename to src/simd/archsimd/_gen/simdgen/xed.go index 9e9b67e77dfddda4e6543016019b472c1685bd38..4ba6738e7efd11a4bfe29115e01ea7ef8c99c47d 100644 --- a/src/simd/_gen/simdgen/xed.go +++ b/src/simd/archsimd/_gen/simdgen/xed.go @@ -15,7 +15,7 @@ "slices" "strconv" "strings" - "simd/_gen/unify" + "simd/archsimd/_gen/unify" "golang.org/x/arch/x86/xeddata" "gopkg.in/yaml.v3" @@ -808,13 +808,14 @@ // AVX512VL doesn't appear explicitly in the ISASet. I guess it's implied by // the vector length suffix. // AVX-512 extension features - {"AVX512EVEX", "AVX512_BITALG"}: "AVX512BITALG", - {"AVX512EVEX", "AVX512_GFNI"}: "AVX512GFNI", - {"AVX512EVEX", "AVX512_VBMI2"}: "AVX512VBMI2", - {"AVX512EVEX", "AVX512_VBMI"}: "AVX512VBMI", - {"AVX512EVEX", "AVX512_VNNI"}: "AVX512VNNI", - {"AVX512EVEX", "AVX512_VPOPCNTDQ"}: "AVX512VPOPCNTDQ", - {"AVX512EVEX", "AVX512_VAES"}: "AVX512VAES", + {"AVX512EVEX", "AVX512_BITALG"}: "AVX512BITALG", + {"AVX512EVEX", "AVX512_GFNI"}: "AVX512GFNI", + {"AVX512EVEX", "AVX512_VBMI2"}: "AVX512VBMI2", + {"AVX512EVEX", "AVX512_VBMI"}: "AVX512VBMI", + {"AVX512EVEX", "AVX512_VNNI"}: "AVX512VNNI", + {"AVX512EVEX", "AVX512_VPOPCNTDQ"}: "AVX512VPOPCNTDQ", + {"AVX512EVEX", "AVX512_VAES"}: "AVX512VAES", + {"AVX512EVEX", "AVX512_VPCLMULQDQ"}: "AVX512VPCLMULQDQ", // AVX 10.2 (not yet supported) {"AVX512EVEX", "AVX10_2_RC"}: "ignore", diff --git a/src/simd/_gen/tmplgen/main.go b/src/simd/archsimd/_gen/tmplgen/main.go rename from src/simd/_gen/tmplgen/main.go rename to src/simd/archsimd/_gen/tmplgen/main.go index 6ec8d45b9b7c086948dbbd1c503cdf0985c82315..473e4f14c087d14bac00d40133b3a9f9a93e6c9e 100644 --- a/src/simd/_gen/tmplgen/main.go +++ b/src/simd/archsimd/_gen/tmplgen/main.go @@ -247,7 +247,7 @@ `// Code generated by '%s'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd `, s) } @@ -267,7 +267,7 @@ `// Code generated by '%s'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd import "unsafe" @@ -287,7 +287,7 @@ package simd_test import ( - "simd" + "simd/archsimd" "testing" ) @@ -324,12 +324,12 @@ `) var unaryTemplate = templateOf("unary_helpers", ` // test{{.VType}}Unary tests the simd unary method f against the expected behavior generated by want -func test{{.VType}}Unary(t *testing.T, f func(_ simd.{{.VType}}) simd.{{.VType}}, want func(_ []{{.Etype}}) []{{.Etype}}) { +func test{{.VType}}Unary(t *testing.T, f func(_ archsimd.{{.VType}}) archsimd.{{.VType}}, want func(_ []{{.Etype}}) []{{.Etype}}) { n := {{.Count}} t.Helper() forSlice(t, {{.Etype}}s, n, func(x []{{.Etype}}) bool { t.Helper() - a := simd.Load{{.VType}}Slice(x) + a := archsimd.Load{{.VType}}Slice(x) g := make([]{{.Etype}}, n) f(a).StoreSlice(g) w := want(x) @@ -341,12 +341,12 @@ var unaryFlakyTemplate = shapedTemplateOf(unaryFlaky, "unary_flaky_helpers", ` // test{{.VType}}UnaryFlaky tests the simd unary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func test{{.VType}}UnaryFlaky(t *testing.T, f func(x simd.{{.VType}}) simd.{{.VType}}, want func(x []{{.Etype}}) []{{.Etype}}, flakiness float64) { +func test{{.VType}}UnaryFlaky(t *testing.T, f func(x archsimd.{{.VType}}) archsimd.{{.VType}}, want func(x []{{.Etype}}) []{{.Etype}}, flakiness float64) { n := {{.Count}} t.Helper() forSlice(t, {{.Etype}}s, n, func(x []{{.Etype}}) bool { t.Helper() - a := simd.Load{{.VType}}Slice(x) + a := archsimd.Load{{.VType}}Slice(x) g := make([]{{.Etype}}, n) f(a).StoreSlice(g) w := want(x) @@ -358,12 +358,12 @@ var convertTemplate = templateOf("convert_helpers", ` // test{{.VType}}ConvertTo{{.OEType}} tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func test{{.VType}}ConvertTo{{.OEType}}(t *testing.T, f func(x simd.{{.VType}}) simd.{{.OVType}}, want func(x []{{.Etype}}) []{{.OEtype}}) { +func test{{.VType}}ConvertTo{{.OEType}}(t *testing.T, f func(x archsimd.{{.VType}}) archsimd.{{.OVType}}, want func(x []{{.Etype}}) []{{.OEtype}}) { n := {{.Count}} t.Helper() forSlice(t, {{.Etype}}s, n, func(x []{{.Etype}}) bool { t.Helper() - a := simd.Load{{.VType}}Slice(x) + a := archsimd.Load{{.VType}}Slice(x) g := make([]{{.OEtype}}, n) f(a).StoreSlice(g) w := want(x) @@ -378,13 +378,13 @@ var unaryToUint16 = convertTemplate.target("uint", 16) var binaryTemplate = templateOf("binary_helpers", ` // test{{.VType}}Binary tests the simd binary method f against the expected behavior generated by want -func test{{.VType}}Binary(t *testing.T, f func(_, _ simd.{{.VType}}) simd.{{.VType}}, want func(_, _ []{{.Etype}}) []{{.Etype}}) { +func test{{.VType}}Binary(t *testing.T, f func(_, _ archsimd.{{.VType}}) archsimd.{{.VType}}, want func(_, _ []{{.Etype}}) []{{.Etype}}) { n := {{.Count}} t.Helper() forSlicePair(t, {{.Etype}}s, n, func(x, y []{{.Etype}}) bool { t.Helper() - a := simd.Load{{.VType}}Slice(x) - b := simd.Load{{.VType}}Slice(y) + a := archsimd.Load{{.VType}}Slice(x) + b := archsimd.Load{{.VType}}Slice(y) g := make([]{{.Etype}}, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -395,14 +395,14 @@ `) var ternaryTemplate = templateOf("ternary_helpers", ` // test{{.VType}}Ternary tests the simd ternary method f against the expected behavior generated by want -func test{{.VType}}Ternary(t *testing.T, f func(_, _, _ simd.{{.VType}}) simd.{{.VType}}, want func(_, _, _ []{{.Etype}}) []{{.Etype}}) { +func test{{.VType}}Ternary(t *testing.T, f func(_, _, _ archsimd.{{.VType}}) archsimd.{{.VType}}, want func(_, _, _ []{{.Etype}}) []{{.Etype}}) { n := {{.Count}} t.Helper() forSliceTriple(t, {{.Etype}}s, n, func(x, y, z []{{.Etype}}) bool { t.Helper() - a := simd.Load{{.VType}}Slice(x) - b := simd.Load{{.VType}}Slice(y) - c := simd.Load{{.VType}}Slice(z) + a := archsimd.Load{{.VType}}Slice(x) + b := archsimd.Load{{.VType}}Slice(y) + c := archsimd.Load{{.VType}}Slice(z) g := make([]{{.Etype}}, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -414,14 +414,14 @@ var ternaryFlakyTemplate = shapedTemplateOf(ternaryFlaky, "ternary_helpers", ` // test{{.VType}}TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func test{{.VType}}TernaryFlaky(t *testing.T, f func(x, y, z simd.{{.VType}}) simd.{{.VType}}, want func(x, y, z []{{.Etype}}) []{{.Etype}}, flakiness float64) { +func test{{.VType}}TernaryFlaky(t *testing.T, f func(x, y, z archsimd.{{.VType}}) archsimd.{{.VType}}, want func(x, y, z []{{.Etype}}) []{{.Etype}}, flakiness float64) { n := {{.Count}} t.Helper() forSliceTriple(t, {{.Etype}}s, n, func(x, y, z []{{.Etype}}) bool { t.Helper() - a := simd.Load{{.VType}}Slice(x) - b := simd.Load{{.VType}}Slice(y) - c := simd.Load{{.VType}}Slice(z) + a := archsimd.Load{{.VType}}Slice(x) + b := archsimd.Load{{.VType}}Slice(y) + c := archsimd.Load{{.VType}}Slice(z) g := make([]{{.Etype}}, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -432,15 +432,15 @@ `) var compareTemplate = templateOf("compare_helpers", ` // test{{.VType}}Compare tests the simd comparison method f against the expected behavior generated by want -func test{{.VType}}Compare(t *testing.T, f func(_, _ simd.{{.VType}}) simd.Mask{{.WxC}}, want func(_, _ []{{.Etype}}) []int64) { +func test{{.VType}}Compare(t *testing.T, f func(_, _ archsimd.{{.VType}}) archsimd.Mask{{.WxC}}, want func(_, _ []{{.Etype}}) []int64) { n := {{.Count}} t.Helper() forSlicePair(t, {{.Etype}}s, n, func(x, y []{{.Etype}}) bool { t.Helper() - a := simd.Load{{.VType}}Slice(x) - b := simd.Load{{.VType}}Slice(y) + a := archsimd.Load{{.VType}}Slice(x) + b := archsimd.Load{{.VType}}Slice(y) g := make([]int{{.EWidth}}, n) - f(a, b).AsInt{{.WxC}}().StoreSlice(g) + f(a, b).ToInt{{.WxC}}().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); }) }) @@ -452,17 +452,17 @@ var compareMaskedTemplate = templateOf("comparemasked_helpers", ` // test{{.VType}}CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func test{{.VType}}CompareMasked(t *testing.T, - f func(_, _ simd.{{.VType}}, m simd.Mask{{.WxC}}) simd.Mask{{.WxC}}, + f func(_, _ archsimd.{{.VType}}, m archsimd.Mask{{.WxC}}) archsimd.Mask{{.WxC}}, want func(_, _ []{{.Etype}}) []int64) { n := {{.Count}} t.Helper() forSlicePairMasked(t, {{.Etype}}s, n, func(x, y []{{.Etype}}, m []bool) bool { t.Helper() - a := simd.Load{{.VType}}Slice(x) - b := simd.Load{{.VType}}Slice(y) - k := simd.LoadInt{{.WxC}}Slice(toVect[int{{.EWidth}}](m)).ToMask() + a := archsimd.Load{{.VType}}Slice(x) + b := archsimd.Load{{.VType}}Slice(y) + k := archsimd.LoadInt{{.WxC}}Slice(toVect[int{{.EWidth}}](m)).ToMask() g := make([]int{{.EWidth}}, n) - f(a, b, k).AsInt{{.WxC}}().StoreSlice(g) + f(a, b, k).ToInt{{.WxC}}().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -591,24 +591,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature {{.CPUfeature}} func (x {{.VType}}) GreaterEqual(y {{.VType}}) Mask{{.WxC}} { - ones := x.Equal(x).AsInt{{.WxC}}() - return y.Greater(x).AsInt{{.WxC}}().Xor(ones).asMask() + ones := x.Equal(x).ToInt{{.WxC}}() + return y.Greater(x).ToInt{{.WxC}}().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature {{.CPUfeature}} func (x {{.VType}}) LessEqual(y {{.VType}}) Mask{{.WxC}} { - ones := x.Equal(x).AsInt{{.WxC}}() - return x.Greater(y).AsInt{{.WxC}}().Xor(ones).asMask() + ones := x.Equal(x).ToInt{{.WxC}}() + return x.Greater(y).ToInt{{.WxC}}().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature {{.CPUfeature}} func (x {{.VType}}) NotEqual(y {{.VType}}) Mask{{.WxC}} { - ones := x.Equal(x).AsInt{{.WxC}}() - return x.Equal(y).AsInt{{.WxC}}().Xor(ones).asMask() + ones := x.Equal(x).ToInt{{.WxC}}() + return x.Equal(y).ToInt{{.WxC}}().Xor(ones).asMask() } `) @@ -617,7 +617,7 @@ // Not returns the bitwise complement of x // // Emulated, CPU Feature {{.CPUfeature}} func (x {{.VType}}) Not() {{.VType}} { - return x.Xor(x.Equal(x).As{{.VType}}()) + return x.Xor(x.Equal(x).ToInt{{.WxC}}()) } `) @@ -626,7 +626,7 @@ // Not returns the bitwise complement of x // // Emulated, CPU Feature {{.CPUfeature}} func (x {{.VType}}) Not() {{.VType}} { - return x.Xor(x.Equal(x).AsInt{{.WxC}}().As{{.VType}}()) + return x.Xor(x.Equal(x).ToInt{{.WxC}}().As{{.VType}}()) } `) @@ -651,7 +651,7 @@ a, b := x.AsInt{{.WxC}}(), y.AsInt{{.WxC}}() {{- if eq .EWidth 8}} signs := BroadcastInt{{.WxC}}(-1 << ({{.EWidth}}-1)) {{- else}} - ones := x.Equal(x).AsInt{{.WxC}}() + ones := x.Equal(x).ToInt{{.WxC}}() signs := ones.ShiftAllLeft({{.EWidth}}-1) {{- end }} return a.Xor(signs).Greater(b.Xor(signs)) @@ -665,7 +665,7 @@ a, b := x.AsInt{{.WxC}}(), y.AsInt{{.WxC}}() {{- if eq .EWidth 8}} signs := BroadcastInt{{.WxC}}(-1 << ({{.EWidth}}-1)) {{- else}} - ones := x.Equal(x).AsInt{{.WxC}}() + ones := x.Equal(x).ToInt{{.WxC}}() signs := ones.ShiftAllLeft({{.EWidth}}-1) {{- end }} return b.Xor(signs).Greater(a.Xor(signs)) @@ -676,13 +676,13 @@ // // Emulated, CPU Feature {{.CPUfeatureAVX2if8}} func (x {{.VType}}) GreaterEqual(y {{.VType}}) Mask{{.WxC}} { a, b := x.AsInt{{.WxC}}(), y.AsInt{{.WxC}}() - ones := x.Equal(x).AsInt{{.WxC}}() + ones := x.Equal(x).ToInt{{.WxC}}() {{- if eq .EWidth 8}} signs := BroadcastInt{{.WxC}}(-1 << ({{.EWidth}}-1)) {{- else}} signs := ones.ShiftAllLeft({{.EWidth}}-1) {{- end }} - return b.Xor(signs).Greater(a.Xor(signs)).AsInt{{.WxC}}().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt{{.WxC}}().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -690,13 +690,13 @@ // // Emulated, CPU Feature {{.CPUfeatureAVX2if8}} func (x {{.VType}}) LessEqual(y {{.VType}}) Mask{{.WxC}} { a, b := x.AsInt{{.WxC}}(), y.AsInt{{.WxC}}() - ones := x.Equal(x).AsInt{{.WxC}}() + ones := x.Equal(x).ToInt{{.WxC}}() {{- if eq .EWidth 8}} signs := BroadcastInt{{.WxC}}(-1 << ({{.EWidth}}-1)) {{- else}} signs := ones.ShiftAllLeft({{.EWidth}}-1) {{- end }} - return a.Xor(signs).Greater(b.Xor(signs)).AsInt{{.WxC}}().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt{{.WxC}}().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -704,8 +704,8 @@ // // Emulated, CPU Feature {{.CPUfeature}} func (x {{.VType}}) NotEqual(y {{.VType}}) Mask{{.WxC}} { a, b := x.AsInt{{.WxC}}(), y.AsInt{{.WxC}}() - ones := x.Equal(x).AsInt{{.WxC}}() - return a.Equal(b).AsInt{{.WxC}}().Xor(ones).asMask() + ones := x.Equal(x).ToInt{{.WxC}}() + return a.Equal(b).ToInt{{.WxC}}().Xor(ones).asMask() } `) @@ -721,7 +721,7 @@ var avx2MaskedTemplate = shapedTemplateOf(avx2Shapes, "avx2 .Masked methods", ` // Masked returns x but with elements zeroed where mask is false. func (x {{.VType}}) Masked(mask Mask{{.WxC}}) {{.VType}} { - im := mask.AsInt{{.WxC}}() + im := mask.ToInt{{.WxC}}() {{- if eq .Base "Int" }} return im.And(x) {{- else}} @@ -732,9 +732,9 @@ // Merge returns x but with elements set to y where mask is false. func (x {{.VType}}) Merge(y {{.VType}}, mask Mask{{.WxC}}) {{.VType}} { {{- if eq .BxC .WxC -}} - im := mask.AsInt{{.BxC}}() + im := mask.ToInt{{.BxC}}() {{- else}} - im := mask.AsInt{{.WxC}}().AsInt{{.BxC}}() + im := mask.ToInt{{.WxC}}().AsInt{{.BxC}}() {{- end -}} {{- if and (eq .Base "Int") (eq .BxC .WxC) }} return y.blend(x, im) @@ -750,7 +750,7 @@ // TODO perhaps write these in ways that work better on AVX512 var avx512MaskedTemplate = shapedTemplateOf(avx512Shapes, "avx512 .Masked methods", ` // Masked returns x but with elements zeroed where mask is false. func (x {{.VType}}) Masked(mask Mask{{.WxC}}) {{.VType}} { - im := mask.AsInt{{.WxC}}() + im := mask.ToInt{{.WxC}}() {{- if eq .Base "Int" }} return im.And(x) {{- else}} @@ -796,7 +796,7 @@ return z.SetElem(0, x).Broadcast{{.Vwidth}}() } `) -var maskCvtTemplate = templateOf("Mask conversions", ` +var maskCvtTemplate = shapedTemplateOf(intShapes, "Mask conversions", ` // ToMask converts from {{.Base}}{{.WxC}} to Mask{{.WxC}}, mask element is set to true when the corresponding vector element is non-zero. func (from {{.Base}}{{.WxC}}) ToMask() (to Mask{{.WxC}}) { return from.NotEqual({{.Base}}{{.WxC}}{}) @@ -814,7 +814,7 @@ `) const SIMD = "../../" const TD = "../../internal/simd_test/" -const SSA = "../../../cmd/compile/internal/ssa/" +const SSA = "../../../../cmd/compile/internal/ssa/" func main() { sl := flag.String("sl", SIMD+"slice_gen_amd64.go", "file name for slice operations") diff --git a/src/simd/_gen/unify/closure.go b/src/simd/archsimd/_gen/unify/closure.go rename from src/simd/_gen/unify/closure.go rename to src/simd/archsimd/_gen/unify/closure.go diff --git a/src/simd/_gen/unify/domain.go b/src/simd/archsimd/_gen/unify/domain.go rename from src/simd/_gen/unify/domain.go rename to src/simd/archsimd/_gen/unify/domain.go diff --git a/src/simd/_gen/unify/dot.go b/src/simd/archsimd/_gen/unify/dot.go rename from src/simd/_gen/unify/dot.go rename to src/simd/archsimd/_gen/unify/dot.go diff --git a/src/simd/_gen/unify/env.go b/src/simd/archsimd/_gen/unify/env.go rename from src/simd/_gen/unify/env.go rename to src/simd/archsimd/_gen/unify/env.go diff --git a/src/simd/_gen/unify/html.go b/src/simd/archsimd/_gen/unify/html.go rename from src/simd/_gen/unify/html.go rename to src/simd/archsimd/_gen/unify/html.go diff --git a/src/simd/_gen/unify/pos.go b/src/simd/archsimd/_gen/unify/pos.go rename from src/simd/_gen/unify/pos.go rename to src/simd/archsimd/_gen/unify/pos.go diff --git a/src/simd/_gen/unify/testdata/stress.yaml b/src/simd/archsimd/_gen/unify/testdata/stress.yaml rename from src/simd/_gen/unify/testdata/stress.yaml rename to src/simd/archsimd/_gen/unify/testdata/stress.yaml diff --git a/src/simd/_gen/unify/testdata/unify.yaml b/src/simd/archsimd/_gen/unify/testdata/unify.yaml rename from src/simd/_gen/unify/testdata/unify.yaml rename to src/simd/archsimd/_gen/unify/testdata/unify.yaml diff --git a/src/simd/_gen/unify/testdata/vars.yaml b/src/simd/archsimd/_gen/unify/testdata/vars.yaml rename from src/simd/_gen/unify/testdata/vars.yaml rename to src/simd/archsimd/_gen/unify/testdata/vars.yaml diff --git a/src/simd/_gen/unify/trace.go b/src/simd/archsimd/_gen/unify/trace.go rename from src/simd/_gen/unify/trace.go rename to src/simd/archsimd/_gen/unify/trace.go diff --git a/src/simd/_gen/unify/unify.go b/src/simd/archsimd/_gen/unify/unify.go rename from src/simd/_gen/unify/unify.go rename to src/simd/archsimd/_gen/unify/unify.go diff --git a/src/simd/_gen/unify/unify_test.go b/src/simd/archsimd/_gen/unify/unify_test.go rename from src/simd/_gen/unify/unify_test.go rename to src/simd/archsimd/_gen/unify/unify_test.go diff --git a/src/simd/_gen/unify/value.go b/src/simd/archsimd/_gen/unify/value.go rename from src/simd/_gen/unify/value.go rename to src/simd/archsimd/_gen/unify/value.go diff --git a/src/simd/_gen/unify/value_test.go b/src/simd/archsimd/_gen/unify/value_test.go rename from src/simd/_gen/unify/value_test.go rename to src/simd/archsimd/_gen/unify/value_test.go diff --git a/src/simd/_gen/unify/yaml.go b/src/simd/archsimd/_gen/unify/yaml.go rename from src/simd/_gen/unify/yaml.go rename to src/simd/archsimd/_gen/unify/yaml.go diff --git a/src/simd/_gen/unify/yaml_test.go b/src/simd/archsimd/_gen/unify/yaml_test.go rename from src/simd/_gen/unify/yaml_test.go rename to src/simd/archsimd/_gen/unify/yaml_test.go diff --git a/src/simd/archsimd/_gen/simdgen/etetest.sh b/src/simd/archsimd/_gen/simdgen/etetest.sh new file mode 100755 index 0000000000000000000000000000000000000000..0bd2354fbb65fa45d226af7888d1a4bdff692269 --- /dev/null +++ b/src/simd/archsimd/_gen/simdgen/etetest.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# This is an end-to-end test of Go SIMD. It updates all generated +# files in this repo and then runs several tests. + +XEDDATA="${XEDDATA:-xeddata}" +if [[ ! -d "$XEDDATA" ]]; then + echo >&2 "Must either set \$XEDDATA or symlink xeddata/ to the XED obj/dgen directory." + exit 1 +fi + +# Ensure that goroot is the appropriate ancestor of this directory +which go >/dev/null || exit 1 +goroot="$(go env GOROOT)" +ancestor="../../../../.." +if [[ ! $ancestor -ef "$goroot" ]]; then + # We might be able to make this work but it's SO CONFUSING. + echo >&2 "go command in path has GOROOT $goroot instead of" `(cd $ancestor; pwd)` + exit 1 +fi + +set -ex + +# Regenerate SIMD files +go run . -o godefs -goroot "$goroot" -xedPath "$XEDDATA" go.yaml types.yaml categories.yaml +# Regenerate SSA files from SIMD rules +go run -C "$goroot"/src/cmd/compile/internal/ssa/_gen . + +# Rebuild compiler +cd "$goroot"/src +go install cmd/compile + +# Tests +# Set the GOEXPERIMENT explicitly. +GOEXPERIMENT=simd GOARCH=amd64 go run -C simd/archsimd/testdata . +GOEXPERIMENT=simd GOARCH=amd64 go test -v simd/archsimd +GOEXPERIMENT=simd GOARCH=amd64 go test go/doc go/build +GOEXPERIMENT=simd GOARCH=amd64 go test cmd/api -v -check -run ^TestCheck$ +GOEXPERIMENT=simd GOARCH=amd64 go test cmd/compile/internal/ssagen -simd=0 + +# Check tests without the GOEXPERIMENT +GOEXPERIMENT= go test go/doc go/build +GOEXPERIMENT= go test cmd/api -v -check -run ^TestCheck$ +GOEXPERIMENT= go test cmd/compile/internal/ssagen -simd=0 + +# TODO: Add some tests of SIMD itself diff --git a/src/simd/archsimd/_gen/simdgen/ops/GaloisField/go.yaml b/src/simd/archsimd/_gen/simdgen/ops/GaloisField/go.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6684bf76d05d28a963ce2f5ce0525c40c90bf0af --- /dev/null +++ b/src/simd/archsimd/_gen/simdgen/ops/GaloisField/go.yaml @@ -0,0 +1,92 @@ +!sum +- go: GaloisFieldAffineTransform + asm: VGF2P8AFFINEQB + operandOrder: 2I # 2nd operand, then immediate + in: &AffineArgs + - &uint8 + go: $t + base: uint + - &uint8x8 + go: $t2 + base: uint + - &pureImmVar + class: immediate + immOffset: 0 + name: b + out: + - *uint8 + +- go: GaloisFieldAffineTransformInverse + asm: VGF2P8AFFINEINVQB + operandOrder: 2I # 2nd operand, then immediate + in: *AffineArgs + out: + - *uint8 + +- go: GaloisFieldMul + asm: VGF2P8MULB + in: + - *uint8 + - *uint8 + out: + - *uint8 + +- go: carrylessMultiply + documentation: !string |- + // NAME computes one of four possible Galois polynomial + // products of selected high and low halves of x and y, + // depending on the value of xyHiLo, returning the 128-bit + // product in the concatenated two elements of the result. + // Bit 0 selects the low (0) or high (1) element of x and + // bit 4 selects the low (0x00) or high (0x10) element of y. + asm: V?PCLMULQDQ + in: + - go: Uint64x2 + - go: Uint64x2 + - class: immediate + immOffset: 0 + name: xyHiLo + out: + - go: Uint64x2 + overwriteElementBits: 64 + hideMaskMethods: true + +- go: carrylessMultiply + documentation: !string |- + // NAME computes one of two possible Galois polynomial + // products of selected high and low halves of each of the two + // 128-bit lanes of x and y, depending on the value of xyHiLo, + // and returns the four 128-bit products in the result's lanes. + // Bit 0 selects the low (0) or high (1) elements of x's lanes and + // bit 4 selects the low (0x00) or high (0x10) elements of y's lanes. + asm: V?PCLMULQDQ + in: + - go: Uint64x4 + - go: Uint64x4 + - class: immediate + immOffset: 0 + name: xyHiLo + out: + - go: Uint64x4 + overwriteElementBits: 64 + hideMaskMethods: true + +- go: carrylessMultiply + documentation: !string |- + // NAME computes one of four possible Galois polynomial + // products of selected high and low halves of each of the four + // 128-bit lanes of x and y, depending on the value of xyHiLo, + // and returns the four 128-bit products in the result's lanes. + // Bit 0 selects the low (0) or high (1) elements of x's lanes and + // bit 4 selects the low (0x00) or high (0x10) elements of y's lanes. + asm: V?PCLMULQDQ + in: + - go: Uint64x8 + - go: Uint64x8 + - class: immediate + immOffset: 0 + name: xyHiLo + out: + - go: Uint64x8 + overwriteElementBits: 64 + hideMaskMethods: true diff --git a/src/simd/archsimd/doc.go b/src/simd/archsimd/doc.go new file mode 100644 index 0000000000000000000000000000000000000000..c9c6e69ef638f1adc144cc3ebdc8294deb932277 --- /dev/null +++ b/src/simd/archsimd/doc.go @@ -0,0 +1,63 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.simd + +// Package archsimd provides access to architecture-specific SIMD operations. +// +// This is a low-level package that exposes hardware-specific functionality. +// It currently supports AMD64. +// +// This package is experimental, and not subject to the Go 1 compatibility promise. +// It only exists when building with the GOEXPERIMENT=simd environment variable set. +// +// # Vector types and operations +// +// Vector types are defined as structs, such as Int8x16 and Float64x8, corresponding +// to the hardware's vector registers. On AMD64, 128-, 256-, and 512-bit vectors are +// supported. +// +// Mask types are defined similarly, such as Mask8x16, and are represented as +// opaque types, handling the differences in the underlying representations. +// A mask can be converted to/from the corresponding integer vector type, or +// to/from a bitmask. +// +// Operations are mostly defined as methods on the vector types. Most of them +// are compiler intrinsics and correspond directly to hardware instructions. +// +// Common operations include: +// - Load/Store: Load a vector from memory or store a vector to memory. +// - Arithmetic: Add, Sub, Mul, etc. +// - Bitwise: And, Or, Xor, etc. +// - Comparison: Equal, Greater, etc., which produce a mask. +// - Conversion: Convert between different vector types. +// - Field selection and rearrangement: GetElem, Permute, etc. +// - Masking: Masked, Merge. +// +// The compiler recognizes certain patterns of operations and may optimize +// them to more performant instructions. For example, on AVX512, an Add operation +// followed by Masked may be optimized to a masked add instruction. +// For this reason, not all hardware instructions are available as APIs. +// +// # CPU feature checks +// +// The package provides global variables to check for CPU features available +// at runtime. For example, on AMD64, the [X86] variable provides methods to +// check for AVX2, AVX512, etc. +// It is recommended to check for CPU features before using the corresponding +// vector operations. +// +// # Notes +// +// - This package is not portable, as the available types and operations depend +// on the target architecture. It is not recommended to expose the SIMD types +// defined in this package in public APIs. +// - For performance reasons, it is recommended to use the vector types directly +// as values. It is not recommended to take the address of a vector type, +// allocate it in the heap, or put it in an aggregate type. +package archsimd + +// BUG(cherry): Using a vector type as a type parameter may not work. + +// BUG(cherry): Using reflect Call to call a vector function/method may not work. diff --git a/src/simd/archsimd/internal/simd_test/binary_test.go b/src/simd/archsimd/internal/simd_test/binary_test.go new file mode 100644 index 0000000000000000000000000000000000000000..fa2b9511ca8d44d64a024e4faa4d24a8e5888261 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/binary_test.go @@ -0,0 +1,361 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.simd && amd64 + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestAdd(t *testing.T) { + testFloat32x4Binary(t, archsimd.Float32x4.Add, addSlice[float32]) + testFloat32x8Binary(t, archsimd.Float32x8.Add, addSlice[float32]) + testFloat64x2Binary(t, archsimd.Float64x2.Add, addSlice[float64]) + testFloat64x4Binary(t, archsimd.Float64x4.Add, addSlice[float64]) + + testInt16x16Binary(t, archsimd.Int16x16.Add, addSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.Add, addSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.Add, addSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.Add, addSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.Add, addSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.Add, addSlice[int64]) + testInt8x16Binary(t, archsimd.Int8x16.Add, addSlice[int8]) + testInt8x32Binary(t, archsimd.Int8x32.Add, addSlice[int8]) + + testUint16x16Binary(t, archsimd.Uint16x16.Add, addSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.Add, addSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.Add, addSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.Add, addSlice[uint32]) + testUint64x2Binary(t, archsimd.Uint64x2.Add, addSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.Add, addSlice[uint64]) + testUint8x16Binary(t, archsimd.Uint8x16.Add, addSlice[uint8]) + testUint8x32Binary(t, archsimd.Uint8x32.Add, addSlice[uint8]) + + if archsimd.X86.AVX512() { + testFloat32x16Binary(t, archsimd.Float32x16.Add, addSlice[float32]) + testFloat64x8Binary(t, archsimd.Float64x8.Add, addSlice[float64]) + testInt8x64Binary(t, archsimd.Int8x64.Add, addSlice[int8]) + testInt16x32Binary(t, archsimd.Int16x32.Add, addSlice[int16]) + testInt32x16Binary(t, archsimd.Int32x16.Add, addSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.Add, addSlice[int64]) + testUint8x64Binary(t, archsimd.Uint8x64.Add, addSlice[uint8]) + testUint16x32Binary(t, archsimd.Uint16x32.Add, addSlice[uint16]) + testUint32x16Binary(t, archsimd.Uint32x16.Add, addSlice[uint32]) + testUint64x8Binary(t, archsimd.Uint64x8.Add, addSlice[uint64]) + } +} + +func TestSub(t *testing.T) { + testFloat32x4Binary(t, archsimd.Float32x4.Sub, subSlice[float32]) + testFloat32x8Binary(t, archsimd.Float32x8.Sub, subSlice[float32]) + testFloat64x2Binary(t, archsimd.Float64x2.Sub, subSlice[float64]) + testFloat64x4Binary(t, archsimd.Float64x4.Sub, subSlice[float64]) + + testInt16x16Binary(t, archsimd.Int16x16.Sub, subSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.Sub, subSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.Sub, subSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.Sub, subSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.Sub, subSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.Sub, subSlice[int64]) + testInt8x16Binary(t, archsimd.Int8x16.Sub, subSlice[int8]) + testInt8x32Binary(t, archsimd.Int8x32.Sub, subSlice[int8]) + + testUint16x16Binary(t, archsimd.Uint16x16.Sub, subSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.Sub, subSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.Sub, subSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.Sub, subSlice[uint32]) + testUint64x2Binary(t, archsimd.Uint64x2.Sub, subSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.Sub, subSlice[uint64]) + testUint8x16Binary(t, archsimd.Uint8x16.Sub, subSlice[uint8]) + testUint8x32Binary(t, archsimd.Uint8x32.Sub, subSlice[uint8]) + + if archsimd.X86.AVX512() { + testFloat32x16Binary(t, archsimd.Float32x16.Sub, subSlice[float32]) + testFloat64x8Binary(t, archsimd.Float64x8.Sub, subSlice[float64]) + testInt8x64Binary(t, archsimd.Int8x64.Sub, subSlice[int8]) + testInt16x32Binary(t, archsimd.Int16x32.Sub, subSlice[int16]) + testInt32x16Binary(t, archsimd.Int32x16.Sub, subSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.Sub, subSlice[int64]) + testUint8x64Binary(t, archsimd.Uint8x64.Sub, subSlice[uint8]) + testUint16x32Binary(t, archsimd.Uint16x32.Sub, subSlice[uint16]) + testUint32x16Binary(t, archsimd.Uint32x16.Sub, subSlice[uint32]) + testUint64x8Binary(t, archsimd.Uint64x8.Sub, subSlice[uint64]) + } +} + +func TestMax(t *testing.T) { + // testFloat32x4Binary(t, archsimd.Float32x4.Max, maxSlice[float32]) // nan is wrong + // testFloat32x8Binary(t, archsimd.Float32x8.Max, maxSlice[float32]) // nan is wrong + // testFloat64x2Binary(t, archsimd.Float64x2.Max, maxSlice[float64]) // nan is wrong + // testFloat64x4Binary(t, archsimd.Float64x4.Max, maxSlice[float64]) // nan is wrong + + testInt16x16Binary(t, archsimd.Int16x16.Max, maxSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.Max, maxSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.Max, maxSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.Max, maxSlice[int32]) + + if archsimd.X86.AVX512() { + testInt64x2Binary(t, archsimd.Int64x2.Max, maxSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.Max, maxSlice[int64]) + } + + testInt8x16Binary(t, archsimd.Int8x16.Max, maxSlice[int8]) + testInt8x32Binary(t, archsimd.Int8x32.Max, maxSlice[int8]) + + testUint16x16Binary(t, archsimd.Uint16x16.Max, maxSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.Max, maxSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.Max, maxSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.Max, maxSlice[uint32]) + + if archsimd.X86.AVX512() { + testUint64x2Binary(t, archsimd.Uint64x2.Max, maxSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.Max, maxSlice[uint64]) + } + + testUint8x16Binary(t, archsimd.Uint8x16.Max, maxSlice[uint8]) + testUint8x32Binary(t, archsimd.Uint8x32.Max, maxSlice[uint8]) + + if archsimd.X86.AVX512() { + // testFloat32x16Binary(t, archsimd.Float32x16.Max, maxSlice[float32]) // nan is wrong + // testFloat64x8Binary(t, archsimd.Float64x8.Max, maxSlice[float64]) // nan is wrong + testInt8x64Binary(t, archsimd.Int8x64.Max, maxSlice[int8]) + testInt16x32Binary(t, archsimd.Int16x32.Max, maxSlice[int16]) + testInt32x16Binary(t, archsimd.Int32x16.Max, maxSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.Max, maxSlice[int64]) + testUint8x64Binary(t, archsimd.Uint8x64.Max, maxSlice[uint8]) + testUint16x32Binary(t, archsimd.Uint16x32.Max, maxSlice[uint16]) + testUint32x16Binary(t, archsimd.Uint32x16.Max, maxSlice[uint32]) + testUint64x8Binary(t, archsimd.Uint64x8.Max, maxSlice[uint64]) + } +} + +func TestMin(t *testing.T) { + // testFloat32x4Binary(t, archsimd.Float32x4.Min, minSlice[float32]) // nan is wrong + // testFloat32x8Binary(t, archsimd.Float32x8.Min, minSlice[float32]) // nan is wrong + // testFloat64x2Binary(t, archsimd.Float64x2.Min, minSlice[float64]) // nan is wrong + // testFloat64x4Binary(t, archsimd.Float64x4.Min, minSlice[float64]) // nan is wrong + + testInt16x16Binary(t, archsimd.Int16x16.Min, minSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.Min, minSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.Min, minSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.Min, minSlice[int32]) + + if archsimd.X86.AVX512() { + testInt64x2Binary(t, archsimd.Int64x2.Min, minSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.Min, minSlice[int64]) + } + + testInt8x16Binary(t, archsimd.Int8x16.Min, minSlice[int8]) + testInt8x32Binary(t, archsimd.Int8x32.Min, minSlice[int8]) + + testUint16x16Binary(t, archsimd.Uint16x16.Min, minSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.Min, minSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.Min, minSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.Min, minSlice[uint32]) + + if archsimd.X86.AVX512() { + testUint64x2Binary(t, archsimd.Uint64x2.Min, minSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.Min, minSlice[uint64]) + } + + testUint8x16Binary(t, archsimd.Uint8x16.Min, minSlice[uint8]) + testUint8x32Binary(t, archsimd.Uint8x32.Min, minSlice[uint8]) + + if archsimd.X86.AVX512() { + // testFloat32x16Binary(t, archsimd.Float32x16.Min, minSlice[float32]) // nan is wrong + // testFloat64x8Binary(t, archsimd.Float64x8.Min, minSlice[float64]) // nan is wrong + testInt8x64Binary(t, archsimd.Int8x64.Min, minSlice[int8]) + testInt16x32Binary(t, archsimd.Int16x32.Min, minSlice[int16]) + testInt32x16Binary(t, archsimd.Int32x16.Min, minSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.Min, minSlice[int64]) + testUint8x64Binary(t, archsimd.Uint8x64.Min, minSlice[uint8]) + testUint16x32Binary(t, archsimd.Uint16x32.Min, minSlice[uint16]) + testUint32x16Binary(t, archsimd.Uint32x16.Min, minSlice[uint32]) + testUint64x8Binary(t, archsimd.Uint64x8.Min, minSlice[uint64]) + } +} + +func TestAnd(t *testing.T) { + testInt16x16Binary(t, archsimd.Int16x16.And, andSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.And, andSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.And, andSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.And, andSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.And, andSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.And, andSlice[int64]) + testInt8x16Binary(t, archsimd.Int8x16.And, andSlice[int8]) + testInt8x32Binary(t, archsimd.Int8x32.And, andSlice[int8]) + + testUint16x16Binary(t, archsimd.Uint16x16.And, andSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.And, andSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.And, andSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.And, andSlice[uint32]) + testUint64x2Binary(t, archsimd.Uint64x2.And, andSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.And, andSlice[uint64]) + testUint8x16Binary(t, archsimd.Uint8x16.And, andSlice[uint8]) + testUint8x32Binary(t, archsimd.Uint8x32.And, andSlice[uint8]) + + if archsimd.X86.AVX512() { + // testInt8x64Binary(t, archsimd.Int8x64.And, andISlice[int8]) // missing + // testInt16x32Binary(t, archsimd.Int16x32.And, andISlice[int16]) // missing + testInt32x16Binary(t, archsimd.Int32x16.And, andSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.And, andSlice[int64]) + // testUint8x64Binary(t, archsimd.Uint8x64.And, andISlice[uint8]) // missing + // testUint16x32Binary(t, archsimd.Uint16x32.And, andISlice[uint16]) // missing + testUint32x16Binary(t, archsimd.Uint32x16.And, andSlice[uint32]) + testUint64x8Binary(t, archsimd.Uint64x8.And, andSlice[uint64]) + } +} + +func TestAndNot(t *testing.T) { + testInt16x16Binary(t, archsimd.Int16x16.AndNot, andNotSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.AndNot, andNotSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.AndNot, andNotSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.AndNot, andNotSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.AndNot, andNotSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.AndNot, andNotSlice[int64]) + testInt8x16Binary(t, archsimd.Int8x16.AndNot, andNotSlice[int8]) + testInt8x32Binary(t, archsimd.Int8x32.AndNot, andNotSlice[int8]) + + testUint16x16Binary(t, archsimd.Uint16x16.AndNot, andNotSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.AndNot, andNotSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.AndNot, andNotSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.AndNot, andNotSlice[uint32]) + testUint64x2Binary(t, archsimd.Uint64x2.AndNot, andNotSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.AndNot, andNotSlice[uint64]) + testUint8x16Binary(t, archsimd.Uint8x16.AndNot, andNotSlice[uint8]) + testUint8x32Binary(t, archsimd.Uint8x32.AndNot, andNotSlice[uint8]) + + if archsimd.X86.AVX512() { + testInt8x64Binary(t, archsimd.Int8x64.AndNot, andNotSlice[int8]) + testInt16x32Binary(t, archsimd.Int16x32.AndNot, andNotSlice[int16]) + testInt32x16Binary(t, archsimd.Int32x16.AndNot, andNotSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.AndNot, andNotSlice[int64]) + testUint8x64Binary(t, archsimd.Uint8x64.AndNot, andNotSlice[uint8]) + testUint16x32Binary(t, archsimd.Uint16x32.AndNot, andNotSlice[uint16]) + testUint32x16Binary(t, archsimd.Uint32x16.AndNot, andNotSlice[uint32]) + testUint64x8Binary(t, archsimd.Uint64x8.AndNot, andNotSlice[uint64]) + } +} + +func TestXor(t *testing.T) { + testInt16x16Binary(t, archsimd.Int16x16.Xor, xorSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.Xor, xorSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.Xor, xorSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.Xor, xorSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.Xor, xorSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.Xor, xorSlice[int64]) + testInt8x16Binary(t, archsimd.Int8x16.Xor, xorSlice[int8]) + testInt8x32Binary(t, archsimd.Int8x32.Xor, xorSlice[int8]) + + testUint16x16Binary(t, archsimd.Uint16x16.Xor, xorSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.Xor, xorSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.Xor, xorSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.Xor, xorSlice[uint32]) + testUint64x2Binary(t, archsimd.Uint64x2.Xor, xorSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.Xor, xorSlice[uint64]) + testUint8x16Binary(t, archsimd.Uint8x16.Xor, xorSlice[uint8]) + testUint8x32Binary(t, archsimd.Uint8x32.Xor, xorSlice[uint8]) + + if archsimd.X86.AVX512() { + // testInt8x64Binary(t, archsimd.Int8x64.Xor, andISlice[int8]) // missing + // testInt16x32Binary(t, archsimd.Int16x32.Xor, andISlice[int16]) // missing + testInt32x16Binary(t, archsimd.Int32x16.Xor, xorSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.Xor, xorSlice[int64]) + // testUint8x64Binary(t, archsimd.Uint8x64.Xor, andISlice[uint8]) // missing + // testUint16x32Binary(t, archsimd.Uint16x32.Xor, andISlice[uint16]) // missing + testUint32x16Binary(t, archsimd.Uint32x16.Xor, xorSlice[uint32]) + testUint64x8Binary(t, archsimd.Uint64x8.Xor, xorSlice[uint64]) + } +} + +func TestOr(t *testing.T) { + testInt16x16Binary(t, archsimd.Int16x16.Or, orSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.Or, orSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.Or, orSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.Or, orSlice[int32]) + testInt64x2Binary(t, archsimd.Int64x2.Or, orSlice[int64]) + testInt64x4Binary(t, archsimd.Int64x4.Or, orSlice[int64]) + testInt8x16Binary(t, archsimd.Int8x16.Or, orSlice[int8]) + testInt8x32Binary(t, archsimd.Int8x32.Or, orSlice[int8]) + + testUint16x16Binary(t, archsimd.Uint16x16.Or, orSlice[uint16]) + testUint16x8Binary(t, archsimd.Uint16x8.Or, orSlice[uint16]) + testUint32x4Binary(t, archsimd.Uint32x4.Or, orSlice[uint32]) + testUint32x8Binary(t, archsimd.Uint32x8.Or, orSlice[uint32]) + testUint64x2Binary(t, archsimd.Uint64x2.Or, orSlice[uint64]) + testUint64x4Binary(t, archsimd.Uint64x4.Or, orSlice[uint64]) + testUint8x16Binary(t, archsimd.Uint8x16.Or, orSlice[uint8]) + testUint8x32Binary(t, archsimd.Uint8x32.Or, orSlice[uint8]) + + if archsimd.X86.AVX512() { + // testInt8x64Binary(t, archsimd.Int8x64.Or, andISlice[int8]) // missing + // testInt16x32Binary(t, archsimd.Int16x32.Or, andISlice[int16]) // missing + testInt32x16Binary(t, archsimd.Int32x16.Or, orSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.Or, orSlice[int64]) + // testUint8x64Binary(t, archsimd.Uint8x64.Or, andISlice[uint8]) // missing + // testUint16x32Binary(t, archsimd.Uint16x32.Or, andISlice[uint16]) // missing + testUint32x16Binary(t, archsimd.Uint32x16.Or, orSlice[uint32]) + testUint64x8Binary(t, archsimd.Uint64x8.Or, orSlice[uint64]) + } +} + +func TestMul(t *testing.T) { + testFloat32x4Binary(t, archsimd.Float32x4.Mul, mulSlice[float32]) + testFloat32x8Binary(t, archsimd.Float32x8.Mul, mulSlice[float32]) + testFloat64x2Binary(t, archsimd.Float64x2.Mul, mulSlice[float64]) + testFloat64x4Binary(t, archsimd.Float64x4.Mul, mulSlice[float64]) + + testInt16x16Binary(t, archsimd.Int16x16.Mul, mulSlice[int16]) + testInt16x8Binary(t, archsimd.Int16x8.Mul, mulSlice[int16]) + testInt32x4Binary(t, archsimd.Int32x4.Mul, mulSlice[int32]) + testInt32x8Binary(t, archsimd.Int32x8.Mul, mulSlice[int32]) + + // testInt8x16Binary(t, archsimd.Int8x16.Mul, mulSlice[int8]) // nope + // testInt8x32Binary(t, archsimd.Int8x32.Mul, mulSlice[int8]) + + // TODO we should be able to do these, there's no difference between signed/unsigned Mul + // testUint16x16Binary(t, archsimd.Uint16x16.Mul, mulSlice[uint16]) + // testUint16x8Binary(t, archsimd.Uint16x8.Mul, mulSlice[uint16]) + // testUint32x4Binary(t, archsimd.Uint32x4.Mul, mulSlice[uint32]) + // testUint32x8Binary(t, archsimd.Uint32x8.Mul, mulSlice[uint32]) + // testUint64x2Binary(t, archsimd.Uint64x2.Mul, mulSlice[uint64]) + // testUint64x4Binary(t, archsimd.Uint64x4.Mul, mulSlice[uint64]) + + // testUint8x16Binary(t, archsimd.Uint8x16.Mul, mulSlice[uint8]) // nope + // testUint8x32Binary(t, archsimd.Uint8x32.Mul, mulSlice[uint8]) + + if archsimd.X86.AVX512() { + testInt64x2Binary(t, archsimd.Int64x2.Mul, mulSlice[int64]) // avx512 only + testInt64x4Binary(t, archsimd.Int64x4.Mul, mulSlice[int64]) + + testFloat32x16Binary(t, archsimd.Float32x16.Mul, mulSlice[float32]) + testFloat64x8Binary(t, archsimd.Float64x8.Mul, mulSlice[float64]) + + // testInt8x64Binary(t, archsimd.Int8x64.Mul, mulSlice[int8]) // nope + testInt16x32Binary(t, archsimd.Int16x32.Mul, mulSlice[int16]) + testInt32x16Binary(t, archsimd.Int32x16.Mul, mulSlice[int32]) + testInt64x8Binary(t, archsimd.Int64x8.Mul, mulSlice[int64]) + // testUint8x64Binary(t, archsimd.Uint8x64.Mul, mulSlice[uint8]) // nope + + // TODO signed should do the job + // testUint16x32Binary(t, archsimd.Uint16x32.Mul, mulSlice[uint16]) + // testUint32x16Binary(t, archsimd.Uint32x16.Mul, mulSlice[uint32]) + // testUint64x8Binary(t, archsimd.Uint64x8.Mul, mulSlice[uint64]) + } +} + +func TestDiv(t *testing.T) { + testFloat32x4Binary(t, archsimd.Float32x4.Div, divSlice[float32]) + testFloat32x8Binary(t, archsimd.Float32x8.Div, divSlice[float32]) + testFloat64x2Binary(t, archsimd.Float64x2.Div, divSlice[float64]) + testFloat64x4Binary(t, archsimd.Float64x4.Div, divSlice[float64]) + + if archsimd.X86.AVX512() { + testFloat32x16Binary(t, archsimd.Float32x16.Div, divSlice[float32]) + testFloat64x8Binary(t, archsimd.Float64x8.Div, divSlice[float64]) + } +} diff --git a/src/simd/archsimd/internal/simd_test/compare_test.go b/src/simd/archsimd/internal/simd_test/compare_test.go new file mode 100644 index 0000000000000000000000000000000000000000..4485e9bdaa3fa4a4f6881eebc13fe8872b278f9b --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/compare_test.go @@ -0,0 +1,265 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.simd && amd64 + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +// AVX 2 lacks most comparisons, but they can be synthesized +// from > and = +var comparisonFixed bool = archsimd.X86.AVX512() + +func TestLess(t *testing.T) { + testFloat32x4Compare(t, archsimd.Float32x4.Less, lessSlice[float32]) + testFloat32x8Compare(t, archsimd.Float32x8.Less, lessSlice[float32]) + testFloat64x2Compare(t, archsimd.Float64x2.Less, lessSlice[float64]) + testFloat64x4Compare(t, archsimd.Float64x4.Less, lessSlice[float64]) + + testInt16x16Compare(t, archsimd.Int16x16.Less, lessSlice[int16]) + testInt16x8Compare(t, archsimd.Int16x8.Less, lessSlice[int16]) + testInt32x4Compare(t, archsimd.Int32x4.Less, lessSlice[int32]) + testInt32x8Compare(t, archsimd.Int32x8.Less, lessSlice[int32]) + testInt64x2Compare(t, archsimd.Int64x2.Less, lessSlice[int64]) + testInt64x4Compare(t, archsimd.Int64x4.Less, lessSlice[int64]) + testInt8x16Compare(t, archsimd.Int8x16.Less, lessSlice[int8]) + testInt8x32Compare(t, archsimd.Int8x32.Less, lessSlice[int8]) + + testInt16x16Compare(t, archsimd.Int16x16.Less, lessSlice[int16]) + testInt16x8Compare(t, archsimd.Int16x8.Less, lessSlice[int16]) + testInt32x4Compare(t, archsimd.Int32x4.Less, lessSlice[int32]) + testInt32x8Compare(t, archsimd.Int32x8.Less, lessSlice[int32]) + testInt64x2Compare(t, archsimd.Int64x2.Less, lessSlice[int64]) + testInt64x4Compare(t, archsimd.Int64x4.Less, lessSlice[int64]) + testInt8x16Compare(t, archsimd.Int8x16.Less, lessSlice[int8]) + testInt8x32Compare(t, archsimd.Int8x32.Less, lessSlice[int8]) + + testUint16x16Compare(t, archsimd.Uint16x16.Less, lessSlice[uint16]) + testUint16x8Compare(t, archsimd.Uint16x8.Less, lessSlice[uint16]) + testUint32x4Compare(t, archsimd.Uint32x4.Less, lessSlice[uint32]) + testUint32x8Compare(t, archsimd.Uint32x8.Less, lessSlice[uint32]) + testUint64x2Compare(t, archsimd.Uint64x2.Less, lessSlice[uint64]) + testUint64x4Compare(t, archsimd.Uint64x4.Less, lessSlice[uint64]) + testUint8x16Compare(t, archsimd.Uint8x16.Less, lessSlice[uint8]) + testUint8x32Compare(t, archsimd.Uint8x32.Less, lessSlice[uint8]) + + if archsimd.X86.AVX512() { + testUint16x16Compare(t, archsimd.Uint16x16.Less, lessSlice[uint16]) + testUint16x8Compare(t, archsimd.Uint16x8.Less, lessSlice[uint16]) + testUint32x4Compare(t, archsimd.Uint32x4.Less, lessSlice[uint32]) + testUint32x8Compare(t, archsimd.Uint32x8.Less, lessSlice[uint32]) + testUint64x2Compare(t, archsimd.Uint64x2.Less, lessSlice[uint64]) + testUint64x4Compare(t, archsimd.Uint64x4.Less, lessSlice[uint64]) + testUint8x16Compare(t, archsimd.Uint8x16.Less, lessSlice[uint8]) + testUint8x32Compare(t, archsimd.Uint8x32.Less, lessSlice[uint8]) + + testFloat32x16Compare(t, archsimd.Float32x16.Less, lessSlice[float32]) + testFloat64x8Compare(t, archsimd.Float64x8.Less, lessSlice[float64]) + testInt8x64Compare(t, archsimd.Int8x64.Less, lessSlice[int8]) + testInt16x32Compare(t, archsimd.Int16x32.Less, lessSlice[int16]) + testInt32x16Compare(t, archsimd.Int32x16.Less, lessSlice[int32]) + testInt64x8Compare(t, archsimd.Int64x8.Less, lessSlice[int64]) + testUint8x64Compare(t, archsimd.Uint8x64.Less, lessSlice[uint8]) + testUint16x32Compare(t, archsimd.Uint16x32.Less, lessSlice[uint16]) + testUint32x16Compare(t, archsimd.Uint32x16.Less, lessSlice[uint32]) + testUint64x8Compare(t, archsimd.Uint64x8.Less, lessSlice[uint64]) + } +} + +func TestLessEqual(t *testing.T) { + testFloat32x4Compare(t, archsimd.Float32x4.LessEqual, lessEqualSlice[float32]) + testFloat32x8Compare(t, archsimd.Float32x8.LessEqual, lessEqualSlice[float32]) + testFloat64x2Compare(t, archsimd.Float64x2.LessEqual, lessEqualSlice[float64]) + testFloat64x4Compare(t, archsimd.Float64x4.LessEqual, lessEqualSlice[float64]) + + testInt16x16Compare(t, archsimd.Int16x16.LessEqual, lessEqualSlice[int16]) + testInt16x8Compare(t, archsimd.Int16x8.LessEqual, lessEqualSlice[int16]) + testInt32x4Compare(t, archsimd.Int32x4.LessEqual, lessEqualSlice[int32]) + testInt32x8Compare(t, archsimd.Int32x8.LessEqual, lessEqualSlice[int32]) + testInt64x2Compare(t, archsimd.Int64x2.LessEqual, lessEqualSlice[int64]) + testInt64x4Compare(t, archsimd.Int64x4.LessEqual, lessEqualSlice[int64]) + testInt8x16Compare(t, archsimd.Int8x16.LessEqual, lessEqualSlice[int8]) + testInt8x32Compare(t, archsimd.Int8x32.LessEqual, lessEqualSlice[int8]) + + testUint16x16Compare(t, archsimd.Uint16x16.LessEqual, lessEqualSlice[uint16]) + testUint16x8Compare(t, archsimd.Uint16x8.LessEqual, lessEqualSlice[uint16]) + testUint32x4Compare(t, archsimd.Uint32x4.LessEqual, lessEqualSlice[uint32]) + testUint32x8Compare(t, archsimd.Uint32x8.LessEqual, lessEqualSlice[uint32]) + testUint64x2Compare(t, archsimd.Uint64x2.LessEqual, lessEqualSlice[uint64]) + testUint64x4Compare(t, archsimd.Uint64x4.LessEqual, lessEqualSlice[uint64]) + testUint8x16Compare(t, archsimd.Uint8x16.LessEqual, lessEqualSlice[uint8]) + testUint8x32Compare(t, archsimd.Uint8x32.LessEqual, lessEqualSlice[uint8]) + + if archsimd.X86.AVX512() { + testFloat32x16Compare(t, archsimd.Float32x16.LessEqual, lessEqualSlice[float32]) + testFloat64x8Compare(t, archsimd.Float64x8.LessEqual, lessEqualSlice[float64]) + testInt8x64Compare(t, archsimd.Int8x64.LessEqual, lessEqualSlice[int8]) + testInt16x32Compare(t, archsimd.Int16x32.LessEqual, lessEqualSlice[int16]) + testInt32x16Compare(t, archsimd.Int32x16.LessEqual, lessEqualSlice[int32]) + testInt64x8Compare(t, archsimd.Int64x8.LessEqual, lessEqualSlice[int64]) + testUint8x64Compare(t, archsimd.Uint8x64.LessEqual, lessEqualSlice[uint8]) + testUint16x32Compare(t, archsimd.Uint16x32.LessEqual, lessEqualSlice[uint16]) + testUint32x16Compare(t, archsimd.Uint32x16.LessEqual, lessEqualSlice[uint32]) + testUint64x8Compare(t, archsimd.Uint64x8.LessEqual, lessEqualSlice[uint64]) + } +} + +func TestGreater(t *testing.T) { + testFloat32x4Compare(t, archsimd.Float32x4.Greater, greaterSlice[float32]) + testFloat32x8Compare(t, archsimd.Float32x8.Greater, greaterSlice[float32]) + testFloat64x2Compare(t, archsimd.Float64x2.Greater, greaterSlice[float64]) + testFloat64x4Compare(t, archsimd.Float64x4.Greater, greaterSlice[float64]) + + testInt16x16Compare(t, archsimd.Int16x16.Greater, greaterSlice[int16]) + testInt16x8Compare(t, archsimd.Int16x8.Greater, greaterSlice[int16]) + testInt32x4Compare(t, archsimd.Int32x4.Greater, greaterSlice[int32]) + testInt32x8Compare(t, archsimd.Int32x8.Greater, greaterSlice[int32]) + + testInt64x2Compare(t, archsimd.Int64x2.Greater, greaterSlice[int64]) + testInt64x4Compare(t, archsimd.Int64x4.Greater, greaterSlice[int64]) + testInt8x16Compare(t, archsimd.Int8x16.Greater, greaterSlice[int8]) + testInt8x32Compare(t, archsimd.Int8x32.Greater, greaterSlice[int8]) + + testUint16x16Compare(t, archsimd.Uint16x16.Greater, greaterSlice[uint16]) + testUint16x8Compare(t, archsimd.Uint16x8.Greater, greaterSlice[uint16]) + testUint32x4Compare(t, archsimd.Uint32x4.Greater, greaterSlice[uint32]) + testUint32x8Compare(t, archsimd.Uint32x8.Greater, greaterSlice[uint32]) + + testUint64x2Compare(t, archsimd.Uint64x2.Greater, greaterSlice[uint64]) + testUint64x4Compare(t, archsimd.Uint64x4.Greater, greaterSlice[uint64]) + testUint8x16Compare(t, archsimd.Uint8x16.Greater, greaterSlice[uint8]) + testUint8x32Compare(t, archsimd.Uint8x32.Greater, greaterSlice[uint8]) + + if archsimd.X86.AVX512() { + + testFloat32x16Compare(t, archsimd.Float32x16.Greater, greaterSlice[float32]) + testFloat64x8Compare(t, archsimd.Float64x8.Greater, greaterSlice[float64]) + testInt8x64Compare(t, archsimd.Int8x64.Greater, greaterSlice[int8]) + testInt16x32Compare(t, archsimd.Int16x32.Greater, greaterSlice[int16]) + testInt32x16Compare(t, archsimd.Int32x16.Greater, greaterSlice[int32]) + testInt64x8Compare(t, archsimd.Int64x8.Greater, greaterSlice[int64]) + testUint8x64Compare(t, archsimd.Uint8x64.Greater, greaterSlice[uint8]) + testUint16x32Compare(t, archsimd.Uint16x32.Greater, greaterSlice[uint16]) + testUint32x16Compare(t, archsimd.Uint32x16.Greater, greaterSlice[uint32]) + testUint64x8Compare(t, archsimd.Uint64x8.Greater, greaterSlice[uint64]) + } +} + +func TestGreaterEqual(t *testing.T) { + testFloat32x4Compare(t, archsimd.Float32x4.GreaterEqual, greaterEqualSlice[float32]) + testFloat32x8Compare(t, archsimd.Float32x8.GreaterEqual, greaterEqualSlice[float32]) + testFloat64x2Compare(t, archsimd.Float64x2.GreaterEqual, greaterEqualSlice[float64]) + testFloat64x4Compare(t, archsimd.Float64x4.GreaterEqual, greaterEqualSlice[float64]) + + testInt16x16Compare(t, archsimd.Int16x16.GreaterEqual, greaterEqualSlice[int16]) + testInt16x8Compare(t, archsimd.Int16x8.GreaterEqual, greaterEqualSlice[int16]) + testInt32x4Compare(t, archsimd.Int32x4.GreaterEqual, greaterEqualSlice[int32]) + testInt32x8Compare(t, archsimd.Int32x8.GreaterEqual, greaterEqualSlice[int32]) + testInt64x2Compare(t, archsimd.Int64x2.GreaterEqual, greaterEqualSlice[int64]) + testInt64x4Compare(t, archsimd.Int64x4.GreaterEqual, greaterEqualSlice[int64]) + testInt8x16Compare(t, archsimd.Int8x16.GreaterEqual, greaterEqualSlice[int8]) + testInt8x32Compare(t, archsimd.Int8x32.GreaterEqual, greaterEqualSlice[int8]) + + testUint16x16Compare(t, archsimd.Uint16x16.GreaterEqual, greaterEqualSlice[uint16]) + testUint16x8Compare(t, archsimd.Uint16x8.GreaterEqual, greaterEqualSlice[uint16]) + testUint32x4Compare(t, archsimd.Uint32x4.GreaterEqual, greaterEqualSlice[uint32]) + testUint32x8Compare(t, archsimd.Uint32x8.GreaterEqual, greaterEqualSlice[uint32]) + testUint64x2Compare(t, archsimd.Uint64x2.GreaterEqual, greaterEqualSlice[uint64]) + testUint64x4Compare(t, archsimd.Uint64x4.GreaterEqual, greaterEqualSlice[uint64]) + testUint8x16Compare(t, archsimd.Uint8x16.GreaterEqual, greaterEqualSlice[uint8]) + testUint8x32Compare(t, archsimd.Uint8x32.GreaterEqual, greaterEqualSlice[uint8]) + + if archsimd.X86.AVX512() { + testFloat32x16Compare(t, archsimd.Float32x16.GreaterEqual, greaterEqualSlice[float32]) + testFloat64x8Compare(t, archsimd.Float64x8.GreaterEqual, greaterEqualSlice[float64]) + testInt8x64Compare(t, archsimd.Int8x64.GreaterEqual, greaterEqualSlice[int8]) + testInt16x32Compare(t, archsimd.Int16x32.GreaterEqual, greaterEqualSlice[int16]) + testInt32x16Compare(t, archsimd.Int32x16.GreaterEqual, greaterEqualSlice[int32]) + testInt64x8Compare(t, archsimd.Int64x8.GreaterEqual, greaterEqualSlice[int64]) + testUint8x64Compare(t, archsimd.Uint8x64.GreaterEqual, greaterEqualSlice[uint8]) + testUint16x32Compare(t, archsimd.Uint16x32.GreaterEqual, greaterEqualSlice[uint16]) + testUint32x16Compare(t, archsimd.Uint32x16.GreaterEqual, greaterEqualSlice[uint32]) + testUint64x8Compare(t, archsimd.Uint64x8.GreaterEqual, greaterEqualSlice[uint64]) + } +} + +func TestEqual(t *testing.T) { + testFloat32x4Compare(t, archsimd.Float32x4.Equal, equalSlice[float32]) + testFloat32x8Compare(t, archsimd.Float32x8.Equal, equalSlice[float32]) + testFloat64x2Compare(t, archsimd.Float64x2.Equal, equalSlice[float64]) + testFloat64x4Compare(t, archsimd.Float64x4.Equal, equalSlice[float64]) + + testInt16x16Compare(t, archsimd.Int16x16.Equal, equalSlice[int16]) + testInt16x8Compare(t, archsimd.Int16x8.Equal, equalSlice[int16]) + testInt32x4Compare(t, archsimd.Int32x4.Equal, equalSlice[int32]) + testInt32x8Compare(t, archsimd.Int32x8.Equal, equalSlice[int32]) + testInt64x2Compare(t, archsimd.Int64x2.Equal, equalSlice[int64]) + testInt64x4Compare(t, archsimd.Int64x4.Equal, equalSlice[int64]) + testInt8x16Compare(t, archsimd.Int8x16.Equal, equalSlice[int8]) + testInt8x32Compare(t, archsimd.Int8x32.Equal, equalSlice[int8]) + + testUint16x16Compare(t, archsimd.Uint16x16.Equal, equalSlice[uint16]) + testUint16x8Compare(t, archsimd.Uint16x8.Equal, equalSlice[uint16]) + testUint32x4Compare(t, archsimd.Uint32x4.Equal, equalSlice[uint32]) + testUint32x8Compare(t, archsimd.Uint32x8.Equal, equalSlice[uint32]) + testUint64x2Compare(t, archsimd.Uint64x2.Equal, equalSlice[uint64]) + testUint64x4Compare(t, archsimd.Uint64x4.Equal, equalSlice[uint64]) + testUint8x16Compare(t, archsimd.Uint8x16.Equal, equalSlice[uint8]) + testUint8x32Compare(t, archsimd.Uint8x32.Equal, equalSlice[uint8]) + + if archsimd.X86.AVX512() { + testFloat32x16Compare(t, archsimd.Float32x16.Equal, equalSlice[float32]) + testFloat64x8Compare(t, archsimd.Float64x8.Equal, equalSlice[float64]) + testInt8x64Compare(t, archsimd.Int8x64.Equal, equalSlice[int8]) + testInt16x32Compare(t, archsimd.Int16x32.Equal, equalSlice[int16]) + testInt32x16Compare(t, archsimd.Int32x16.Equal, equalSlice[int32]) + testInt64x8Compare(t, archsimd.Int64x8.Equal, equalSlice[int64]) + testUint8x64Compare(t, archsimd.Uint8x64.Equal, equalSlice[uint8]) + testUint16x32Compare(t, archsimd.Uint16x32.Equal, equalSlice[uint16]) + testUint32x16Compare(t, archsimd.Uint32x16.Equal, equalSlice[uint32]) + testUint64x8Compare(t, archsimd.Uint64x8.Equal, equalSlice[uint64]) + } +} + +func TestNotEqual(t *testing.T) { + testFloat32x4Compare(t, archsimd.Float32x4.NotEqual, notEqualSlice[float32]) + testFloat32x8Compare(t, archsimd.Float32x8.NotEqual, notEqualSlice[float32]) + testFloat64x2Compare(t, archsimd.Float64x2.NotEqual, notEqualSlice[float64]) + testFloat64x4Compare(t, archsimd.Float64x4.NotEqual, notEqualSlice[float64]) + + testInt16x16Compare(t, archsimd.Int16x16.NotEqual, notEqualSlice[int16]) + testInt16x8Compare(t, archsimd.Int16x8.NotEqual, notEqualSlice[int16]) + testInt32x4Compare(t, archsimd.Int32x4.NotEqual, notEqualSlice[int32]) + testInt32x8Compare(t, archsimd.Int32x8.NotEqual, notEqualSlice[int32]) + testInt64x2Compare(t, archsimd.Int64x2.NotEqual, notEqualSlice[int64]) + testInt64x4Compare(t, archsimd.Int64x4.NotEqual, notEqualSlice[int64]) + testInt8x16Compare(t, archsimd.Int8x16.NotEqual, notEqualSlice[int8]) + testInt8x32Compare(t, archsimd.Int8x32.NotEqual, notEqualSlice[int8]) + + testUint16x16Compare(t, archsimd.Uint16x16.NotEqual, notEqualSlice[uint16]) + testUint16x8Compare(t, archsimd.Uint16x8.NotEqual, notEqualSlice[uint16]) + testUint32x4Compare(t, archsimd.Uint32x4.NotEqual, notEqualSlice[uint32]) + testUint32x8Compare(t, archsimd.Uint32x8.NotEqual, notEqualSlice[uint32]) + testUint64x2Compare(t, archsimd.Uint64x2.NotEqual, notEqualSlice[uint64]) + testUint64x4Compare(t, archsimd.Uint64x4.NotEqual, notEqualSlice[uint64]) + testUint8x16Compare(t, archsimd.Uint8x16.NotEqual, notEqualSlice[uint8]) + testUint8x32Compare(t, archsimd.Uint8x32.NotEqual, notEqualSlice[uint8]) + + if archsimd.X86.AVX512() { + testFloat32x16Compare(t, archsimd.Float32x16.NotEqual, notEqualSlice[float32]) + testFloat64x8Compare(t, archsimd.Float64x8.NotEqual, notEqualSlice[float64]) + testInt8x64Compare(t, archsimd.Int8x64.NotEqual, notEqualSlice[int8]) + testInt16x32Compare(t, archsimd.Int16x32.NotEqual, notEqualSlice[int16]) + testInt32x16Compare(t, archsimd.Int32x16.NotEqual, notEqualSlice[int32]) + testInt64x8Compare(t, archsimd.Int64x8.NotEqual, notEqualSlice[int64]) + testUint8x64Compare(t, archsimd.Uint8x64.NotEqual, notEqualSlice[uint8]) + testUint16x32Compare(t, archsimd.Uint16x32.NotEqual, notEqualSlice[uint16]) + testUint32x16Compare(t, archsimd.Uint32x16.NotEqual, notEqualSlice[uint32]) + testUint64x8Compare(t, archsimd.Uint64x8.NotEqual, notEqualSlice[uint64]) + } +} diff --git a/src/simd/archsimd/internal/simd_test/ternary_test.go b/src/simd/archsimd/internal/simd_test/ternary_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0cc091be0934d1b07d54139a77434c1f744a15c3 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/ternary_test.go @@ -0,0 +1,23 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.simd && amd64 + +package simd_test + +import ( + "simd/archsimd" + "testing" +) + +func TestFMA(t *testing.T) { + if archsimd.X86.AVX512() { + testFloat32x4TernaryFlaky(t, archsimd.Float32x4.MulAdd, fmaSlice[float32], 0.001) + testFloat32x8TernaryFlaky(t, archsimd.Float32x8.MulAdd, fmaSlice[float32], 0.001) + testFloat32x16TernaryFlaky(t, archsimd.Float32x16.MulAdd, fmaSlice[float32], 0.001) + testFloat64x2Ternary(t, archsimd.Float64x2.MulAdd, fmaSlice[float64]) + testFloat64x4Ternary(t, archsimd.Float64x4.MulAdd, fmaSlice[float64]) + testFloat64x8Ternary(t, archsimd.Float64x8.MulAdd, fmaSlice[float64]) + } +} diff --git a/src/simd/archsimd/internal/simd_test/unary_test.go b/src/simd/archsimd/internal/simd_test/unary_test.go new file mode 100644 index 0000000000000000000000000000000000000000..6b53669d78edf7804c617310cfcbc7df2729da26 --- /dev/null +++ b/src/simd/archsimd/internal/simd_test/unary_test.go @@ -0,0 +1,137 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.simd && amd64 + +package simd_test + +import ( + "math" + "simd/archsimd" + "testing" +) + +func TestCeil(t *testing.T) { + testFloat32x4Unary(t, archsimd.Float32x4.Ceil, ceilSlice[float32]) + testFloat32x8Unary(t, archsimd.Float32x8.Ceil, ceilSlice[float32]) + testFloat64x2Unary(t, archsimd.Float64x2.Ceil, ceilSlice[float64]) + testFloat64x4Unary(t, archsimd.Float64x4.Ceil, ceilSlice[float64]) + if archsimd.X86.AVX512() { + // testFloat32x16Unary(t, archsimd.Float32x16.Ceil, ceilSlice[float32]) // missing + // testFloat64x8Unary(t, archsimd.Float64x8.Ceil, ceilSlice[float64]) // missing + } +} + +func TestFloor(t *testing.T) { + testFloat32x4Unary(t, archsimd.Float32x4.Floor, floorSlice[float32]) + testFloat32x8Unary(t, archsimd.Float32x8.Floor, floorSlice[float32]) + testFloat64x2Unary(t, archsimd.Float64x2.Floor, floorSlice[float64]) + testFloat64x4Unary(t, archsimd.Float64x4.Floor, floorSlice[float64]) + if archsimd.X86.AVX512() { + // testFloat32x16Unary(t, archsimd.Float32x16.Floor, floorSlice[float32]) // missing + // testFloat64x8Unary(t, archsimd.Float64x8.Floor, floorSlice[float64]) // missing + } +} + +func TestTrunc(t *testing.T) { + testFloat32x4Unary(t, archsimd.Float32x4.Trunc, truncSlice[float32]) + testFloat32x8Unary(t, archsimd.Float32x8.Trunc, truncSlice[float32]) + testFloat64x2Unary(t, archsimd.Float64x2.Trunc, truncSlice[float64]) + testFloat64x4Unary(t, archsimd.Float64x4.Trunc, truncSlice[float64]) + if archsimd.X86.AVX512() { + // testFloat32x16Unary(t, archsimd.Float32x16.Trunc, truncSlice[float32]) // missing + // testFloat64x8Unary(t, archsimd.Float64x8.Trunc, truncSlice[float64]) // missing + } +} + +func TestRound(t *testing.T) { + testFloat32x4Unary(t, archsimd.Float32x4.RoundToEven, roundSlice[float32]) + testFloat32x8Unary(t, archsimd.Float32x8.RoundToEven, roundSlice[float32]) + testFloat64x2Unary(t, archsimd.Float64x2.RoundToEven, roundSlice[float64]) + testFloat64x4Unary(t, archsimd.Float64x4.RoundToEven, roundSlice[float64]) + if archsimd.X86.AVX512() { + // testFloat32x16Unary(t, archsimd.Float32x16.Round, roundSlice[float32]) // missing + // testFloat64x8Unary(t, archsimd.Float64x8.Round, roundSlice[float64]) // missing + } +} + +func TestSqrt(t *testing.T) { + testFloat32x4Unary(t, archsimd.Float32x4.Sqrt, sqrtSlice[float32]) + testFloat32x8Unary(t, archsimd.Float32x8.Sqrt, sqrtSlice[float32]) + testFloat64x2Unary(t, archsimd.Float64x2.Sqrt, sqrtSlice[float64]) + testFloat64x4Unary(t, archsimd.Float64x4.Sqrt, sqrtSlice[float64]) + if archsimd.X86.AVX512() { + testFloat32x16Unary(t, archsimd.Float32x16.Sqrt, sqrtSlice[float32]) + testFloat64x8Unary(t, archsimd.Float64x8.Sqrt, sqrtSlice[float64]) + } +} + +func TestNot(t *testing.T) { + testInt8x16Unary(t, archsimd.Int8x16.Not, map1[int8](not)) + testInt8x32Unary(t, archsimd.Int8x32.Not, map1[int8](not)) + testInt16x8Unary(t, archsimd.Int16x8.Not, map1[int16](not)) + testInt16x16Unary(t, archsimd.Int16x16.Not, map1[int16](not)) + testInt32x4Unary(t, archsimd.Int32x4.Not, map1[int32](not)) + testInt32x8Unary(t, archsimd.Int32x8.Not, map1[int32](not)) +} + +func TestAbsolute(t *testing.T) { + testInt8x16Unary(t, archsimd.Int8x16.Abs, map1[int8](abs)) + testInt8x32Unary(t, archsimd.Int8x32.Abs, map1[int8](abs)) + testInt16x8Unary(t, archsimd.Int16x8.Abs, map1[int16](abs)) + testInt16x16Unary(t, archsimd.Int16x16.Abs, map1[int16](abs)) + testInt32x4Unary(t, archsimd.Int32x4.Abs, map1[int32](abs)) + testInt32x8Unary(t, archsimd.Int32x8.Abs, map1[int32](abs)) + if archsimd.X86.AVX512() { + testInt8x64Unary(t, archsimd.Int8x64.Abs, map1[int8](abs)) + testInt16x32Unary(t, archsimd.Int16x32.Abs, map1[int16](abs)) + testInt32x16Unary(t, archsimd.Int32x16.Abs, map1[int32](abs)) + testInt64x2Unary(t, archsimd.Int64x2.Abs, map1[int64](abs)) + testInt64x4Unary(t, archsimd.Int64x4.Abs, map1[int64](abs)) + testInt64x8Unary(t, archsimd.Int64x8.Abs, map1[int64](abs)) + } +} + +func TestCeilScaledResidue(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Needs AVX512") + } + testFloat64x8UnaryFlaky(t, + func(x archsimd.Float64x8) archsimd.Float64x8 { return x.CeilScaledResidue(0) }, + map1(ceilResidueForPrecision[float64](0)), + 0.001) + testFloat64x8UnaryFlaky(t, + func(x archsimd.Float64x8) archsimd.Float64x8 { return x.CeilScaledResidue(1) }, + map1(ceilResidueForPrecision[float64](1)), + 0.001) + testFloat64x8Unary(t, + func(x archsimd.Float64x8) archsimd.Float64x8 { return x.Sub(x.CeilScaled(0)) }, + map1[float64](func(x float64) float64 { return x - math.Ceil(x) })) +} + +func TestToUint32(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Needs AVX512") + } + testFloat32x4ConvertToUint32(t, archsimd.Float32x4.ConvertToUint32, map1[float32](toUint32)) + testFloat32x8ConvertToUint32(t, archsimd.Float32x8.ConvertToUint32, map1[float32](toUint32)) + testFloat32x16ConvertToUint32(t, archsimd.Float32x16.ConvertToUint32, map1[float32](toUint32)) +} + +func TestToInt32(t *testing.T) { + testFloat32x4ConvertToInt32(t, archsimd.Float32x4.ConvertToInt32, map1[float32](toInt32)) + testFloat32x8ConvertToInt32(t, archsimd.Float32x8.ConvertToInt32, map1[float32](toInt32)) +} + +func TestConverts(t *testing.T) { + testUint8x16ConvertToUint16(t, archsimd.Uint8x16.ExtendToUint16, map1[uint8](toUint16)) + testUint16x8ConvertToUint32(t, archsimd.Uint16x8.ExtendToUint32, map1[uint16](toUint32)) +} + +func TestConvertsAVX512(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("Needs AVX512") + } + testUint8x32ConvertToUint16(t, archsimd.Uint8x32.ExtendToUint16, map1[uint8](toUint16)) +} diff --git a/src/simd/archsimd/pkginternal_test.go b/src/simd/archsimd/pkginternal_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2b9dea1374933e908377acd838108bd3525f913e --- /dev/null +++ b/src/simd/archsimd/pkginternal_test.go @@ -0,0 +1,268 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build goexperiment.simd && amd64 + +package archsimd_test + +import ( + "fmt" + "os" + "simd/archsimd" + "simd/archsimd/internal/test_helpers" + "testing" +) + +func TestMain(m *testing.M) { + if !archsimd.X86.AVX() { + fmt.Fprintln(os.Stderr, "Skipping tests: AVX is not available") + os.Exit(0) + } + os.Exit(m.Run()) +} + +func TestConcatSelectedConstant64(t *testing.T) { + a := make([]int64, 2) + x := archsimd.LoadInt64x2Slice([]int64{4, 5}) + y := archsimd.LoadInt64x2Slice([]int64{6, 7}) + z := x.ExportTestConcatSelectedConstant(0b10, y) + z.StoreSlice(a) + test_helpers.CheckSlices[int64](t, a, []int64{4, 7}) +} + +func TestConcatSelectedConstantGrouped64(t *testing.T) { + a := make([]float64, 4) + x := archsimd.LoadFloat64x4Slice([]float64{4, 5, 8, 9}) + y := archsimd.LoadFloat64x4Slice([]float64{6, 7, 10, 11}) + z := x.ExportTestConcatSelectedConstantGrouped(0b_11_10, y) + z.StoreSlice(a) + test_helpers.CheckSlices[float64](t, a, []float64{4, 7, 9, 11}) +} + +func TestConcatSelectedConstant32(t *testing.T) { + a := make([]float32, 4) + x := archsimd.LoadFloat32x4Slice([]float32{4, 5, 8, 9}) + y := archsimd.LoadFloat32x4Slice([]float32{6, 7, 10, 11}) + z := x.ExportTestConcatSelectedConstant(0b_11_01_10_00, y) + z.StoreSlice(a) + test_helpers.CheckSlices[float32](t, a, []float32{4, 8, 7, 11}) +} + +func TestConcatSelectedConstantGrouped32(t *testing.T) { + a := make([]uint32, 8) + x := archsimd.LoadUint32x8Slice([]uint32{0, 1, 2, 3, 8, 9, 10, 11}) + y := archsimd.LoadUint32x8Slice([]uint32{4, 5, 6, 7, 12, 13, 14, 15}) + z := x.ExportTestConcatSelectedConstantGrouped(0b_11_01_00_10, y) + z.StoreSlice(a) + test_helpers.CheckSlices[uint32](t, a, []uint32{2, 0, 5, 7, 10, 8, 13, 15}) +} + +func TestTern(t *testing.T) { + if !archsimd.X86.AVX512() { + t.Skip("This test needs AVX512") + } + x := archsimd.LoadInt32x8Slice([]int32{0, 0, 0, 0, 1, 1, 1, 1}) + y := archsimd.LoadInt32x8Slice([]int32{0, 0, 1, 1, 0, 0, 1, 1}) + z := archsimd.LoadInt32x8Slice([]int32{0, 1, 0, 1, 0, 1, 0, 1}) + + foo := func(w archsimd.Int32x8, k uint8) { + a := make([]int32, 8) + w.StoreSlice(a) + t.Logf("For k=%0b, w=%v", k, a) + for i, b := range a { + if (int32(k)>>i)&1 != b { + t.Errorf("Element %d of stored slice (=%d) did not match corresponding bit in 0b%b", + i, b, k) + } + } + } + + foo(x.ExportTestTern(0b1111_0000, y, z), 0b1111_0000) + foo(x.ExportTestTern(0b1100_1100, y, z), 0b1100_1100) + foo(x.ExportTestTern(0b1010_1010, y, z), 0b1010_1010) +} + +func TestSelect2x4x32(t *testing.T) { + for a := range uint8(8) { + for b := range uint8(8) { + for c := range uint8(8) { + for d := range uint8(8) { + x := archsimd.LoadInt32x4Slice([]int32{0, 1, 2, 3}) + y := archsimd.LoadInt32x4Slice([]int32{4, 5, 6, 7}) + z := select2x4x32(x, a, b, c, d, y) + w := make([]int32, 4, 4) + z.StoreSlice(w) + if w[0] != int32(a) || w[1] != int32(b) || + w[2] != int32(c) || w[3] != int32(d) { + t.Errorf("Expected [%d %d %d %d] got %v", a, b, c, d, w) + } + } + } + } + } +} + +func TestSelect2x8x32Grouped(t *testing.T) { + for a := range uint8(8) { + for b := range uint8(8) { + for c := range uint8(8) { + for d := range uint8(8) { + x := archsimd.LoadInt32x8Slice([]int32{0, 1, 2, 3, 10, 11, 12, 13}) + y := archsimd.LoadInt32x8Slice([]int32{4, 5, 6, 7, 14, 15, 16, 17}) + z := select2x8x32Grouped(x, a, b, c, d, y) + w := make([]int32, 8, 8) + z.StoreSlice(w) + if w[0] != int32(a) || w[1] != int32(b) || + w[2] != int32(c) || w[3] != int32(d) || + w[4] != int32(10+a) || w[5] != int32(10+b) || + w[6] != int32(10+c) || w[7] != int32(10+d) { + t.Errorf("Expected [%d %d %d %d %d %d %d %d] got %v", a, b, c, d, 10+a, 10+b, 10+c, 10+d, w) + } + } + } + } + } +} + +// select2x4x32 returns a selection of 4 elements in x and y, numbered +// 0-7, where 0-3 are the four elements of x and 4-7 are the four elements +// of y. +func select2x4x32(x archsimd.Int32x4, a, b, c, d uint8, y archsimd.Int32x4) archsimd.Int32x4 { + pattern := a>>2 + (b&4)>>1 + (c & 4) + (d&4)<<1 + + a, b, c, d = a&3, b&3, c&3, d&3 + + switch pattern { + case archsimd.LLLL: + return x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, b, c, d), x) + case archsimd.HHHH: + return y.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, b, c, d), y) + case archsimd.LLHH: + return x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, b, c, d), y) + case archsimd.HHLL: + return y.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, b, c, d), x) + + case archsimd.HLLL: + z := y.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, a, b, b), x) + return z.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(0, 2, c, d), x) + case archsimd.LHLL: + z := x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, a, b, b), y) + return z.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(0, 2, c, d), x) + + case archsimd.HLHH: + z := y.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, a, b, b), x) + return z.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(0, 2, c, d), y) + case archsimd.LHHH: + z := x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, a, b, b), y) + return z.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(0, 2, c, d), y) + + case archsimd.LLLH: + z := x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(c, c, d, d), y) + return x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, b, 0, 2), z) + case archsimd.LLHL: + z := y.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(c, c, d, d), x) + return x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, b, 0, 2), z) + case archsimd.HHLH: + z := x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(c, c, d, d), y) + return y.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, b, 0, 2), z) + case archsimd.HHHL: + z := y.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(c, c, d, d), x) + return y.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, b, 0, 2), z) + + case archsimd.LHLH: + z := x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, c, b, d), y) + return z.ExportTestConcatSelectedConstant(0b11_01_10_00 /* =archsimd.ExportTestCscImm4(0, 2, 1, 3) */, z) + case archsimd.HLHL: + z := x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(b, d, a, c), y) + return z.ExportTestConcatSelectedConstant(0b01_11_00_10 /* =archsimd.ExportTestCscImm4(2, 0, 3, 1) */, z) + case archsimd.HLLH: + z := x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(b, c, a, d), y) + return z.ExportTestConcatSelectedConstant(0b11_01_00_10 /* =archsimd.ExportTestCscImm4(2, 0, 1, 3) */, z) + case archsimd.LHHL: + z := x.ExportTestConcatSelectedConstant(archsimd.ExportTestCscImm4(a, d, b, c), y) + return z.ExportTestConcatSelectedConstant(0b01_11_10_00 /* =archsimd.ExportTestCscImm4(0, 2, 3, 1) */, z) + } + panic("missing case, switch should be exhaustive") +} + +// select2x8x32Grouped returns a pair of selection of 4 elements in x and y, +// numbered 0-7, where 0-3 are the four elements of x's two groups (lower and +// upper 128 bits) and 4-7 are the four elements of y's two groups. + +func select2x8x32Grouped(x archsimd.Int32x8, a, b, c, d uint8, y archsimd.Int32x8) archsimd.Int32x8 { + // selections as being expressible in the ExportTestConcatSelectedConstant pattern, + // or not. Classification is by H and L, where H is a selection from 4-7 + // and L is a selection from 0-3. + // archsimd.LLHH -> CSC(x,y, a, b, c&3, d&3) + // archsimd.HHLL -> CSC(y,x, a&3, b&3, c, d) + // archsimd.LLLL -> CSC(x,x, a, b, c, d) + // archsimd.HHHH -> CSC(y,y, a&3, b&3, c&3, d&3) + + // archsimd.LLLH -> z = CSC(x, y, c, c, d&3, d&3); CSC(x, z, a, b, 0, 2) + // archsimd.LLHL -> z = CSC(x, y, c&3, c&3, d, d); CSC(x, z, a, b, 0, 2) + // archsimd.HHLH -> z = CSC(x, y, c, c, d&3, d&3); CSC(y, z, a&3, b&3, 0, 2) + // archsimd.HHHL -> z = CSC(x, y, c&3, c&3, d, d); CSC(y, z, a&3, b&3, 0, 2) + + // archsimd.LHLL -> z = CSC(x, y, a, a, b&3, b&3); CSC(z, x, 0, 2, c, d) + // etc + + // archsimd.LHLH -> z = CSC(x, y, a, c, b&3, d&3); CSC(z, z, 0, 2, 1, 3) + // archsimd.HLHL -> z = CSC(x, y, b, d, a&3, c&3); CSC(z, z, 2, 0, 3, 1) + + pattern := a>>2 + (b&4)>>1 + (c & 4) + (d&4)<<1 + + a, b, c, d = a&3, b&3, c&3, d&3 + + switch pattern { + case archsimd.LLLL: + return x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, b, c, d), x) + case archsimd.HHHH: + return y.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, b, c, d), y) + case archsimd.LLHH: + return x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, b, c, d), y) + case archsimd.HHLL: + return y.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, b, c, d), x) + + case archsimd.HLLL: + z := y.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, a, b, b), x) + return z.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(0, 2, c, d), x) + case archsimd.LHLL: + z := x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, a, b, b), y) + return z.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(0, 2, c, d), x) + + case archsimd.HLHH: + z := y.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, a, b, b), x) + return z.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(0, 2, c, d), y) + case archsimd.LHHH: + z := x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, a, b, b), y) + return z.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(0, 2, c, d), y) + + case archsimd.LLLH: + z := x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(c, c, d, d), y) + return x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, b, 0, 2), z) + case archsimd.LLHL: + z := y.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(c, c, d, d), x) + return x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, b, 0, 2), z) + case archsimd.HHLH: + z := x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(c, c, d, d), y) + return y.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, b, 0, 2), z) + case archsimd.HHHL: + z := y.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(c, c, d, d), x) + return y.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, b, 0, 2), z) + + case archsimd.LHLH: + z := x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, c, b, d), y) + return z.ExportTestConcatSelectedConstantGrouped(0b11_01_10_00 /* =archsimd.ExportTestCscImm4(0, 2, 1, 3) */, z) + case archsimd.HLHL: + z := x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(b, d, a, c), y) + return z.ExportTestConcatSelectedConstantGrouped(0b01_11_00_10 /* =archsimd.ExportTestCscImm4(2, 0, 3, 1) */, z) + case archsimd.HLLH: + z := x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(b, c, a, d), y) + return z.ExportTestConcatSelectedConstantGrouped(0b11_01_00_10 /* =archsimd.ExportTestCscImm4(2, 0, 1, 3) */, z) + case archsimd.LHHL: + z := x.ExportTestConcatSelectedConstantGrouped(archsimd.ExportTestCscImm4(a, d, b, c), y) + return z.ExportTestConcatSelectedConstantGrouped(0b01_11_10_00 /* =archsimd.ExportTestCscImm4(0, 2, 3, 1) */, z) + } + panic("missing case, switch should be exhaustive") +} diff --git a/src/simd/compare_gen_amd64.go b/src/simd/archsimd/compare_gen_amd64.go rename from src/simd/compare_gen_amd64.go rename to src/simd/archsimd/compare_gen_amd64.go index 01e4f842118dce8db6a3ebc5504baf8286c05a64..a8636f0b33df9cf3a00c1ebf59e9df2415e4b365 100644 --- a/src/simd/compare_gen_amd64.go +++ b/src/simd/archsimd/compare_gen_amd64.go @@ -2,7 +2,7 @@ // Code generated by 'go run genfiles.go'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd // Less returns a mask whose elements indicate whether x < y // @@ -15,24 +15,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature AVX func (x Int8x16) GreaterEqual(y Int8x16) Mask8x16 { - ones := x.Equal(x).AsInt8x16() - return y.Greater(x).AsInt8x16().Xor(ones).asMask() + ones := x.Equal(x).ToInt8x16() + return y.Greater(x).ToInt8x16().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature AVX func (x Int8x16) LessEqual(y Int8x16) Mask8x16 { - ones := x.Equal(x).AsInt8x16() - return x.Greater(y).AsInt8x16().Xor(ones).asMask() + ones := x.Equal(x).ToInt8x16() + return x.Greater(y).ToInt8x16().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature AVX func (x Int8x16) NotEqual(y Int8x16) Mask8x16 { - ones := x.Equal(x).AsInt8x16() - return x.Equal(y).AsInt8x16().Xor(ones).asMask() + ones := x.Equal(x).ToInt8x16() + return x.Equal(y).ToInt8x16().Xor(ones).asMask() } // Less returns a mask whose elements indicate whether x < y @@ -46,24 +46,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature AVX func (x Int16x8) GreaterEqual(y Int16x8) Mask16x8 { - ones := x.Equal(x).AsInt16x8() - return y.Greater(x).AsInt16x8().Xor(ones).asMask() + ones := x.Equal(x).ToInt16x8() + return y.Greater(x).ToInt16x8().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature AVX func (x Int16x8) LessEqual(y Int16x8) Mask16x8 { - ones := x.Equal(x).AsInt16x8() - return x.Greater(y).AsInt16x8().Xor(ones).asMask() + ones := x.Equal(x).ToInt16x8() + return x.Greater(y).ToInt16x8().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature AVX func (x Int16x8) NotEqual(y Int16x8) Mask16x8 { - ones := x.Equal(x).AsInt16x8() - return x.Equal(y).AsInt16x8().Xor(ones).asMask() + ones := x.Equal(x).ToInt16x8() + return x.Equal(y).ToInt16x8().Xor(ones).asMask() } // Less returns a mask whose elements indicate whether x < y @@ -77,24 +77,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature AVX func (x Int32x4) GreaterEqual(y Int32x4) Mask32x4 { - ones := x.Equal(x).AsInt32x4() - return y.Greater(x).AsInt32x4().Xor(ones).asMask() + ones := x.Equal(x).ToInt32x4() + return y.Greater(x).ToInt32x4().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature AVX func (x Int32x4) LessEqual(y Int32x4) Mask32x4 { - ones := x.Equal(x).AsInt32x4() - return x.Greater(y).AsInt32x4().Xor(ones).asMask() + ones := x.Equal(x).ToInt32x4() + return x.Greater(y).ToInt32x4().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature AVX func (x Int32x4) NotEqual(y Int32x4) Mask32x4 { - ones := x.Equal(x).AsInt32x4() - return x.Equal(y).AsInt32x4().Xor(ones).asMask() + ones := x.Equal(x).ToInt32x4() + return x.Equal(y).ToInt32x4().Xor(ones).asMask() } // Less returns a mask whose elements indicate whether x < y @@ -108,24 +108,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature AVX func (x Int64x2) GreaterEqual(y Int64x2) Mask64x2 { - ones := x.Equal(x).AsInt64x2() - return y.Greater(x).AsInt64x2().Xor(ones).asMask() + ones := x.Equal(x).ToInt64x2() + return y.Greater(x).ToInt64x2().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature AVX func (x Int64x2) LessEqual(y Int64x2) Mask64x2 { - ones := x.Equal(x).AsInt64x2() - return x.Greater(y).AsInt64x2().Xor(ones).asMask() + ones := x.Equal(x).ToInt64x2() + return x.Greater(y).ToInt64x2().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature AVX func (x Int64x2) NotEqual(y Int64x2) Mask64x2 { - ones := x.Equal(x).AsInt64x2() - return x.Equal(y).AsInt64x2().Xor(ones).asMask() + ones := x.Equal(x).ToInt64x2() + return x.Equal(y).ToInt64x2().Xor(ones).asMask() } // Less returns a mask whose elements indicate whether x < y @@ -139,24 +139,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature AVX2 func (x Int8x32) GreaterEqual(y Int8x32) Mask8x32 { - ones := x.Equal(x).AsInt8x32() - return y.Greater(x).AsInt8x32().Xor(ones).asMask() + ones := x.Equal(x).ToInt8x32() + return y.Greater(x).ToInt8x32().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature AVX2 func (x Int8x32) LessEqual(y Int8x32) Mask8x32 { - ones := x.Equal(x).AsInt8x32() - return x.Greater(y).AsInt8x32().Xor(ones).asMask() + ones := x.Equal(x).ToInt8x32() + return x.Greater(y).ToInt8x32().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature AVX2 func (x Int8x32) NotEqual(y Int8x32) Mask8x32 { - ones := x.Equal(x).AsInt8x32() - return x.Equal(y).AsInt8x32().Xor(ones).asMask() + ones := x.Equal(x).ToInt8x32() + return x.Equal(y).ToInt8x32().Xor(ones).asMask() } // Less returns a mask whose elements indicate whether x < y @@ -170,24 +170,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature AVX2 func (x Int16x16) GreaterEqual(y Int16x16) Mask16x16 { - ones := x.Equal(x).AsInt16x16() - return y.Greater(x).AsInt16x16().Xor(ones).asMask() + ones := x.Equal(x).ToInt16x16() + return y.Greater(x).ToInt16x16().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature AVX2 func (x Int16x16) LessEqual(y Int16x16) Mask16x16 { - ones := x.Equal(x).AsInt16x16() - return x.Greater(y).AsInt16x16().Xor(ones).asMask() + ones := x.Equal(x).ToInt16x16() + return x.Greater(y).ToInt16x16().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature AVX2 func (x Int16x16) NotEqual(y Int16x16) Mask16x16 { - ones := x.Equal(x).AsInt16x16() - return x.Equal(y).AsInt16x16().Xor(ones).asMask() + ones := x.Equal(x).ToInt16x16() + return x.Equal(y).ToInt16x16().Xor(ones).asMask() } // Less returns a mask whose elements indicate whether x < y @@ -201,24 +201,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature AVX2 func (x Int32x8) GreaterEqual(y Int32x8) Mask32x8 { - ones := x.Equal(x).AsInt32x8() - return y.Greater(x).AsInt32x8().Xor(ones).asMask() + ones := x.Equal(x).ToInt32x8() + return y.Greater(x).ToInt32x8().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature AVX2 func (x Int32x8) LessEqual(y Int32x8) Mask32x8 { - ones := x.Equal(x).AsInt32x8() - return x.Greater(y).AsInt32x8().Xor(ones).asMask() + ones := x.Equal(x).ToInt32x8() + return x.Greater(y).ToInt32x8().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature AVX2 func (x Int32x8) NotEqual(y Int32x8) Mask32x8 { - ones := x.Equal(x).AsInt32x8() - return x.Equal(y).AsInt32x8().Xor(ones).asMask() + ones := x.Equal(x).ToInt32x8() + return x.Equal(y).ToInt32x8().Xor(ones).asMask() } // Less returns a mask whose elements indicate whether x < y @@ -232,24 +232,24 @@ // GreaterEqual returns a mask whose elements indicate whether x >= y // // Emulated, CPU Feature AVX2 func (x Int64x4) GreaterEqual(y Int64x4) Mask64x4 { - ones := x.Equal(x).AsInt64x4() - return y.Greater(x).AsInt64x4().Xor(ones).asMask() + ones := x.Equal(x).ToInt64x4() + return y.Greater(x).ToInt64x4().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y // // Emulated, CPU Feature AVX2 func (x Int64x4) LessEqual(y Int64x4) Mask64x4 { - ones := x.Equal(x).AsInt64x4() - return x.Greater(y).AsInt64x4().Xor(ones).asMask() + ones := x.Equal(x).ToInt64x4() + return x.Greater(y).ToInt64x4().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y // // Emulated, CPU Feature AVX2 func (x Int64x4) NotEqual(y Int64x4) Mask64x4 { - ones := x.Equal(x).AsInt64x4() - return x.Equal(y).AsInt64x4().Xor(ones).asMask() + ones := x.Equal(x).ToInt64x4() + return x.Equal(y).ToInt64x4().Xor(ones).asMask() } // Greater returns a mask whose elements indicate whether x > y @@ -275,9 +275,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint8x16) GreaterEqual(y Uint8x16) Mask8x16 { a, b := x.AsInt8x16(), y.AsInt8x16() - ones := x.Equal(x).AsInt8x16() + ones := x.Equal(x).ToInt8x16() signs := BroadcastInt8x16(-1 << (8 - 1)) - return b.Xor(signs).Greater(a.Xor(signs)).AsInt8x16().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt8x16().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -285,9 +285,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint8x16) LessEqual(y Uint8x16) Mask8x16 { a, b := x.AsInt8x16(), y.AsInt8x16() - ones := x.Equal(x).AsInt8x16() + ones := x.Equal(x).ToInt8x16() signs := BroadcastInt8x16(-1 << (8 - 1)) - return a.Xor(signs).Greater(b.Xor(signs)).AsInt8x16().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt8x16().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -295,8 +295,8 @@ // // Emulated, CPU Feature AVX func (x Uint8x16) NotEqual(y Uint8x16) Mask8x16 { a, b := x.AsInt8x16(), y.AsInt8x16() - ones := x.Equal(x).AsInt8x16() - return a.Equal(b).AsInt8x16().Xor(ones).asMask() + ones := x.Equal(x).ToInt8x16() + return a.Equal(b).ToInt8x16().Xor(ones).asMask() } // Greater returns a mask whose elements indicate whether x > y @@ -304,7 +304,7 @@ // // Emulated, CPU Feature AVX func (x Uint16x8) Greater(y Uint16x8) Mask16x8 { a, b := x.AsInt16x8(), y.AsInt16x8() - ones := x.Equal(x).AsInt16x8() + ones := x.Equal(x).ToInt16x8() signs := ones.ShiftAllLeft(16 - 1) return a.Xor(signs).Greater(b.Xor(signs)) } @@ -314,7 +314,7 @@ // // Emulated, CPU Feature AVX func (x Uint16x8) Less(y Uint16x8) Mask16x8 { a, b := x.AsInt16x8(), y.AsInt16x8() - ones := x.Equal(x).AsInt16x8() + ones := x.Equal(x).ToInt16x8() signs := ones.ShiftAllLeft(16 - 1) return b.Xor(signs).Greater(a.Xor(signs)) } @@ -324,9 +324,9 @@ // // Emulated, CPU Feature AVX func (x Uint16x8) GreaterEqual(y Uint16x8) Mask16x8 { a, b := x.AsInt16x8(), y.AsInt16x8() - ones := x.Equal(x).AsInt16x8() + ones := x.Equal(x).ToInt16x8() signs := ones.ShiftAllLeft(16 - 1) - return b.Xor(signs).Greater(a.Xor(signs)).AsInt16x8().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt16x8().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -334,9 +334,9 @@ // // Emulated, CPU Feature AVX func (x Uint16x8) LessEqual(y Uint16x8) Mask16x8 { a, b := x.AsInt16x8(), y.AsInt16x8() - ones := x.Equal(x).AsInt16x8() + ones := x.Equal(x).ToInt16x8() signs := ones.ShiftAllLeft(16 - 1) - return a.Xor(signs).Greater(b.Xor(signs)).AsInt16x8().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt16x8().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -344,8 +344,8 @@ // // Emulated, CPU Feature AVX func (x Uint16x8) NotEqual(y Uint16x8) Mask16x8 { a, b := x.AsInt16x8(), y.AsInt16x8() - ones := x.Equal(x).AsInt16x8() - return a.Equal(b).AsInt16x8().Xor(ones).asMask() + ones := x.Equal(x).ToInt16x8() + return a.Equal(b).ToInt16x8().Xor(ones).asMask() } // Greater returns a mask whose elements indicate whether x > y @@ -353,7 +353,7 @@ // // Emulated, CPU Feature AVX func (x Uint32x4) Greater(y Uint32x4) Mask32x4 { a, b := x.AsInt32x4(), y.AsInt32x4() - ones := x.Equal(x).AsInt32x4() + ones := x.Equal(x).ToInt32x4() signs := ones.ShiftAllLeft(32 - 1) return a.Xor(signs).Greater(b.Xor(signs)) } @@ -363,7 +363,7 @@ // // Emulated, CPU Feature AVX func (x Uint32x4) Less(y Uint32x4) Mask32x4 { a, b := x.AsInt32x4(), y.AsInt32x4() - ones := x.Equal(x).AsInt32x4() + ones := x.Equal(x).ToInt32x4() signs := ones.ShiftAllLeft(32 - 1) return b.Xor(signs).Greater(a.Xor(signs)) } @@ -373,9 +373,9 @@ // // Emulated, CPU Feature AVX func (x Uint32x4) GreaterEqual(y Uint32x4) Mask32x4 { a, b := x.AsInt32x4(), y.AsInt32x4() - ones := x.Equal(x).AsInt32x4() + ones := x.Equal(x).ToInt32x4() signs := ones.ShiftAllLeft(32 - 1) - return b.Xor(signs).Greater(a.Xor(signs)).AsInt32x4().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt32x4().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -383,9 +383,9 @@ // // Emulated, CPU Feature AVX func (x Uint32x4) LessEqual(y Uint32x4) Mask32x4 { a, b := x.AsInt32x4(), y.AsInt32x4() - ones := x.Equal(x).AsInt32x4() + ones := x.Equal(x).ToInt32x4() signs := ones.ShiftAllLeft(32 - 1) - return a.Xor(signs).Greater(b.Xor(signs)).AsInt32x4().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt32x4().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -393,8 +393,8 @@ // // Emulated, CPU Feature AVX func (x Uint32x4) NotEqual(y Uint32x4) Mask32x4 { a, b := x.AsInt32x4(), y.AsInt32x4() - ones := x.Equal(x).AsInt32x4() - return a.Equal(b).AsInt32x4().Xor(ones).asMask() + ones := x.Equal(x).ToInt32x4() + return a.Equal(b).ToInt32x4().Xor(ones).asMask() } // Greater returns a mask whose elements indicate whether x > y @@ -402,7 +402,7 @@ // // Emulated, CPU Feature AVX func (x Uint64x2) Greater(y Uint64x2) Mask64x2 { a, b := x.AsInt64x2(), y.AsInt64x2() - ones := x.Equal(x).AsInt64x2() + ones := x.Equal(x).ToInt64x2() signs := ones.ShiftAllLeft(64 - 1) return a.Xor(signs).Greater(b.Xor(signs)) } @@ -412,7 +412,7 @@ // // Emulated, CPU Feature AVX func (x Uint64x2) Less(y Uint64x2) Mask64x2 { a, b := x.AsInt64x2(), y.AsInt64x2() - ones := x.Equal(x).AsInt64x2() + ones := x.Equal(x).ToInt64x2() signs := ones.ShiftAllLeft(64 - 1) return b.Xor(signs).Greater(a.Xor(signs)) } @@ -422,9 +422,9 @@ // // Emulated, CPU Feature AVX func (x Uint64x2) GreaterEqual(y Uint64x2) Mask64x2 { a, b := x.AsInt64x2(), y.AsInt64x2() - ones := x.Equal(x).AsInt64x2() + ones := x.Equal(x).ToInt64x2() signs := ones.ShiftAllLeft(64 - 1) - return b.Xor(signs).Greater(a.Xor(signs)).AsInt64x2().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt64x2().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -432,9 +432,9 @@ // // Emulated, CPU Feature AVX func (x Uint64x2) LessEqual(y Uint64x2) Mask64x2 { a, b := x.AsInt64x2(), y.AsInt64x2() - ones := x.Equal(x).AsInt64x2() + ones := x.Equal(x).ToInt64x2() signs := ones.ShiftAllLeft(64 - 1) - return a.Xor(signs).Greater(b.Xor(signs)).AsInt64x2().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt64x2().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -442,8 +442,8 @@ // // Emulated, CPU Feature AVX func (x Uint64x2) NotEqual(y Uint64x2) Mask64x2 { a, b := x.AsInt64x2(), y.AsInt64x2() - ones := x.Equal(x).AsInt64x2() - return a.Equal(b).AsInt64x2().Xor(ones).asMask() + ones := x.Equal(x).ToInt64x2() + return a.Equal(b).ToInt64x2().Xor(ones).asMask() } // Greater returns a mask whose elements indicate whether x > y @@ -469,9 +469,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint8x32) GreaterEqual(y Uint8x32) Mask8x32 { a, b := x.AsInt8x32(), y.AsInt8x32() - ones := x.Equal(x).AsInt8x32() + ones := x.Equal(x).ToInt8x32() signs := BroadcastInt8x32(-1 << (8 - 1)) - return b.Xor(signs).Greater(a.Xor(signs)).AsInt8x32().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt8x32().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -479,9 +479,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint8x32) LessEqual(y Uint8x32) Mask8x32 { a, b := x.AsInt8x32(), y.AsInt8x32() - ones := x.Equal(x).AsInt8x32() + ones := x.Equal(x).ToInt8x32() signs := BroadcastInt8x32(-1 << (8 - 1)) - return a.Xor(signs).Greater(b.Xor(signs)).AsInt8x32().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt8x32().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -489,8 +489,8 @@ // // Emulated, CPU Feature AVX2 func (x Uint8x32) NotEqual(y Uint8x32) Mask8x32 { a, b := x.AsInt8x32(), y.AsInt8x32() - ones := x.Equal(x).AsInt8x32() - return a.Equal(b).AsInt8x32().Xor(ones).asMask() + ones := x.Equal(x).ToInt8x32() + return a.Equal(b).ToInt8x32().Xor(ones).asMask() } // Greater returns a mask whose elements indicate whether x > y @@ -498,7 +498,7 @@ // // Emulated, CPU Feature AVX2 func (x Uint16x16) Greater(y Uint16x16) Mask16x16 { a, b := x.AsInt16x16(), y.AsInt16x16() - ones := x.Equal(x).AsInt16x16() + ones := x.Equal(x).ToInt16x16() signs := ones.ShiftAllLeft(16 - 1) return a.Xor(signs).Greater(b.Xor(signs)) } @@ -508,7 +508,7 @@ // // Emulated, CPU Feature AVX2 func (x Uint16x16) Less(y Uint16x16) Mask16x16 { a, b := x.AsInt16x16(), y.AsInt16x16() - ones := x.Equal(x).AsInt16x16() + ones := x.Equal(x).ToInt16x16() signs := ones.ShiftAllLeft(16 - 1) return b.Xor(signs).Greater(a.Xor(signs)) } @@ -518,9 +518,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint16x16) GreaterEqual(y Uint16x16) Mask16x16 { a, b := x.AsInt16x16(), y.AsInt16x16() - ones := x.Equal(x).AsInt16x16() + ones := x.Equal(x).ToInt16x16() signs := ones.ShiftAllLeft(16 - 1) - return b.Xor(signs).Greater(a.Xor(signs)).AsInt16x16().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt16x16().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -528,9 +528,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint16x16) LessEqual(y Uint16x16) Mask16x16 { a, b := x.AsInt16x16(), y.AsInt16x16() - ones := x.Equal(x).AsInt16x16() + ones := x.Equal(x).ToInt16x16() signs := ones.ShiftAllLeft(16 - 1) - return a.Xor(signs).Greater(b.Xor(signs)).AsInt16x16().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt16x16().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -538,8 +538,8 @@ // // Emulated, CPU Feature AVX2 func (x Uint16x16) NotEqual(y Uint16x16) Mask16x16 { a, b := x.AsInt16x16(), y.AsInt16x16() - ones := x.Equal(x).AsInt16x16() - return a.Equal(b).AsInt16x16().Xor(ones).asMask() + ones := x.Equal(x).ToInt16x16() + return a.Equal(b).ToInt16x16().Xor(ones).asMask() } // Greater returns a mask whose elements indicate whether x > y @@ -547,7 +547,7 @@ // // Emulated, CPU Feature AVX2 func (x Uint32x8) Greater(y Uint32x8) Mask32x8 { a, b := x.AsInt32x8(), y.AsInt32x8() - ones := x.Equal(x).AsInt32x8() + ones := x.Equal(x).ToInt32x8() signs := ones.ShiftAllLeft(32 - 1) return a.Xor(signs).Greater(b.Xor(signs)) } @@ -557,7 +557,7 @@ // // Emulated, CPU Feature AVX2 func (x Uint32x8) Less(y Uint32x8) Mask32x8 { a, b := x.AsInt32x8(), y.AsInt32x8() - ones := x.Equal(x).AsInt32x8() + ones := x.Equal(x).ToInt32x8() signs := ones.ShiftAllLeft(32 - 1) return b.Xor(signs).Greater(a.Xor(signs)) } @@ -567,9 +567,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint32x8) GreaterEqual(y Uint32x8) Mask32x8 { a, b := x.AsInt32x8(), y.AsInt32x8() - ones := x.Equal(x).AsInt32x8() + ones := x.Equal(x).ToInt32x8() signs := ones.ShiftAllLeft(32 - 1) - return b.Xor(signs).Greater(a.Xor(signs)).AsInt32x8().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt32x8().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -577,9 +577,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint32x8) LessEqual(y Uint32x8) Mask32x8 { a, b := x.AsInt32x8(), y.AsInt32x8() - ones := x.Equal(x).AsInt32x8() + ones := x.Equal(x).ToInt32x8() signs := ones.ShiftAllLeft(32 - 1) - return a.Xor(signs).Greater(b.Xor(signs)).AsInt32x8().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt32x8().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -587,8 +587,8 @@ // // Emulated, CPU Feature AVX2 func (x Uint32x8) NotEqual(y Uint32x8) Mask32x8 { a, b := x.AsInt32x8(), y.AsInt32x8() - ones := x.Equal(x).AsInt32x8() - return a.Equal(b).AsInt32x8().Xor(ones).asMask() + ones := x.Equal(x).ToInt32x8() + return a.Equal(b).ToInt32x8().Xor(ones).asMask() } // Greater returns a mask whose elements indicate whether x > y @@ -596,7 +596,7 @@ // // Emulated, CPU Feature AVX2 func (x Uint64x4) Greater(y Uint64x4) Mask64x4 { a, b := x.AsInt64x4(), y.AsInt64x4() - ones := x.Equal(x).AsInt64x4() + ones := x.Equal(x).ToInt64x4() signs := ones.ShiftAllLeft(64 - 1) return a.Xor(signs).Greater(b.Xor(signs)) } @@ -606,7 +606,7 @@ // // Emulated, CPU Feature AVX2 func (x Uint64x4) Less(y Uint64x4) Mask64x4 { a, b := x.AsInt64x4(), y.AsInt64x4() - ones := x.Equal(x).AsInt64x4() + ones := x.Equal(x).ToInt64x4() signs := ones.ShiftAllLeft(64 - 1) return b.Xor(signs).Greater(a.Xor(signs)) } @@ -616,9 +616,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint64x4) GreaterEqual(y Uint64x4) Mask64x4 { a, b := x.AsInt64x4(), y.AsInt64x4() - ones := x.Equal(x).AsInt64x4() + ones := x.Equal(x).ToInt64x4() signs := ones.ShiftAllLeft(64 - 1) - return b.Xor(signs).Greater(a.Xor(signs)).AsInt64x4().Xor(ones).asMask() + return b.Xor(signs).Greater(a.Xor(signs)).ToInt64x4().Xor(ones).asMask() } // LessEqual returns a mask whose elements indicate whether x <= y @@ -626,9 +626,9 @@ // // Emulated, CPU Feature AVX2 func (x Uint64x4) LessEqual(y Uint64x4) Mask64x4 { a, b := x.AsInt64x4(), y.AsInt64x4() - ones := x.Equal(x).AsInt64x4() + ones := x.Equal(x).ToInt64x4() signs := ones.ShiftAllLeft(64 - 1) - return a.Xor(signs).Greater(b.Xor(signs)).AsInt64x4().Xor(ones).asMask() + return a.Xor(signs).Greater(b.Xor(signs)).ToInt64x4().Xor(ones).asMask() } // NotEqual returns a mask whose elements indicate whether x != y @@ -636,6 +636,6 @@ // // Emulated, CPU Feature AVX2 func (x Uint64x4) NotEqual(y Uint64x4) Mask64x4 { a, b := x.AsInt64x4(), y.AsInt64x4() - ones := x.Equal(x).AsInt64x4() - return a.Equal(b).AsInt64x4().Xor(ones).asMask() + ones := x.Equal(x).ToInt64x4() + return a.Equal(b).ToInt64x4().Xor(ones).asMask() } diff --git a/src/simd/cpu.go b/src/simd/archsimd/cpu.go rename from src/simd/cpu.go rename to src/simd/archsimd/cpu.go index 7c348baedcce60ea6a65997509009a6e455ec294..bb0ebbc16acfcee5368bb473413321722e64b7b2 100644 --- a/src/simd/cpu.go +++ b/src/simd/archsimd/cpu.go @@ -2,7 +2,7 @@ // Code generated by x/arch/internal/simdgen using 'go run . -xedPath $XED_PATH -o godefs -goroot $GOROOT go.yaml types.yaml categories.yaml'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd import "internal/cpu" @@ -93,6 +93,14 @@ // AVX512VNNI is defined on all GOARCHes, but will only return true on // GOARCH amd64. func (X86Features) AVX512VNNI() bool { return cpu.X86.HasAVX512VNNI +} + +// AVX512VPCLMULQDQ returns whether the CPU supports the AVX512VPCLMULQDQ feature. +// +// AVX512VPCLMULQDQ is defined on all GOARCHes, but will only return true on +// GOARCH amd64. +func (X86Features) AVX512VPCLMULQDQ() bool { + return cpu.X86.HasAVX512VPCLMULQDQ } // AVX512VPOPCNTDQ returns whether the CPU supports the AVX512VPOPCNTDQ feature. diff --git a/src/simd/dummy.s b/src/simd/archsimd/dummy.s rename from src/simd/dummy.s rename to src/simd/archsimd/dummy.s diff --git a/src/simd/export_test.go b/src/simd/archsimd/export_test.go rename from src/simd/export_test.go rename to src/simd/archsimd/export_test.go index c6e9c4a85585c40293af1d101709baa9d21c6a61..f448af10d41107e219cf346d47c253b72a1c2bb2 100644 --- a/src/simd/export_test.go +++ b/src/simd/archsimd/export_test.go @@ -6,7 +6,7 @@ //go:build goexperiment.simd && amd64 // This exposes some internal interfaces to simd_test. -package simd +package archsimd func (x Int64x2) ExportTestConcatSelectedConstant(indices uint8, y Int64x2) Int64x2 { return x.concatSelectedConstant(indices, y) diff --git a/src/simd/extra_amd64.go b/src/simd/archsimd/extra_amd64.go rename from src/simd/extra_amd64.go rename to src/simd/archsimd/extra_amd64.go index a7832e6a57f82b14f917904e4c255b3fdf1ebc69..921e148f633eb60c51383fbdb5e794b14a0a095f 100644 --- a/src/simd/extra_amd64.go +++ b/src/simd/archsimd/extra_amd64.go @@ -4,7 +4,7 @@ // license that can be found in the LICENSE file. //go:build goexperiment.simd && amd64 -package simd +package archsimd // ClearAVXUpperBits clears the high bits of Y0-Y15 and Z0-Z15 registers. // It is intended for transitioning from AVX to SSE, eliminating the diff --git a/src/simd/generate.go b/src/simd/archsimd/generate.go rename from src/simd/generate.go rename to src/simd/archsimd/generate.go index 5cd94e165e814d4f0f76e1ced68ae82c7bdcd461..587eb32dfcb32dcae272d56ddb033a601a82e298 100644 --- a/src/simd/generate.go +++ b/src/simd/archsimd/generate.go @@ -4,7 +4,7 @@ // license that can be found in the LICENSE file. //go:build goexperiment.simd -package simd +package archsimd // Invoke code generators. diff --git a/src/simd/internal/simd_test/binary_helpers_test.go b/src/simd/archsimd/internal/simd_test/binary_helpers_test.go rename from src/simd/internal/simd_test/binary_helpers_test.go rename to src/simd/archsimd/internal/simd_test/binary_helpers_test.go index 82cf784bcac72e137fd78d17de13ad991917ddeb..9c361dbeb9888bb3696d23d9c0c87e78ad1feceb 100644 --- a/src/simd/internal/simd_test/binary_helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/binary_helpers_test.go @@ -9,18 +9,18 @@ package simd_test import ( - "simd" + "simd/archsimd" "testing" ) // testInt8x16Binary tests the simd binary method f against the expected behavior generated by want -func testInt8x16Binary(t *testing.T, f func(_, _ simd.Int8x16) simd.Int8x16, want func(_, _ []int8) []int8) { +func testInt8x16Binary(t *testing.T, f func(_, _ archsimd.Int8x16) archsimd.Int8x16, want func(_, _ []int8) []int8) { n := 16 t.Helper() forSlicePair(t, int8s, n, func(x, y []int8) bool { t.Helper() - a := simd.LoadInt8x16Slice(x) - b := simd.LoadInt8x16Slice(y) + a := archsimd.LoadInt8x16Slice(x) + b := archsimd.LoadInt8x16Slice(y) g := make([]int8, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -29,13 +29,13 @@ }) } // testInt16x8Binary tests the simd binary method f against the expected behavior generated by want -func testInt16x8Binary(t *testing.T, f func(_, _ simd.Int16x8) simd.Int16x8, want func(_, _ []int16) []int16) { +func testInt16x8Binary(t *testing.T, f func(_, _ archsimd.Int16x8) archsimd.Int16x8, want func(_, _ []int16) []int16) { n := 8 t.Helper() forSlicePair(t, int16s, n, func(x, y []int16) bool { t.Helper() - a := simd.LoadInt16x8Slice(x) - b := simd.LoadInt16x8Slice(y) + a := archsimd.LoadInt16x8Slice(x) + b := archsimd.LoadInt16x8Slice(y) g := make([]int16, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -44,13 +44,13 @@ }) } // testInt32x4Binary tests the simd binary method f against the expected behavior generated by want -func testInt32x4Binary(t *testing.T, f func(_, _ simd.Int32x4) simd.Int32x4, want func(_, _ []int32) []int32) { +func testInt32x4Binary(t *testing.T, f func(_, _ archsimd.Int32x4) archsimd.Int32x4, want func(_, _ []int32) []int32) { n := 4 t.Helper() forSlicePair(t, int32s, n, func(x, y []int32) bool { t.Helper() - a := simd.LoadInt32x4Slice(x) - b := simd.LoadInt32x4Slice(y) + a := archsimd.LoadInt32x4Slice(x) + b := archsimd.LoadInt32x4Slice(y) g := make([]int32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -59,13 +59,13 @@ }) } // testInt64x2Binary tests the simd binary method f against the expected behavior generated by want -func testInt64x2Binary(t *testing.T, f func(_, _ simd.Int64x2) simd.Int64x2, want func(_, _ []int64) []int64) { +func testInt64x2Binary(t *testing.T, f func(_, _ archsimd.Int64x2) archsimd.Int64x2, want func(_, _ []int64) []int64) { n := 2 t.Helper() forSlicePair(t, int64s, n, func(x, y []int64) bool { t.Helper() - a := simd.LoadInt64x2Slice(x) - b := simd.LoadInt64x2Slice(y) + a := archsimd.LoadInt64x2Slice(x) + b := archsimd.LoadInt64x2Slice(y) g := make([]int64, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -74,13 +74,13 @@ }) } // testUint8x16Binary tests the simd binary method f against the expected behavior generated by want -func testUint8x16Binary(t *testing.T, f func(_, _ simd.Uint8x16) simd.Uint8x16, want func(_, _ []uint8) []uint8) { +func testUint8x16Binary(t *testing.T, f func(_, _ archsimd.Uint8x16) archsimd.Uint8x16, want func(_, _ []uint8) []uint8) { n := 16 t.Helper() forSlicePair(t, uint8s, n, func(x, y []uint8) bool { t.Helper() - a := simd.LoadUint8x16Slice(x) - b := simd.LoadUint8x16Slice(y) + a := archsimd.LoadUint8x16Slice(x) + b := archsimd.LoadUint8x16Slice(y) g := make([]uint8, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -89,13 +89,13 @@ }) } // testUint16x8Binary tests the simd binary method f against the expected behavior generated by want -func testUint16x8Binary(t *testing.T, f func(_, _ simd.Uint16x8) simd.Uint16x8, want func(_, _ []uint16) []uint16) { +func testUint16x8Binary(t *testing.T, f func(_, _ archsimd.Uint16x8) archsimd.Uint16x8, want func(_, _ []uint16) []uint16) { n := 8 t.Helper() forSlicePair(t, uint16s, n, func(x, y []uint16) bool { t.Helper() - a := simd.LoadUint16x8Slice(x) - b := simd.LoadUint16x8Slice(y) + a := archsimd.LoadUint16x8Slice(x) + b := archsimd.LoadUint16x8Slice(y) g := make([]uint16, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -104,13 +104,13 @@ }) } // testUint32x4Binary tests the simd binary method f against the expected behavior generated by want -func testUint32x4Binary(t *testing.T, f func(_, _ simd.Uint32x4) simd.Uint32x4, want func(_, _ []uint32) []uint32) { +func testUint32x4Binary(t *testing.T, f func(_, _ archsimd.Uint32x4) archsimd.Uint32x4, want func(_, _ []uint32) []uint32) { n := 4 t.Helper() forSlicePair(t, uint32s, n, func(x, y []uint32) bool { t.Helper() - a := simd.LoadUint32x4Slice(x) - b := simd.LoadUint32x4Slice(y) + a := archsimd.LoadUint32x4Slice(x) + b := archsimd.LoadUint32x4Slice(y) g := make([]uint32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -119,13 +119,13 @@ }) } // testUint64x2Binary tests the simd binary method f against the expected behavior generated by want -func testUint64x2Binary(t *testing.T, f func(_, _ simd.Uint64x2) simd.Uint64x2, want func(_, _ []uint64) []uint64) { +func testUint64x2Binary(t *testing.T, f func(_, _ archsimd.Uint64x2) archsimd.Uint64x2, want func(_, _ []uint64) []uint64) { n := 2 t.Helper() forSlicePair(t, uint64s, n, func(x, y []uint64) bool { t.Helper() - a := simd.LoadUint64x2Slice(x) - b := simd.LoadUint64x2Slice(y) + a := archsimd.LoadUint64x2Slice(x) + b := archsimd.LoadUint64x2Slice(y) g := make([]uint64, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -134,13 +134,13 @@ }) } // testFloat32x4Binary tests the simd binary method f against the expected behavior generated by want -func testFloat32x4Binary(t *testing.T, f func(_, _ simd.Float32x4) simd.Float32x4, want func(_, _ []float32) []float32) { +func testFloat32x4Binary(t *testing.T, f func(_, _ archsimd.Float32x4) archsimd.Float32x4, want func(_, _ []float32) []float32) { n := 4 t.Helper() forSlicePair(t, float32s, n, func(x, y []float32) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) - b := simd.LoadFloat32x4Slice(y) + a := archsimd.LoadFloat32x4Slice(x) + b := archsimd.LoadFloat32x4Slice(y) g := make([]float32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -149,13 +149,13 @@ }) } // testFloat64x2Binary tests the simd binary method f against the expected behavior generated by want -func testFloat64x2Binary(t *testing.T, f func(_, _ simd.Float64x2) simd.Float64x2, want func(_, _ []float64) []float64) { +func testFloat64x2Binary(t *testing.T, f func(_, _ archsimd.Float64x2) archsimd.Float64x2, want func(_, _ []float64) []float64) { n := 2 t.Helper() forSlicePair(t, float64s, n, func(x, y []float64) bool { t.Helper() - a := simd.LoadFloat64x2Slice(x) - b := simd.LoadFloat64x2Slice(y) + a := archsimd.LoadFloat64x2Slice(x) + b := archsimd.LoadFloat64x2Slice(y) g := make([]float64, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -164,13 +164,13 @@ }) } // testInt8x32Binary tests the simd binary method f against the expected behavior generated by want -func testInt8x32Binary(t *testing.T, f func(_, _ simd.Int8x32) simd.Int8x32, want func(_, _ []int8) []int8) { +func testInt8x32Binary(t *testing.T, f func(_, _ archsimd.Int8x32) archsimd.Int8x32, want func(_, _ []int8) []int8) { n := 32 t.Helper() forSlicePair(t, int8s, n, func(x, y []int8) bool { t.Helper() - a := simd.LoadInt8x32Slice(x) - b := simd.LoadInt8x32Slice(y) + a := archsimd.LoadInt8x32Slice(x) + b := archsimd.LoadInt8x32Slice(y) g := make([]int8, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -179,13 +179,13 @@ }) } // testInt16x16Binary tests the simd binary method f against the expected behavior generated by want -func testInt16x16Binary(t *testing.T, f func(_, _ simd.Int16x16) simd.Int16x16, want func(_, _ []int16) []int16) { +func testInt16x16Binary(t *testing.T, f func(_, _ archsimd.Int16x16) archsimd.Int16x16, want func(_, _ []int16) []int16) { n := 16 t.Helper() forSlicePair(t, int16s, n, func(x, y []int16) bool { t.Helper() - a := simd.LoadInt16x16Slice(x) - b := simd.LoadInt16x16Slice(y) + a := archsimd.LoadInt16x16Slice(x) + b := archsimd.LoadInt16x16Slice(y) g := make([]int16, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -194,13 +194,13 @@ }) } // testInt32x8Binary tests the simd binary method f against the expected behavior generated by want -func testInt32x8Binary(t *testing.T, f func(_, _ simd.Int32x8) simd.Int32x8, want func(_, _ []int32) []int32) { +func testInt32x8Binary(t *testing.T, f func(_, _ archsimd.Int32x8) archsimd.Int32x8, want func(_, _ []int32) []int32) { n := 8 t.Helper() forSlicePair(t, int32s, n, func(x, y []int32) bool { t.Helper() - a := simd.LoadInt32x8Slice(x) - b := simd.LoadInt32x8Slice(y) + a := archsimd.LoadInt32x8Slice(x) + b := archsimd.LoadInt32x8Slice(y) g := make([]int32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -209,13 +209,13 @@ }) } // testInt64x4Binary tests the simd binary method f against the expected behavior generated by want -func testInt64x4Binary(t *testing.T, f func(_, _ simd.Int64x4) simd.Int64x4, want func(_, _ []int64) []int64) { +func testInt64x4Binary(t *testing.T, f func(_, _ archsimd.Int64x4) archsimd.Int64x4, want func(_, _ []int64) []int64) { n := 4 t.Helper() forSlicePair(t, int64s, n, func(x, y []int64) bool { t.Helper() - a := simd.LoadInt64x4Slice(x) - b := simd.LoadInt64x4Slice(y) + a := archsimd.LoadInt64x4Slice(x) + b := archsimd.LoadInt64x4Slice(y) g := make([]int64, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -224,13 +224,13 @@ }) } // testUint8x32Binary tests the simd binary method f against the expected behavior generated by want -func testUint8x32Binary(t *testing.T, f func(_, _ simd.Uint8x32) simd.Uint8x32, want func(_, _ []uint8) []uint8) { +func testUint8x32Binary(t *testing.T, f func(_, _ archsimd.Uint8x32) archsimd.Uint8x32, want func(_, _ []uint8) []uint8) { n := 32 t.Helper() forSlicePair(t, uint8s, n, func(x, y []uint8) bool { t.Helper() - a := simd.LoadUint8x32Slice(x) - b := simd.LoadUint8x32Slice(y) + a := archsimd.LoadUint8x32Slice(x) + b := archsimd.LoadUint8x32Slice(y) g := make([]uint8, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -239,13 +239,13 @@ }) } // testUint16x16Binary tests the simd binary method f against the expected behavior generated by want -func testUint16x16Binary(t *testing.T, f func(_, _ simd.Uint16x16) simd.Uint16x16, want func(_, _ []uint16) []uint16) { +func testUint16x16Binary(t *testing.T, f func(_, _ archsimd.Uint16x16) archsimd.Uint16x16, want func(_, _ []uint16) []uint16) { n := 16 t.Helper() forSlicePair(t, uint16s, n, func(x, y []uint16) bool { t.Helper() - a := simd.LoadUint16x16Slice(x) - b := simd.LoadUint16x16Slice(y) + a := archsimd.LoadUint16x16Slice(x) + b := archsimd.LoadUint16x16Slice(y) g := make([]uint16, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -254,13 +254,13 @@ }) } // testUint32x8Binary tests the simd binary method f against the expected behavior generated by want -func testUint32x8Binary(t *testing.T, f func(_, _ simd.Uint32x8) simd.Uint32x8, want func(_, _ []uint32) []uint32) { +func testUint32x8Binary(t *testing.T, f func(_, _ archsimd.Uint32x8) archsimd.Uint32x8, want func(_, _ []uint32) []uint32) { n := 8 t.Helper() forSlicePair(t, uint32s, n, func(x, y []uint32) bool { t.Helper() - a := simd.LoadUint32x8Slice(x) - b := simd.LoadUint32x8Slice(y) + a := archsimd.LoadUint32x8Slice(x) + b := archsimd.LoadUint32x8Slice(y) g := make([]uint32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -269,13 +269,13 @@ }) } // testUint64x4Binary tests the simd binary method f against the expected behavior generated by want -func testUint64x4Binary(t *testing.T, f func(_, _ simd.Uint64x4) simd.Uint64x4, want func(_, _ []uint64) []uint64) { +func testUint64x4Binary(t *testing.T, f func(_, _ archsimd.Uint64x4) archsimd.Uint64x4, want func(_, _ []uint64) []uint64) { n := 4 t.Helper() forSlicePair(t, uint64s, n, func(x, y []uint64) bool { t.Helper() - a := simd.LoadUint64x4Slice(x) - b := simd.LoadUint64x4Slice(y) + a := archsimd.LoadUint64x4Slice(x) + b := archsimd.LoadUint64x4Slice(y) g := make([]uint64, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -284,13 +284,13 @@ }) } // testFloat32x8Binary tests the simd binary method f against the expected behavior generated by want -func testFloat32x8Binary(t *testing.T, f func(_, _ simd.Float32x8) simd.Float32x8, want func(_, _ []float32) []float32) { +func testFloat32x8Binary(t *testing.T, f func(_, _ archsimd.Float32x8) archsimd.Float32x8, want func(_, _ []float32) []float32) { n := 8 t.Helper() forSlicePair(t, float32s, n, func(x, y []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) - b := simd.LoadFloat32x8Slice(y) + a := archsimd.LoadFloat32x8Slice(x) + b := archsimd.LoadFloat32x8Slice(y) g := make([]float32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -299,13 +299,13 @@ }) } // testFloat64x4Binary tests the simd binary method f against the expected behavior generated by want -func testFloat64x4Binary(t *testing.T, f func(_, _ simd.Float64x4) simd.Float64x4, want func(_, _ []float64) []float64) { +func testFloat64x4Binary(t *testing.T, f func(_, _ archsimd.Float64x4) archsimd.Float64x4, want func(_, _ []float64) []float64) { n := 4 t.Helper() forSlicePair(t, float64s, n, func(x, y []float64) bool { t.Helper() - a := simd.LoadFloat64x4Slice(x) - b := simd.LoadFloat64x4Slice(y) + a := archsimd.LoadFloat64x4Slice(x) + b := archsimd.LoadFloat64x4Slice(y) g := make([]float64, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -314,13 +314,13 @@ }) } // testInt8x64Binary tests the simd binary method f against the expected behavior generated by want -func testInt8x64Binary(t *testing.T, f func(_, _ simd.Int8x64) simd.Int8x64, want func(_, _ []int8) []int8) { +func testInt8x64Binary(t *testing.T, f func(_, _ archsimd.Int8x64) archsimd.Int8x64, want func(_, _ []int8) []int8) { n := 64 t.Helper() forSlicePair(t, int8s, n, func(x, y []int8) bool { t.Helper() - a := simd.LoadInt8x64Slice(x) - b := simd.LoadInt8x64Slice(y) + a := archsimd.LoadInt8x64Slice(x) + b := archsimd.LoadInt8x64Slice(y) g := make([]int8, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -329,13 +329,13 @@ }) } // testInt16x32Binary tests the simd binary method f against the expected behavior generated by want -func testInt16x32Binary(t *testing.T, f func(_, _ simd.Int16x32) simd.Int16x32, want func(_, _ []int16) []int16) { +func testInt16x32Binary(t *testing.T, f func(_, _ archsimd.Int16x32) archsimd.Int16x32, want func(_, _ []int16) []int16) { n := 32 t.Helper() forSlicePair(t, int16s, n, func(x, y []int16) bool { t.Helper() - a := simd.LoadInt16x32Slice(x) - b := simd.LoadInt16x32Slice(y) + a := archsimd.LoadInt16x32Slice(x) + b := archsimd.LoadInt16x32Slice(y) g := make([]int16, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -344,13 +344,13 @@ }) } // testInt32x16Binary tests the simd binary method f against the expected behavior generated by want -func testInt32x16Binary(t *testing.T, f func(_, _ simd.Int32x16) simd.Int32x16, want func(_, _ []int32) []int32) { +func testInt32x16Binary(t *testing.T, f func(_, _ archsimd.Int32x16) archsimd.Int32x16, want func(_, _ []int32) []int32) { n := 16 t.Helper() forSlicePair(t, int32s, n, func(x, y []int32) bool { t.Helper() - a := simd.LoadInt32x16Slice(x) - b := simd.LoadInt32x16Slice(y) + a := archsimd.LoadInt32x16Slice(x) + b := archsimd.LoadInt32x16Slice(y) g := make([]int32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -359,13 +359,13 @@ }) } // testInt64x8Binary tests the simd binary method f against the expected behavior generated by want -func testInt64x8Binary(t *testing.T, f func(_, _ simd.Int64x8) simd.Int64x8, want func(_, _ []int64) []int64) { +func testInt64x8Binary(t *testing.T, f func(_, _ archsimd.Int64x8) archsimd.Int64x8, want func(_, _ []int64) []int64) { n := 8 t.Helper() forSlicePair(t, int64s, n, func(x, y []int64) bool { t.Helper() - a := simd.LoadInt64x8Slice(x) - b := simd.LoadInt64x8Slice(y) + a := archsimd.LoadInt64x8Slice(x) + b := archsimd.LoadInt64x8Slice(y) g := make([]int64, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -374,13 +374,13 @@ }) } // testUint8x64Binary tests the simd binary method f against the expected behavior generated by want -func testUint8x64Binary(t *testing.T, f func(_, _ simd.Uint8x64) simd.Uint8x64, want func(_, _ []uint8) []uint8) { +func testUint8x64Binary(t *testing.T, f func(_, _ archsimd.Uint8x64) archsimd.Uint8x64, want func(_, _ []uint8) []uint8) { n := 64 t.Helper() forSlicePair(t, uint8s, n, func(x, y []uint8) bool { t.Helper() - a := simd.LoadUint8x64Slice(x) - b := simd.LoadUint8x64Slice(y) + a := archsimd.LoadUint8x64Slice(x) + b := archsimd.LoadUint8x64Slice(y) g := make([]uint8, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -389,13 +389,13 @@ }) } // testUint16x32Binary tests the simd binary method f against the expected behavior generated by want -func testUint16x32Binary(t *testing.T, f func(_, _ simd.Uint16x32) simd.Uint16x32, want func(_, _ []uint16) []uint16) { +func testUint16x32Binary(t *testing.T, f func(_, _ archsimd.Uint16x32) archsimd.Uint16x32, want func(_, _ []uint16) []uint16) { n := 32 t.Helper() forSlicePair(t, uint16s, n, func(x, y []uint16) bool { t.Helper() - a := simd.LoadUint16x32Slice(x) - b := simd.LoadUint16x32Slice(y) + a := archsimd.LoadUint16x32Slice(x) + b := archsimd.LoadUint16x32Slice(y) g := make([]uint16, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -404,13 +404,13 @@ }) } // testUint32x16Binary tests the simd binary method f against the expected behavior generated by want -func testUint32x16Binary(t *testing.T, f func(_, _ simd.Uint32x16) simd.Uint32x16, want func(_, _ []uint32) []uint32) { +func testUint32x16Binary(t *testing.T, f func(_, _ archsimd.Uint32x16) archsimd.Uint32x16, want func(_, _ []uint32) []uint32) { n := 16 t.Helper() forSlicePair(t, uint32s, n, func(x, y []uint32) bool { t.Helper() - a := simd.LoadUint32x16Slice(x) - b := simd.LoadUint32x16Slice(y) + a := archsimd.LoadUint32x16Slice(x) + b := archsimd.LoadUint32x16Slice(y) g := make([]uint32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -419,13 +419,13 @@ }) } // testUint64x8Binary tests the simd binary method f against the expected behavior generated by want -func testUint64x8Binary(t *testing.T, f func(_, _ simd.Uint64x8) simd.Uint64x8, want func(_, _ []uint64) []uint64) { +func testUint64x8Binary(t *testing.T, f func(_, _ archsimd.Uint64x8) archsimd.Uint64x8, want func(_, _ []uint64) []uint64) { n := 8 t.Helper() forSlicePair(t, uint64s, n, func(x, y []uint64) bool { t.Helper() - a := simd.LoadUint64x8Slice(x) - b := simd.LoadUint64x8Slice(y) + a := archsimd.LoadUint64x8Slice(x) + b := archsimd.LoadUint64x8Slice(y) g := make([]uint64, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -434,13 +434,13 @@ }) } // testFloat32x16Binary tests the simd binary method f against the expected behavior generated by want -func testFloat32x16Binary(t *testing.T, f func(_, _ simd.Float32x16) simd.Float32x16, want func(_, _ []float32) []float32) { +func testFloat32x16Binary(t *testing.T, f func(_, _ archsimd.Float32x16) archsimd.Float32x16, want func(_, _ []float32) []float32) { n := 16 t.Helper() forSlicePair(t, float32s, n, func(x, y []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) - b := simd.LoadFloat32x16Slice(y) + a := archsimd.LoadFloat32x16Slice(x) + b := archsimd.LoadFloat32x16Slice(y) g := make([]float32, n) f(a, b).StoreSlice(g) w := want(x, y) @@ -449,13 +449,13 @@ }) } // testFloat64x8Binary tests the simd binary method f against the expected behavior generated by want -func testFloat64x8Binary(t *testing.T, f func(_, _ simd.Float64x8) simd.Float64x8, want func(_, _ []float64) []float64) { +func testFloat64x8Binary(t *testing.T, f func(_, _ archsimd.Float64x8) archsimd.Float64x8, want func(_, _ []float64) []float64) { n := 8 t.Helper() forSlicePair(t, float64s, n, func(x, y []float64) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) - b := simd.LoadFloat64x8Slice(y) + a := archsimd.LoadFloat64x8Slice(x) + b := archsimd.LoadFloat64x8Slice(y) g := make([]float64, n) f(a, b).StoreSlice(g) w := want(x, y) diff --git a/src/simd/internal/simd_test/binary_test.go b/src/simd/internal/simd_test/binary_test.go deleted file mode 100644 index 04dca3e2e2ef00674dc0fa18e2749690ec93a6be..0000000000000000000000000000000000000000 --- a/src/simd/internal/simd_test/binary_test.go +++ /dev/null @@ -1,361 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build goexperiment.simd && amd64 - -package simd_test - -import ( - "simd" - "testing" -) - -func TestAdd(t *testing.T) { - testFloat32x4Binary(t, simd.Float32x4.Add, addSlice[float32]) - testFloat32x8Binary(t, simd.Float32x8.Add, addSlice[float32]) - testFloat64x2Binary(t, simd.Float64x2.Add, addSlice[float64]) - testFloat64x4Binary(t, simd.Float64x4.Add, addSlice[float64]) - - testInt16x16Binary(t, simd.Int16x16.Add, addSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.Add, addSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.Add, addSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.Add, addSlice[int32]) - testInt64x2Binary(t, simd.Int64x2.Add, addSlice[int64]) - testInt64x4Binary(t, simd.Int64x4.Add, addSlice[int64]) - testInt8x16Binary(t, simd.Int8x16.Add, addSlice[int8]) - testInt8x32Binary(t, simd.Int8x32.Add, addSlice[int8]) - - testUint16x16Binary(t, simd.Uint16x16.Add, addSlice[uint16]) - testUint16x8Binary(t, simd.Uint16x8.Add, addSlice[uint16]) - testUint32x4Binary(t, simd.Uint32x4.Add, addSlice[uint32]) - testUint32x8Binary(t, simd.Uint32x8.Add, addSlice[uint32]) - testUint64x2Binary(t, simd.Uint64x2.Add, addSlice[uint64]) - testUint64x4Binary(t, simd.Uint64x4.Add, addSlice[uint64]) - testUint8x16Binary(t, simd.Uint8x16.Add, addSlice[uint8]) - testUint8x32Binary(t, simd.Uint8x32.Add, addSlice[uint8]) - - if simd.X86.AVX512() { - testFloat32x16Binary(t, simd.Float32x16.Add, addSlice[float32]) - testFloat64x8Binary(t, simd.Float64x8.Add, addSlice[float64]) - testInt8x64Binary(t, simd.Int8x64.Add, addSlice[int8]) - testInt16x32Binary(t, simd.Int16x32.Add, addSlice[int16]) - testInt32x16Binary(t, simd.Int32x16.Add, addSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.Add, addSlice[int64]) - testUint8x64Binary(t, simd.Uint8x64.Add, addSlice[uint8]) - testUint16x32Binary(t, simd.Uint16x32.Add, addSlice[uint16]) - testUint32x16Binary(t, simd.Uint32x16.Add, addSlice[uint32]) - testUint64x8Binary(t, simd.Uint64x8.Add, addSlice[uint64]) - } -} - -func TestSub(t *testing.T) { - testFloat32x4Binary(t, simd.Float32x4.Sub, subSlice[float32]) - testFloat32x8Binary(t, simd.Float32x8.Sub, subSlice[float32]) - testFloat64x2Binary(t, simd.Float64x2.Sub, subSlice[float64]) - testFloat64x4Binary(t, simd.Float64x4.Sub, subSlice[float64]) - - testInt16x16Binary(t, simd.Int16x16.Sub, subSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.Sub, subSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.Sub, subSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.Sub, subSlice[int32]) - testInt64x2Binary(t, simd.Int64x2.Sub, subSlice[int64]) - testInt64x4Binary(t, simd.Int64x4.Sub, subSlice[int64]) - testInt8x16Binary(t, simd.Int8x16.Sub, subSlice[int8]) - testInt8x32Binary(t, simd.Int8x32.Sub, subSlice[int8]) - - testUint16x16Binary(t, simd.Uint16x16.Sub, subSlice[uint16]) - testUint16x8Binary(t, simd.Uint16x8.Sub, subSlice[uint16]) - testUint32x4Binary(t, simd.Uint32x4.Sub, subSlice[uint32]) - testUint32x8Binary(t, simd.Uint32x8.Sub, subSlice[uint32]) - testUint64x2Binary(t, simd.Uint64x2.Sub, subSlice[uint64]) - testUint64x4Binary(t, simd.Uint64x4.Sub, subSlice[uint64]) - testUint8x16Binary(t, simd.Uint8x16.Sub, subSlice[uint8]) - testUint8x32Binary(t, simd.Uint8x32.Sub, subSlice[uint8]) - - if simd.X86.AVX512() { - testFloat32x16Binary(t, simd.Float32x16.Sub, subSlice[float32]) - testFloat64x8Binary(t, simd.Float64x8.Sub, subSlice[float64]) - testInt8x64Binary(t, simd.Int8x64.Sub, subSlice[int8]) - testInt16x32Binary(t, simd.Int16x32.Sub, subSlice[int16]) - testInt32x16Binary(t, simd.Int32x16.Sub, subSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.Sub, subSlice[int64]) - testUint8x64Binary(t, simd.Uint8x64.Sub, subSlice[uint8]) - testUint16x32Binary(t, simd.Uint16x32.Sub, subSlice[uint16]) - testUint32x16Binary(t, simd.Uint32x16.Sub, subSlice[uint32]) - testUint64x8Binary(t, simd.Uint64x8.Sub, subSlice[uint64]) - } -} - -func TestMax(t *testing.T) { - // testFloat32x4Binary(t, simd.Float32x4.Max, maxSlice[float32]) // nan is wrong - // testFloat32x8Binary(t, simd.Float32x8.Max, maxSlice[float32]) // nan is wrong - // testFloat64x2Binary(t, simd.Float64x2.Max, maxSlice[float64]) // nan is wrong - // testFloat64x4Binary(t, simd.Float64x4.Max, maxSlice[float64]) // nan is wrong - - testInt16x16Binary(t, simd.Int16x16.Max, maxSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.Max, maxSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.Max, maxSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.Max, maxSlice[int32]) - - if simd.X86.AVX512() { - testInt64x2Binary(t, simd.Int64x2.Max, maxSlice[int64]) - testInt64x4Binary(t, simd.Int64x4.Max, maxSlice[int64]) - } - - testInt8x16Binary(t, simd.Int8x16.Max, maxSlice[int8]) - testInt8x32Binary(t, simd.Int8x32.Max, maxSlice[int8]) - - testUint16x16Binary(t, simd.Uint16x16.Max, maxSlice[uint16]) - testUint16x8Binary(t, simd.Uint16x8.Max, maxSlice[uint16]) - testUint32x4Binary(t, simd.Uint32x4.Max, maxSlice[uint32]) - testUint32x8Binary(t, simd.Uint32x8.Max, maxSlice[uint32]) - - if simd.X86.AVX512() { - testUint64x2Binary(t, simd.Uint64x2.Max, maxSlice[uint64]) - testUint64x4Binary(t, simd.Uint64x4.Max, maxSlice[uint64]) - } - - testUint8x16Binary(t, simd.Uint8x16.Max, maxSlice[uint8]) - testUint8x32Binary(t, simd.Uint8x32.Max, maxSlice[uint8]) - - if simd.X86.AVX512() { - // testFloat32x16Binary(t, simd.Float32x16.Max, maxSlice[float32]) // nan is wrong - // testFloat64x8Binary(t, simd.Float64x8.Max, maxSlice[float64]) // nan is wrong - testInt8x64Binary(t, simd.Int8x64.Max, maxSlice[int8]) - testInt16x32Binary(t, simd.Int16x32.Max, maxSlice[int16]) - testInt32x16Binary(t, simd.Int32x16.Max, maxSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.Max, maxSlice[int64]) - testUint8x64Binary(t, simd.Uint8x64.Max, maxSlice[uint8]) - testUint16x32Binary(t, simd.Uint16x32.Max, maxSlice[uint16]) - testUint32x16Binary(t, simd.Uint32x16.Max, maxSlice[uint32]) - testUint64x8Binary(t, simd.Uint64x8.Max, maxSlice[uint64]) - } -} - -func TestMin(t *testing.T) { - // testFloat32x4Binary(t, simd.Float32x4.Min, minSlice[float32]) // nan is wrong - // testFloat32x8Binary(t, simd.Float32x8.Min, minSlice[float32]) // nan is wrong - // testFloat64x2Binary(t, simd.Float64x2.Min, minSlice[float64]) // nan is wrong - // testFloat64x4Binary(t, simd.Float64x4.Min, minSlice[float64]) // nan is wrong - - testInt16x16Binary(t, simd.Int16x16.Min, minSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.Min, minSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.Min, minSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.Min, minSlice[int32]) - - if simd.X86.AVX512() { - testInt64x2Binary(t, simd.Int64x2.Min, minSlice[int64]) - testInt64x4Binary(t, simd.Int64x4.Min, minSlice[int64]) - } - - testInt8x16Binary(t, simd.Int8x16.Min, minSlice[int8]) - testInt8x32Binary(t, simd.Int8x32.Min, minSlice[int8]) - - testUint16x16Binary(t, simd.Uint16x16.Min, minSlice[uint16]) - testUint16x8Binary(t, simd.Uint16x8.Min, minSlice[uint16]) - testUint32x4Binary(t, simd.Uint32x4.Min, minSlice[uint32]) - testUint32x8Binary(t, simd.Uint32x8.Min, minSlice[uint32]) - - if simd.X86.AVX512() { - testUint64x2Binary(t, simd.Uint64x2.Min, minSlice[uint64]) - testUint64x4Binary(t, simd.Uint64x4.Min, minSlice[uint64]) - } - - testUint8x16Binary(t, simd.Uint8x16.Min, minSlice[uint8]) - testUint8x32Binary(t, simd.Uint8x32.Min, minSlice[uint8]) - - if simd.X86.AVX512() { - // testFloat32x16Binary(t, simd.Float32x16.Min, minSlice[float32]) // nan is wrong - // testFloat64x8Binary(t, simd.Float64x8.Min, minSlice[float64]) // nan is wrong - testInt8x64Binary(t, simd.Int8x64.Min, minSlice[int8]) - testInt16x32Binary(t, simd.Int16x32.Min, minSlice[int16]) - testInt32x16Binary(t, simd.Int32x16.Min, minSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.Min, minSlice[int64]) - testUint8x64Binary(t, simd.Uint8x64.Min, minSlice[uint8]) - testUint16x32Binary(t, simd.Uint16x32.Min, minSlice[uint16]) - testUint32x16Binary(t, simd.Uint32x16.Min, minSlice[uint32]) - testUint64x8Binary(t, simd.Uint64x8.Min, minSlice[uint64]) - } -} - -func TestAnd(t *testing.T) { - testInt16x16Binary(t, simd.Int16x16.And, andSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.And, andSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.And, andSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.And, andSlice[int32]) - testInt64x2Binary(t, simd.Int64x2.And, andSlice[int64]) - testInt64x4Binary(t, simd.Int64x4.And, andSlice[int64]) - testInt8x16Binary(t, simd.Int8x16.And, andSlice[int8]) - testInt8x32Binary(t, simd.Int8x32.And, andSlice[int8]) - - testUint16x16Binary(t, simd.Uint16x16.And, andSlice[uint16]) - testUint16x8Binary(t, simd.Uint16x8.And, andSlice[uint16]) - testUint32x4Binary(t, simd.Uint32x4.And, andSlice[uint32]) - testUint32x8Binary(t, simd.Uint32x8.And, andSlice[uint32]) - testUint64x2Binary(t, simd.Uint64x2.And, andSlice[uint64]) - testUint64x4Binary(t, simd.Uint64x4.And, andSlice[uint64]) - testUint8x16Binary(t, simd.Uint8x16.And, andSlice[uint8]) - testUint8x32Binary(t, simd.Uint8x32.And, andSlice[uint8]) - - if simd.X86.AVX512() { - // testInt8x64Binary(t, simd.Int8x64.And, andISlice[int8]) // missing - // testInt16x32Binary(t, simd.Int16x32.And, andISlice[int16]) // missing - testInt32x16Binary(t, simd.Int32x16.And, andSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.And, andSlice[int64]) - // testUint8x64Binary(t, simd.Uint8x64.And, andISlice[uint8]) // missing - // testUint16x32Binary(t, simd.Uint16x32.And, andISlice[uint16]) // missing - testUint32x16Binary(t, simd.Uint32x16.And, andSlice[uint32]) - testUint64x8Binary(t, simd.Uint64x8.And, andSlice[uint64]) - } -} - -func TestAndNot(t *testing.T) { - testInt16x16Binary(t, simd.Int16x16.AndNot, andNotSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.AndNot, andNotSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.AndNot, andNotSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.AndNot, andNotSlice[int32]) - testInt64x2Binary(t, simd.Int64x2.AndNot, andNotSlice[int64]) - testInt64x4Binary(t, simd.Int64x4.AndNot, andNotSlice[int64]) - testInt8x16Binary(t, simd.Int8x16.AndNot, andNotSlice[int8]) - testInt8x32Binary(t, simd.Int8x32.AndNot, andNotSlice[int8]) - - testUint16x16Binary(t, simd.Uint16x16.AndNot, andNotSlice[uint16]) - testUint16x8Binary(t, simd.Uint16x8.AndNot, andNotSlice[uint16]) - testUint32x4Binary(t, simd.Uint32x4.AndNot, andNotSlice[uint32]) - testUint32x8Binary(t, simd.Uint32x8.AndNot, andNotSlice[uint32]) - testUint64x2Binary(t, simd.Uint64x2.AndNot, andNotSlice[uint64]) - testUint64x4Binary(t, simd.Uint64x4.AndNot, andNotSlice[uint64]) - testUint8x16Binary(t, simd.Uint8x16.AndNot, andNotSlice[uint8]) - testUint8x32Binary(t, simd.Uint8x32.AndNot, andNotSlice[uint8]) - - if simd.X86.AVX512() { - testInt8x64Binary(t, simd.Int8x64.AndNot, andNotSlice[int8]) - testInt16x32Binary(t, simd.Int16x32.AndNot, andNotSlice[int16]) - testInt32x16Binary(t, simd.Int32x16.AndNot, andNotSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.AndNot, andNotSlice[int64]) - testUint8x64Binary(t, simd.Uint8x64.AndNot, andNotSlice[uint8]) - testUint16x32Binary(t, simd.Uint16x32.AndNot, andNotSlice[uint16]) - testUint32x16Binary(t, simd.Uint32x16.AndNot, andNotSlice[uint32]) - testUint64x8Binary(t, simd.Uint64x8.AndNot, andNotSlice[uint64]) - } -} - -func TestXor(t *testing.T) { - testInt16x16Binary(t, simd.Int16x16.Xor, xorSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.Xor, xorSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.Xor, xorSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.Xor, xorSlice[int32]) - testInt64x2Binary(t, simd.Int64x2.Xor, xorSlice[int64]) - testInt64x4Binary(t, simd.Int64x4.Xor, xorSlice[int64]) - testInt8x16Binary(t, simd.Int8x16.Xor, xorSlice[int8]) - testInt8x32Binary(t, simd.Int8x32.Xor, xorSlice[int8]) - - testUint16x16Binary(t, simd.Uint16x16.Xor, xorSlice[uint16]) - testUint16x8Binary(t, simd.Uint16x8.Xor, xorSlice[uint16]) - testUint32x4Binary(t, simd.Uint32x4.Xor, xorSlice[uint32]) - testUint32x8Binary(t, simd.Uint32x8.Xor, xorSlice[uint32]) - testUint64x2Binary(t, simd.Uint64x2.Xor, xorSlice[uint64]) - testUint64x4Binary(t, simd.Uint64x4.Xor, xorSlice[uint64]) - testUint8x16Binary(t, simd.Uint8x16.Xor, xorSlice[uint8]) - testUint8x32Binary(t, simd.Uint8x32.Xor, xorSlice[uint8]) - - if simd.X86.AVX512() { - // testInt8x64Binary(t, simd.Int8x64.Xor, andISlice[int8]) // missing - // testInt16x32Binary(t, simd.Int16x32.Xor, andISlice[int16]) // missing - testInt32x16Binary(t, simd.Int32x16.Xor, xorSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.Xor, xorSlice[int64]) - // testUint8x64Binary(t, simd.Uint8x64.Xor, andISlice[uint8]) // missing - // testUint16x32Binary(t, simd.Uint16x32.Xor, andISlice[uint16]) // missing - testUint32x16Binary(t, simd.Uint32x16.Xor, xorSlice[uint32]) - testUint64x8Binary(t, simd.Uint64x8.Xor, xorSlice[uint64]) - } -} - -func TestOr(t *testing.T) { - testInt16x16Binary(t, simd.Int16x16.Or, orSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.Or, orSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.Or, orSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.Or, orSlice[int32]) - testInt64x2Binary(t, simd.Int64x2.Or, orSlice[int64]) - testInt64x4Binary(t, simd.Int64x4.Or, orSlice[int64]) - testInt8x16Binary(t, simd.Int8x16.Or, orSlice[int8]) - testInt8x32Binary(t, simd.Int8x32.Or, orSlice[int8]) - - testUint16x16Binary(t, simd.Uint16x16.Or, orSlice[uint16]) - testUint16x8Binary(t, simd.Uint16x8.Or, orSlice[uint16]) - testUint32x4Binary(t, simd.Uint32x4.Or, orSlice[uint32]) - testUint32x8Binary(t, simd.Uint32x8.Or, orSlice[uint32]) - testUint64x2Binary(t, simd.Uint64x2.Or, orSlice[uint64]) - testUint64x4Binary(t, simd.Uint64x4.Or, orSlice[uint64]) - testUint8x16Binary(t, simd.Uint8x16.Or, orSlice[uint8]) - testUint8x32Binary(t, simd.Uint8x32.Or, orSlice[uint8]) - - if simd.X86.AVX512() { - // testInt8x64Binary(t, simd.Int8x64.Or, andISlice[int8]) // missing - // testInt16x32Binary(t, simd.Int16x32.Or, andISlice[int16]) // missing - testInt32x16Binary(t, simd.Int32x16.Or, orSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.Or, orSlice[int64]) - // testUint8x64Binary(t, simd.Uint8x64.Or, andISlice[uint8]) // missing - // testUint16x32Binary(t, simd.Uint16x32.Or, andISlice[uint16]) // missing - testUint32x16Binary(t, simd.Uint32x16.Or, orSlice[uint32]) - testUint64x8Binary(t, simd.Uint64x8.Or, orSlice[uint64]) - } -} - -func TestMul(t *testing.T) { - testFloat32x4Binary(t, simd.Float32x4.Mul, mulSlice[float32]) - testFloat32x8Binary(t, simd.Float32x8.Mul, mulSlice[float32]) - testFloat64x2Binary(t, simd.Float64x2.Mul, mulSlice[float64]) - testFloat64x4Binary(t, simd.Float64x4.Mul, mulSlice[float64]) - - testInt16x16Binary(t, simd.Int16x16.Mul, mulSlice[int16]) - testInt16x8Binary(t, simd.Int16x8.Mul, mulSlice[int16]) - testInt32x4Binary(t, simd.Int32x4.Mul, mulSlice[int32]) - testInt32x8Binary(t, simd.Int32x8.Mul, mulSlice[int32]) - - // testInt8x16Binary(t, simd.Int8x16.Mul, mulSlice[int8]) // nope - // testInt8x32Binary(t, simd.Int8x32.Mul, mulSlice[int8]) - - // TODO we should be able to do these, there's no difference between signed/unsigned Mul - // testUint16x16Binary(t, simd.Uint16x16.Mul, mulSlice[uint16]) - // testUint16x8Binary(t, simd.Uint16x8.Mul, mulSlice[uint16]) - // testUint32x4Binary(t, simd.Uint32x4.Mul, mulSlice[uint32]) - // testUint32x8Binary(t, simd.Uint32x8.Mul, mulSlice[uint32]) - // testUint64x2Binary(t, simd.Uint64x2.Mul, mulSlice[uint64]) - // testUint64x4Binary(t, simd.Uint64x4.Mul, mulSlice[uint64]) - - // testUint8x16Binary(t, simd.Uint8x16.Mul, mulSlice[uint8]) // nope - // testUint8x32Binary(t, simd.Uint8x32.Mul, mulSlice[uint8]) - - if simd.X86.AVX512() { - testInt64x2Binary(t, simd.Int64x2.Mul, mulSlice[int64]) // avx512 only - testInt64x4Binary(t, simd.Int64x4.Mul, mulSlice[int64]) - - testFloat32x16Binary(t, simd.Float32x16.Mul, mulSlice[float32]) - testFloat64x8Binary(t, simd.Float64x8.Mul, mulSlice[float64]) - - // testInt8x64Binary(t, simd.Int8x64.Mul, mulSlice[int8]) // nope - testInt16x32Binary(t, simd.Int16x32.Mul, mulSlice[int16]) - testInt32x16Binary(t, simd.Int32x16.Mul, mulSlice[int32]) - testInt64x8Binary(t, simd.Int64x8.Mul, mulSlice[int64]) - // testUint8x64Binary(t, simd.Uint8x64.Mul, mulSlice[uint8]) // nope - - // TODO signed should do the job - // testUint16x32Binary(t, simd.Uint16x32.Mul, mulSlice[uint16]) - // testUint32x16Binary(t, simd.Uint32x16.Mul, mulSlice[uint32]) - // testUint64x8Binary(t, simd.Uint64x8.Mul, mulSlice[uint64]) - } -} - -func TestDiv(t *testing.T) { - testFloat32x4Binary(t, simd.Float32x4.Div, divSlice[float32]) - testFloat32x8Binary(t, simd.Float32x8.Div, divSlice[float32]) - testFloat64x2Binary(t, simd.Float64x2.Div, divSlice[float64]) - testFloat64x4Binary(t, simd.Float64x4.Div, divSlice[float64]) - - if simd.X86.AVX512() { - testFloat32x16Binary(t, simd.Float32x16.Div, divSlice[float32]) - testFloat64x8Binary(t, simd.Float64x8.Div, divSlice[float64]) - } -} diff --git a/src/simd/internal/simd_test/compare_helpers_test.go b/src/simd/archsimd/internal/simd_test/compare_helpers_test.go rename from src/simd/internal/simd_test/compare_helpers_test.go rename to src/simd/archsimd/internal/simd_test/compare_helpers_test.go index aef703c66a06d198888ddbc26634624632fae27e..279fdc7155802588bdf67819ac9fa511ba2960b2 100644 --- a/src/simd/internal/simd_test/compare_helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/compare_helpers_test.go @@ -9,455 +9,455 @@ package simd_test import ( - "simd" + "simd/archsimd" "testing" ) // testInt8x16Compare tests the simd comparison method f against the expected behavior generated by want -func testInt8x16Compare(t *testing.T, f func(_, _ simd.Int8x16) simd.Mask8x16, want func(_, _ []int8) []int64) { +func testInt8x16Compare(t *testing.T, f func(_, _ archsimd.Int8x16) archsimd.Mask8x16, want func(_, _ []int8) []int64) { n := 16 t.Helper() forSlicePair(t, int8s, n, func(x, y []int8) bool { t.Helper() - a := simd.LoadInt8x16Slice(x) - b := simd.LoadInt8x16Slice(y) + a := archsimd.LoadInt8x16Slice(x) + b := archsimd.LoadInt8x16Slice(y) g := make([]int8, n) - f(a, b).AsInt8x16().StoreSlice(g) + f(a, b).ToInt8x16().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt16x8Compare tests the simd comparison method f against the expected behavior generated by want -func testInt16x8Compare(t *testing.T, f func(_, _ simd.Int16x8) simd.Mask16x8, want func(_, _ []int16) []int64) { +func testInt16x8Compare(t *testing.T, f func(_, _ archsimd.Int16x8) archsimd.Mask16x8, want func(_, _ []int16) []int64) { n := 8 t.Helper() forSlicePair(t, int16s, n, func(x, y []int16) bool { t.Helper() - a := simd.LoadInt16x8Slice(x) - b := simd.LoadInt16x8Slice(y) + a := archsimd.LoadInt16x8Slice(x) + b := archsimd.LoadInt16x8Slice(y) g := make([]int16, n) - f(a, b).AsInt16x8().StoreSlice(g) + f(a, b).ToInt16x8().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt32x4Compare tests the simd comparison method f against the expected behavior generated by want -func testInt32x4Compare(t *testing.T, f func(_, _ simd.Int32x4) simd.Mask32x4, want func(_, _ []int32) []int64) { +func testInt32x4Compare(t *testing.T, f func(_, _ archsimd.Int32x4) archsimd.Mask32x4, want func(_, _ []int32) []int64) { n := 4 t.Helper() forSlicePair(t, int32s, n, func(x, y []int32) bool { t.Helper() - a := simd.LoadInt32x4Slice(x) - b := simd.LoadInt32x4Slice(y) + a := archsimd.LoadInt32x4Slice(x) + b := archsimd.LoadInt32x4Slice(y) g := make([]int32, n) - f(a, b).AsInt32x4().StoreSlice(g) + f(a, b).ToInt32x4().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt64x2Compare tests the simd comparison method f against the expected behavior generated by want -func testInt64x2Compare(t *testing.T, f func(_, _ simd.Int64x2) simd.Mask64x2, want func(_, _ []int64) []int64) { +func testInt64x2Compare(t *testing.T, f func(_, _ archsimd.Int64x2) archsimd.Mask64x2, want func(_, _ []int64) []int64) { n := 2 t.Helper() forSlicePair(t, int64s, n, func(x, y []int64) bool { t.Helper() - a := simd.LoadInt64x2Slice(x) - b := simd.LoadInt64x2Slice(y) + a := archsimd.LoadInt64x2Slice(x) + b := archsimd.LoadInt64x2Slice(y) g := make([]int64, n) - f(a, b).AsInt64x2().StoreSlice(g) + f(a, b).ToInt64x2().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint8x16Compare tests the simd comparison method f against the expected behavior generated by want -func testUint8x16Compare(t *testing.T, f func(_, _ simd.Uint8x16) simd.Mask8x16, want func(_, _ []uint8) []int64) { +func testUint8x16Compare(t *testing.T, f func(_, _ archsimd.Uint8x16) archsimd.Mask8x16, want func(_, _ []uint8) []int64) { n := 16 t.Helper() forSlicePair(t, uint8s, n, func(x, y []uint8) bool { t.Helper() - a := simd.LoadUint8x16Slice(x) - b := simd.LoadUint8x16Slice(y) + a := archsimd.LoadUint8x16Slice(x) + b := archsimd.LoadUint8x16Slice(y) g := make([]int8, n) - f(a, b).AsInt8x16().StoreSlice(g) + f(a, b).ToInt8x16().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint16x8Compare tests the simd comparison method f against the expected behavior generated by want -func testUint16x8Compare(t *testing.T, f func(_, _ simd.Uint16x8) simd.Mask16x8, want func(_, _ []uint16) []int64) { +func testUint16x8Compare(t *testing.T, f func(_, _ archsimd.Uint16x8) archsimd.Mask16x8, want func(_, _ []uint16) []int64) { n := 8 t.Helper() forSlicePair(t, uint16s, n, func(x, y []uint16) bool { t.Helper() - a := simd.LoadUint16x8Slice(x) - b := simd.LoadUint16x8Slice(y) + a := archsimd.LoadUint16x8Slice(x) + b := archsimd.LoadUint16x8Slice(y) g := make([]int16, n) - f(a, b).AsInt16x8().StoreSlice(g) + f(a, b).ToInt16x8().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint32x4Compare tests the simd comparison method f against the expected behavior generated by want -func testUint32x4Compare(t *testing.T, f func(_, _ simd.Uint32x4) simd.Mask32x4, want func(_, _ []uint32) []int64) { +func testUint32x4Compare(t *testing.T, f func(_, _ archsimd.Uint32x4) archsimd.Mask32x4, want func(_, _ []uint32) []int64) { n := 4 t.Helper() forSlicePair(t, uint32s, n, func(x, y []uint32) bool { t.Helper() - a := simd.LoadUint32x4Slice(x) - b := simd.LoadUint32x4Slice(y) + a := archsimd.LoadUint32x4Slice(x) + b := archsimd.LoadUint32x4Slice(y) g := make([]int32, n) - f(a, b).AsInt32x4().StoreSlice(g) + f(a, b).ToInt32x4().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint64x2Compare tests the simd comparison method f against the expected behavior generated by want -func testUint64x2Compare(t *testing.T, f func(_, _ simd.Uint64x2) simd.Mask64x2, want func(_, _ []uint64) []int64) { +func testUint64x2Compare(t *testing.T, f func(_, _ archsimd.Uint64x2) archsimd.Mask64x2, want func(_, _ []uint64) []int64) { n := 2 t.Helper() forSlicePair(t, uint64s, n, func(x, y []uint64) bool { t.Helper() - a := simd.LoadUint64x2Slice(x) - b := simd.LoadUint64x2Slice(y) + a := archsimd.LoadUint64x2Slice(x) + b := archsimd.LoadUint64x2Slice(y) g := make([]int64, n) - f(a, b).AsInt64x2().StoreSlice(g) + f(a, b).ToInt64x2().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testFloat32x4Compare tests the simd comparison method f against the expected behavior generated by want -func testFloat32x4Compare(t *testing.T, f func(_, _ simd.Float32x4) simd.Mask32x4, want func(_, _ []float32) []int64) { +func testFloat32x4Compare(t *testing.T, f func(_, _ archsimd.Float32x4) archsimd.Mask32x4, want func(_, _ []float32) []int64) { n := 4 t.Helper() forSlicePair(t, float32s, n, func(x, y []float32) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) - b := simd.LoadFloat32x4Slice(y) + a := archsimd.LoadFloat32x4Slice(x) + b := archsimd.LoadFloat32x4Slice(y) g := make([]int32, n) - f(a, b).AsInt32x4().StoreSlice(g) + f(a, b).ToInt32x4().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testFloat64x2Compare tests the simd comparison method f against the expected behavior generated by want -func testFloat64x2Compare(t *testing.T, f func(_, _ simd.Float64x2) simd.Mask64x2, want func(_, _ []float64) []int64) { +func testFloat64x2Compare(t *testing.T, f func(_, _ archsimd.Float64x2) archsimd.Mask64x2, want func(_, _ []float64) []int64) { n := 2 t.Helper() forSlicePair(t, float64s, n, func(x, y []float64) bool { t.Helper() - a := simd.LoadFloat64x2Slice(x) - b := simd.LoadFloat64x2Slice(y) + a := archsimd.LoadFloat64x2Slice(x) + b := archsimd.LoadFloat64x2Slice(y) g := make([]int64, n) - f(a, b).AsInt64x2().StoreSlice(g) + f(a, b).ToInt64x2().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt8x32Compare tests the simd comparison method f against the expected behavior generated by want -func testInt8x32Compare(t *testing.T, f func(_, _ simd.Int8x32) simd.Mask8x32, want func(_, _ []int8) []int64) { +func testInt8x32Compare(t *testing.T, f func(_, _ archsimd.Int8x32) archsimd.Mask8x32, want func(_, _ []int8) []int64) { n := 32 t.Helper() forSlicePair(t, int8s, n, func(x, y []int8) bool { t.Helper() - a := simd.LoadInt8x32Slice(x) - b := simd.LoadInt8x32Slice(y) + a := archsimd.LoadInt8x32Slice(x) + b := archsimd.LoadInt8x32Slice(y) g := make([]int8, n) - f(a, b).AsInt8x32().StoreSlice(g) + f(a, b).ToInt8x32().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt16x16Compare tests the simd comparison method f against the expected behavior generated by want -func testInt16x16Compare(t *testing.T, f func(_, _ simd.Int16x16) simd.Mask16x16, want func(_, _ []int16) []int64) { +func testInt16x16Compare(t *testing.T, f func(_, _ archsimd.Int16x16) archsimd.Mask16x16, want func(_, _ []int16) []int64) { n := 16 t.Helper() forSlicePair(t, int16s, n, func(x, y []int16) bool { t.Helper() - a := simd.LoadInt16x16Slice(x) - b := simd.LoadInt16x16Slice(y) + a := archsimd.LoadInt16x16Slice(x) + b := archsimd.LoadInt16x16Slice(y) g := make([]int16, n) - f(a, b).AsInt16x16().StoreSlice(g) + f(a, b).ToInt16x16().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt32x8Compare tests the simd comparison method f against the expected behavior generated by want -func testInt32x8Compare(t *testing.T, f func(_, _ simd.Int32x8) simd.Mask32x8, want func(_, _ []int32) []int64) { +func testInt32x8Compare(t *testing.T, f func(_, _ archsimd.Int32x8) archsimd.Mask32x8, want func(_, _ []int32) []int64) { n := 8 t.Helper() forSlicePair(t, int32s, n, func(x, y []int32) bool { t.Helper() - a := simd.LoadInt32x8Slice(x) - b := simd.LoadInt32x8Slice(y) + a := archsimd.LoadInt32x8Slice(x) + b := archsimd.LoadInt32x8Slice(y) g := make([]int32, n) - f(a, b).AsInt32x8().StoreSlice(g) + f(a, b).ToInt32x8().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt64x4Compare tests the simd comparison method f against the expected behavior generated by want -func testInt64x4Compare(t *testing.T, f func(_, _ simd.Int64x4) simd.Mask64x4, want func(_, _ []int64) []int64) { +func testInt64x4Compare(t *testing.T, f func(_, _ archsimd.Int64x4) archsimd.Mask64x4, want func(_, _ []int64) []int64) { n := 4 t.Helper() forSlicePair(t, int64s, n, func(x, y []int64) bool { t.Helper() - a := simd.LoadInt64x4Slice(x) - b := simd.LoadInt64x4Slice(y) + a := archsimd.LoadInt64x4Slice(x) + b := archsimd.LoadInt64x4Slice(y) g := make([]int64, n) - f(a, b).AsInt64x4().StoreSlice(g) + f(a, b).ToInt64x4().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint8x32Compare tests the simd comparison method f against the expected behavior generated by want -func testUint8x32Compare(t *testing.T, f func(_, _ simd.Uint8x32) simd.Mask8x32, want func(_, _ []uint8) []int64) { +func testUint8x32Compare(t *testing.T, f func(_, _ archsimd.Uint8x32) archsimd.Mask8x32, want func(_, _ []uint8) []int64) { n := 32 t.Helper() forSlicePair(t, uint8s, n, func(x, y []uint8) bool { t.Helper() - a := simd.LoadUint8x32Slice(x) - b := simd.LoadUint8x32Slice(y) + a := archsimd.LoadUint8x32Slice(x) + b := archsimd.LoadUint8x32Slice(y) g := make([]int8, n) - f(a, b).AsInt8x32().StoreSlice(g) + f(a, b).ToInt8x32().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint16x16Compare tests the simd comparison method f against the expected behavior generated by want -func testUint16x16Compare(t *testing.T, f func(_, _ simd.Uint16x16) simd.Mask16x16, want func(_, _ []uint16) []int64) { +func testUint16x16Compare(t *testing.T, f func(_, _ archsimd.Uint16x16) archsimd.Mask16x16, want func(_, _ []uint16) []int64) { n := 16 t.Helper() forSlicePair(t, uint16s, n, func(x, y []uint16) bool { t.Helper() - a := simd.LoadUint16x16Slice(x) - b := simd.LoadUint16x16Slice(y) + a := archsimd.LoadUint16x16Slice(x) + b := archsimd.LoadUint16x16Slice(y) g := make([]int16, n) - f(a, b).AsInt16x16().StoreSlice(g) + f(a, b).ToInt16x16().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint32x8Compare tests the simd comparison method f against the expected behavior generated by want -func testUint32x8Compare(t *testing.T, f func(_, _ simd.Uint32x8) simd.Mask32x8, want func(_, _ []uint32) []int64) { +func testUint32x8Compare(t *testing.T, f func(_, _ archsimd.Uint32x8) archsimd.Mask32x8, want func(_, _ []uint32) []int64) { n := 8 t.Helper() forSlicePair(t, uint32s, n, func(x, y []uint32) bool { t.Helper() - a := simd.LoadUint32x8Slice(x) - b := simd.LoadUint32x8Slice(y) + a := archsimd.LoadUint32x8Slice(x) + b := archsimd.LoadUint32x8Slice(y) g := make([]int32, n) - f(a, b).AsInt32x8().StoreSlice(g) + f(a, b).ToInt32x8().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint64x4Compare tests the simd comparison method f against the expected behavior generated by want -func testUint64x4Compare(t *testing.T, f func(_, _ simd.Uint64x4) simd.Mask64x4, want func(_, _ []uint64) []int64) { +func testUint64x4Compare(t *testing.T, f func(_, _ archsimd.Uint64x4) archsimd.Mask64x4, want func(_, _ []uint64) []int64) { n := 4 t.Helper() forSlicePair(t, uint64s, n, func(x, y []uint64) bool { t.Helper() - a := simd.LoadUint64x4Slice(x) - b := simd.LoadUint64x4Slice(y) + a := archsimd.LoadUint64x4Slice(x) + b := archsimd.LoadUint64x4Slice(y) g := make([]int64, n) - f(a, b).AsInt64x4().StoreSlice(g) + f(a, b).ToInt64x4().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testFloat32x8Compare tests the simd comparison method f against the expected behavior generated by want -func testFloat32x8Compare(t *testing.T, f func(_, _ simd.Float32x8) simd.Mask32x8, want func(_, _ []float32) []int64) { +func testFloat32x8Compare(t *testing.T, f func(_, _ archsimd.Float32x8) archsimd.Mask32x8, want func(_, _ []float32) []int64) { n := 8 t.Helper() forSlicePair(t, float32s, n, func(x, y []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) - b := simd.LoadFloat32x8Slice(y) + a := archsimd.LoadFloat32x8Slice(x) + b := archsimd.LoadFloat32x8Slice(y) g := make([]int32, n) - f(a, b).AsInt32x8().StoreSlice(g) + f(a, b).ToInt32x8().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testFloat64x4Compare tests the simd comparison method f against the expected behavior generated by want -func testFloat64x4Compare(t *testing.T, f func(_, _ simd.Float64x4) simd.Mask64x4, want func(_, _ []float64) []int64) { +func testFloat64x4Compare(t *testing.T, f func(_, _ archsimd.Float64x4) archsimd.Mask64x4, want func(_, _ []float64) []int64) { n := 4 t.Helper() forSlicePair(t, float64s, n, func(x, y []float64) bool { t.Helper() - a := simd.LoadFloat64x4Slice(x) - b := simd.LoadFloat64x4Slice(y) + a := archsimd.LoadFloat64x4Slice(x) + b := archsimd.LoadFloat64x4Slice(y) g := make([]int64, n) - f(a, b).AsInt64x4().StoreSlice(g) + f(a, b).ToInt64x4().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt8x64Compare tests the simd comparison method f against the expected behavior generated by want -func testInt8x64Compare(t *testing.T, f func(_, _ simd.Int8x64) simd.Mask8x64, want func(_, _ []int8) []int64) { +func testInt8x64Compare(t *testing.T, f func(_, _ archsimd.Int8x64) archsimd.Mask8x64, want func(_, _ []int8) []int64) { n := 64 t.Helper() forSlicePair(t, int8s, n, func(x, y []int8) bool { t.Helper() - a := simd.LoadInt8x64Slice(x) - b := simd.LoadInt8x64Slice(y) + a := archsimd.LoadInt8x64Slice(x) + b := archsimd.LoadInt8x64Slice(y) g := make([]int8, n) - f(a, b).AsInt8x64().StoreSlice(g) + f(a, b).ToInt8x64().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt16x32Compare tests the simd comparison method f against the expected behavior generated by want -func testInt16x32Compare(t *testing.T, f func(_, _ simd.Int16x32) simd.Mask16x32, want func(_, _ []int16) []int64) { +func testInt16x32Compare(t *testing.T, f func(_, _ archsimd.Int16x32) archsimd.Mask16x32, want func(_, _ []int16) []int64) { n := 32 t.Helper() forSlicePair(t, int16s, n, func(x, y []int16) bool { t.Helper() - a := simd.LoadInt16x32Slice(x) - b := simd.LoadInt16x32Slice(y) + a := archsimd.LoadInt16x32Slice(x) + b := archsimd.LoadInt16x32Slice(y) g := make([]int16, n) - f(a, b).AsInt16x32().StoreSlice(g) + f(a, b).ToInt16x32().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt32x16Compare tests the simd comparison method f against the expected behavior generated by want -func testInt32x16Compare(t *testing.T, f func(_, _ simd.Int32x16) simd.Mask32x16, want func(_, _ []int32) []int64) { +func testInt32x16Compare(t *testing.T, f func(_, _ archsimd.Int32x16) archsimd.Mask32x16, want func(_, _ []int32) []int64) { n := 16 t.Helper() forSlicePair(t, int32s, n, func(x, y []int32) bool { t.Helper() - a := simd.LoadInt32x16Slice(x) - b := simd.LoadInt32x16Slice(y) + a := archsimd.LoadInt32x16Slice(x) + b := archsimd.LoadInt32x16Slice(y) g := make([]int32, n) - f(a, b).AsInt32x16().StoreSlice(g) + f(a, b).ToInt32x16().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testInt64x8Compare tests the simd comparison method f against the expected behavior generated by want -func testInt64x8Compare(t *testing.T, f func(_, _ simd.Int64x8) simd.Mask64x8, want func(_, _ []int64) []int64) { +func testInt64x8Compare(t *testing.T, f func(_, _ archsimd.Int64x8) archsimd.Mask64x8, want func(_, _ []int64) []int64) { n := 8 t.Helper() forSlicePair(t, int64s, n, func(x, y []int64) bool { t.Helper() - a := simd.LoadInt64x8Slice(x) - b := simd.LoadInt64x8Slice(y) + a := archsimd.LoadInt64x8Slice(x) + b := archsimd.LoadInt64x8Slice(y) g := make([]int64, n) - f(a, b).AsInt64x8().StoreSlice(g) + f(a, b).ToInt64x8().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint8x64Compare tests the simd comparison method f against the expected behavior generated by want -func testUint8x64Compare(t *testing.T, f func(_, _ simd.Uint8x64) simd.Mask8x64, want func(_, _ []uint8) []int64) { +func testUint8x64Compare(t *testing.T, f func(_, _ archsimd.Uint8x64) archsimd.Mask8x64, want func(_, _ []uint8) []int64) { n := 64 t.Helper() forSlicePair(t, uint8s, n, func(x, y []uint8) bool { t.Helper() - a := simd.LoadUint8x64Slice(x) - b := simd.LoadUint8x64Slice(y) + a := archsimd.LoadUint8x64Slice(x) + b := archsimd.LoadUint8x64Slice(y) g := make([]int8, n) - f(a, b).AsInt8x64().StoreSlice(g) + f(a, b).ToInt8x64().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint16x32Compare tests the simd comparison method f against the expected behavior generated by want -func testUint16x32Compare(t *testing.T, f func(_, _ simd.Uint16x32) simd.Mask16x32, want func(_, _ []uint16) []int64) { +func testUint16x32Compare(t *testing.T, f func(_, _ archsimd.Uint16x32) archsimd.Mask16x32, want func(_, _ []uint16) []int64) { n := 32 t.Helper() forSlicePair(t, uint16s, n, func(x, y []uint16) bool { t.Helper() - a := simd.LoadUint16x32Slice(x) - b := simd.LoadUint16x32Slice(y) + a := archsimd.LoadUint16x32Slice(x) + b := archsimd.LoadUint16x32Slice(y) g := make([]int16, n) - f(a, b).AsInt16x32().StoreSlice(g) + f(a, b).ToInt16x32().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint32x16Compare tests the simd comparison method f against the expected behavior generated by want -func testUint32x16Compare(t *testing.T, f func(_, _ simd.Uint32x16) simd.Mask32x16, want func(_, _ []uint32) []int64) { +func testUint32x16Compare(t *testing.T, f func(_, _ archsimd.Uint32x16) archsimd.Mask32x16, want func(_, _ []uint32) []int64) { n := 16 t.Helper() forSlicePair(t, uint32s, n, func(x, y []uint32) bool { t.Helper() - a := simd.LoadUint32x16Slice(x) - b := simd.LoadUint32x16Slice(y) + a := archsimd.LoadUint32x16Slice(x) + b := archsimd.LoadUint32x16Slice(y) g := make([]int32, n) - f(a, b).AsInt32x16().StoreSlice(g) + f(a, b).ToInt32x16().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testUint64x8Compare tests the simd comparison method f against the expected behavior generated by want -func testUint64x8Compare(t *testing.T, f func(_, _ simd.Uint64x8) simd.Mask64x8, want func(_, _ []uint64) []int64) { +func testUint64x8Compare(t *testing.T, f func(_, _ archsimd.Uint64x8) archsimd.Mask64x8, want func(_, _ []uint64) []int64) { n := 8 t.Helper() forSlicePair(t, uint64s, n, func(x, y []uint64) bool { t.Helper() - a := simd.LoadUint64x8Slice(x) - b := simd.LoadUint64x8Slice(y) + a := archsimd.LoadUint64x8Slice(x) + b := archsimd.LoadUint64x8Slice(y) g := make([]int64, n) - f(a, b).AsInt64x8().StoreSlice(g) + f(a, b).ToInt64x8().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testFloat32x16Compare tests the simd comparison method f against the expected behavior generated by want -func testFloat32x16Compare(t *testing.T, f func(_, _ simd.Float32x16) simd.Mask32x16, want func(_, _ []float32) []int64) { +func testFloat32x16Compare(t *testing.T, f func(_, _ archsimd.Float32x16) archsimd.Mask32x16, want func(_, _ []float32) []int64) { n := 16 t.Helper() forSlicePair(t, float32s, n, func(x, y []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) - b := simd.LoadFloat32x16Slice(y) + a := archsimd.LoadFloat32x16Slice(x) + b := archsimd.LoadFloat32x16Slice(y) g := make([]int32, n) - f(a, b).AsInt32x16().StoreSlice(g) + f(a, b).ToInt32x16().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) } // testFloat64x8Compare tests the simd comparison method f against the expected behavior generated by want -func testFloat64x8Compare(t *testing.T, f func(_, _ simd.Float64x8) simd.Mask64x8, want func(_, _ []float64) []int64) { +func testFloat64x8Compare(t *testing.T, f func(_, _ archsimd.Float64x8) archsimd.Mask64x8, want func(_, _ []float64) []int64) { n := 8 t.Helper() forSlicePair(t, float64s, n, func(x, y []float64) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) - b := simd.LoadFloat64x8Slice(y) + a := archsimd.LoadFloat64x8Slice(x) + b := archsimd.LoadFloat64x8Slice(y) g := make([]int64, n) - f(a, b).AsInt64x8().StoreSlice(g) + f(a, b).ToInt64x8().StoreSlice(g) w := want(x, y) return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) }) }) diff --git a/src/simd/internal/simd_test/compare_test.go b/src/simd/internal/simd_test/compare_test.go deleted file mode 100644 index 09b3bfc0d96ff13c7ed8eac57dd97f3c07592774..0000000000000000000000000000000000000000 --- a/src/simd/internal/simd_test/compare_test.go +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build goexperiment.simd && amd64 - -package simd_test - -import ( - "simd" - "testing" -) - -// AVX 2 lacks most comparisons, but they can be synthesized -// from > and = -var comparisonFixed bool = simd.X86.AVX512() - -func TestLess(t *testing.T) { - testFloat32x4Compare(t, simd.Float32x4.Less, lessSlice[float32]) - testFloat32x8Compare(t, simd.Float32x8.Less, lessSlice[float32]) - testFloat64x2Compare(t, simd.Float64x2.Less, lessSlice[float64]) - testFloat64x4Compare(t, simd.Float64x4.Less, lessSlice[float64]) - - testInt16x16Compare(t, simd.Int16x16.Less, lessSlice[int16]) - testInt16x8Compare(t, simd.Int16x8.Less, lessSlice[int16]) - testInt32x4Compare(t, simd.Int32x4.Less, lessSlice[int32]) - testInt32x8Compare(t, simd.Int32x8.Less, lessSlice[int32]) - testInt64x2Compare(t, simd.Int64x2.Less, lessSlice[int64]) - testInt64x4Compare(t, simd.Int64x4.Less, lessSlice[int64]) - testInt8x16Compare(t, simd.Int8x16.Less, lessSlice[int8]) - testInt8x32Compare(t, simd.Int8x32.Less, lessSlice[int8]) - - testInt16x16Compare(t, simd.Int16x16.Less, lessSlice[int16]) - testInt16x8Compare(t, simd.Int16x8.Less, lessSlice[int16]) - testInt32x4Compare(t, simd.Int32x4.Less, lessSlice[int32]) - testInt32x8Compare(t, simd.Int32x8.Less, lessSlice[int32]) - testInt64x2Compare(t, simd.Int64x2.Less, lessSlice[int64]) - testInt64x4Compare(t, simd.Int64x4.Less, lessSlice[int64]) - testInt8x16Compare(t, simd.Int8x16.Less, lessSlice[int8]) - testInt8x32Compare(t, simd.Int8x32.Less, lessSlice[int8]) - - testUint16x16Compare(t, simd.Uint16x16.Less, lessSlice[uint16]) - testUint16x8Compare(t, simd.Uint16x8.Less, lessSlice[uint16]) - testUint32x4Compare(t, simd.Uint32x4.Less, lessSlice[uint32]) - testUint32x8Compare(t, simd.Uint32x8.Less, lessSlice[uint32]) - testUint64x2Compare(t, simd.Uint64x2.Less, lessSlice[uint64]) - testUint64x4Compare(t, simd.Uint64x4.Less, lessSlice[uint64]) - testUint8x16Compare(t, simd.Uint8x16.Less, lessSlice[uint8]) - testUint8x32Compare(t, simd.Uint8x32.Less, lessSlice[uint8]) - - if simd.X86.AVX512() { - testUint16x16Compare(t, simd.Uint16x16.Less, lessSlice[uint16]) - testUint16x8Compare(t, simd.Uint16x8.Less, lessSlice[uint16]) - testUint32x4Compare(t, simd.Uint32x4.Less, lessSlice[uint32]) - testUint32x8Compare(t, simd.Uint32x8.Less, lessSlice[uint32]) - testUint64x2Compare(t, simd.Uint64x2.Less, lessSlice[uint64]) - testUint64x4Compare(t, simd.Uint64x4.Less, lessSlice[uint64]) - testUint8x16Compare(t, simd.Uint8x16.Less, lessSlice[uint8]) - testUint8x32Compare(t, simd.Uint8x32.Less, lessSlice[uint8]) - - testFloat32x16Compare(t, simd.Float32x16.Less, lessSlice[float32]) - testFloat64x8Compare(t, simd.Float64x8.Less, lessSlice[float64]) - testInt8x64Compare(t, simd.Int8x64.Less, lessSlice[int8]) - testInt16x32Compare(t, simd.Int16x32.Less, lessSlice[int16]) - testInt32x16Compare(t, simd.Int32x16.Less, lessSlice[int32]) - testInt64x8Compare(t, simd.Int64x8.Less, lessSlice[int64]) - testUint8x64Compare(t, simd.Uint8x64.Less, lessSlice[uint8]) - testUint16x32Compare(t, simd.Uint16x32.Less, lessSlice[uint16]) - testUint32x16Compare(t, simd.Uint32x16.Less, lessSlice[uint32]) - testUint64x8Compare(t, simd.Uint64x8.Less, lessSlice[uint64]) - } -} - -func TestLessEqual(t *testing.T) { - testFloat32x4Compare(t, simd.Float32x4.LessEqual, lessEqualSlice[float32]) - testFloat32x8Compare(t, simd.Float32x8.LessEqual, lessEqualSlice[float32]) - testFloat64x2Compare(t, simd.Float64x2.LessEqual, lessEqualSlice[float64]) - testFloat64x4Compare(t, simd.Float64x4.LessEqual, lessEqualSlice[float64]) - - testInt16x16Compare(t, simd.Int16x16.LessEqual, lessEqualSlice[int16]) - testInt16x8Compare(t, simd.Int16x8.LessEqual, lessEqualSlice[int16]) - testInt32x4Compare(t, simd.Int32x4.LessEqual, lessEqualSlice[int32]) - testInt32x8Compare(t, simd.Int32x8.LessEqual, lessEqualSlice[int32]) - testInt64x2Compare(t, simd.Int64x2.LessEqual, lessEqualSlice[int64]) - testInt64x4Compare(t, simd.Int64x4.LessEqual, lessEqualSlice[int64]) - testInt8x16Compare(t, simd.Int8x16.LessEqual, lessEqualSlice[int8]) - testInt8x32Compare(t, simd.Int8x32.LessEqual, lessEqualSlice[int8]) - - testUint16x16Compare(t, simd.Uint16x16.LessEqual, lessEqualSlice[uint16]) - testUint16x8Compare(t, simd.Uint16x8.LessEqual, lessEqualSlice[uint16]) - testUint32x4Compare(t, simd.Uint32x4.LessEqual, lessEqualSlice[uint32]) - testUint32x8Compare(t, simd.Uint32x8.LessEqual, lessEqualSlice[uint32]) - testUint64x2Compare(t, simd.Uint64x2.LessEqual, lessEqualSlice[uint64]) - testUint64x4Compare(t, simd.Uint64x4.LessEqual, lessEqualSlice[uint64]) - testUint8x16Compare(t, simd.Uint8x16.LessEqual, lessEqualSlice[uint8]) - testUint8x32Compare(t, simd.Uint8x32.LessEqual, lessEqualSlice[uint8]) - - if simd.X86.AVX512() { - testFloat32x16Compare(t, simd.Float32x16.LessEqual, lessEqualSlice[float32]) - testFloat64x8Compare(t, simd.Float64x8.LessEqual, lessEqualSlice[float64]) - testInt8x64Compare(t, simd.Int8x64.LessEqual, lessEqualSlice[int8]) - testInt16x32Compare(t, simd.Int16x32.LessEqual, lessEqualSlice[int16]) - testInt32x16Compare(t, simd.Int32x16.LessEqual, lessEqualSlice[int32]) - testInt64x8Compare(t, simd.Int64x8.LessEqual, lessEqualSlice[int64]) - testUint8x64Compare(t, simd.Uint8x64.LessEqual, lessEqualSlice[uint8]) - testUint16x32Compare(t, simd.Uint16x32.LessEqual, lessEqualSlice[uint16]) - testUint32x16Compare(t, simd.Uint32x16.LessEqual, lessEqualSlice[uint32]) - testUint64x8Compare(t, simd.Uint64x8.LessEqual, lessEqualSlice[uint64]) - } -} - -func TestGreater(t *testing.T) { - testFloat32x4Compare(t, simd.Float32x4.Greater, greaterSlice[float32]) - testFloat32x8Compare(t, simd.Float32x8.Greater, greaterSlice[float32]) - testFloat64x2Compare(t, simd.Float64x2.Greater, greaterSlice[float64]) - testFloat64x4Compare(t, simd.Float64x4.Greater, greaterSlice[float64]) - - testInt16x16Compare(t, simd.Int16x16.Greater, greaterSlice[int16]) - testInt16x8Compare(t, simd.Int16x8.Greater, greaterSlice[int16]) - testInt32x4Compare(t, simd.Int32x4.Greater, greaterSlice[int32]) - testInt32x8Compare(t, simd.Int32x8.Greater, greaterSlice[int32]) - - testInt64x2Compare(t, simd.Int64x2.Greater, greaterSlice[int64]) - testInt64x4Compare(t, simd.Int64x4.Greater, greaterSlice[int64]) - testInt8x16Compare(t, simd.Int8x16.Greater, greaterSlice[int8]) - testInt8x32Compare(t, simd.Int8x32.Greater, greaterSlice[int8]) - - testUint16x16Compare(t, simd.Uint16x16.Greater, greaterSlice[uint16]) - testUint16x8Compare(t, simd.Uint16x8.Greater, greaterSlice[uint16]) - testUint32x4Compare(t, simd.Uint32x4.Greater, greaterSlice[uint32]) - testUint32x8Compare(t, simd.Uint32x8.Greater, greaterSlice[uint32]) - - testUint64x2Compare(t, simd.Uint64x2.Greater, greaterSlice[uint64]) - testUint64x4Compare(t, simd.Uint64x4.Greater, greaterSlice[uint64]) - testUint8x16Compare(t, simd.Uint8x16.Greater, greaterSlice[uint8]) - testUint8x32Compare(t, simd.Uint8x32.Greater, greaterSlice[uint8]) - - if simd.X86.AVX512() { - - testFloat32x16Compare(t, simd.Float32x16.Greater, greaterSlice[float32]) - testFloat64x8Compare(t, simd.Float64x8.Greater, greaterSlice[float64]) - testInt8x64Compare(t, simd.Int8x64.Greater, greaterSlice[int8]) - testInt16x32Compare(t, simd.Int16x32.Greater, greaterSlice[int16]) - testInt32x16Compare(t, simd.Int32x16.Greater, greaterSlice[int32]) - testInt64x8Compare(t, simd.Int64x8.Greater, greaterSlice[int64]) - testUint8x64Compare(t, simd.Uint8x64.Greater, greaterSlice[uint8]) - testUint16x32Compare(t, simd.Uint16x32.Greater, greaterSlice[uint16]) - testUint32x16Compare(t, simd.Uint32x16.Greater, greaterSlice[uint32]) - testUint64x8Compare(t, simd.Uint64x8.Greater, greaterSlice[uint64]) - } -} - -func TestGreaterEqual(t *testing.T) { - testFloat32x4Compare(t, simd.Float32x4.GreaterEqual, greaterEqualSlice[float32]) - testFloat32x8Compare(t, simd.Float32x8.GreaterEqual, greaterEqualSlice[float32]) - testFloat64x2Compare(t, simd.Float64x2.GreaterEqual, greaterEqualSlice[float64]) - testFloat64x4Compare(t, simd.Float64x4.GreaterEqual, greaterEqualSlice[float64]) - - testInt16x16Compare(t, simd.Int16x16.GreaterEqual, greaterEqualSlice[int16]) - testInt16x8Compare(t, simd.Int16x8.GreaterEqual, greaterEqualSlice[int16]) - testInt32x4Compare(t, simd.Int32x4.GreaterEqual, greaterEqualSlice[int32]) - testInt32x8Compare(t, simd.Int32x8.GreaterEqual, greaterEqualSlice[int32]) - testInt64x2Compare(t, simd.Int64x2.GreaterEqual, greaterEqualSlice[int64]) - testInt64x4Compare(t, simd.Int64x4.GreaterEqual, greaterEqualSlice[int64]) - testInt8x16Compare(t, simd.Int8x16.GreaterEqual, greaterEqualSlice[int8]) - testInt8x32Compare(t, simd.Int8x32.GreaterEqual, greaterEqualSlice[int8]) - - testUint16x16Compare(t, simd.Uint16x16.GreaterEqual, greaterEqualSlice[uint16]) - testUint16x8Compare(t, simd.Uint16x8.GreaterEqual, greaterEqualSlice[uint16]) - testUint32x4Compare(t, simd.Uint32x4.GreaterEqual, greaterEqualSlice[uint32]) - testUint32x8Compare(t, simd.Uint32x8.GreaterEqual, greaterEqualSlice[uint32]) - testUint64x2Compare(t, simd.Uint64x2.GreaterEqual, greaterEqualSlice[uint64]) - testUint64x4Compare(t, simd.Uint64x4.GreaterEqual, greaterEqualSlice[uint64]) - testUint8x16Compare(t, simd.Uint8x16.GreaterEqual, greaterEqualSlice[uint8]) - testUint8x32Compare(t, simd.Uint8x32.GreaterEqual, greaterEqualSlice[uint8]) - - if simd.X86.AVX512() { - testFloat32x16Compare(t, simd.Float32x16.GreaterEqual, greaterEqualSlice[float32]) - testFloat64x8Compare(t, simd.Float64x8.GreaterEqual, greaterEqualSlice[float64]) - testInt8x64Compare(t, simd.Int8x64.GreaterEqual, greaterEqualSlice[int8]) - testInt16x32Compare(t, simd.Int16x32.GreaterEqual, greaterEqualSlice[int16]) - testInt32x16Compare(t, simd.Int32x16.GreaterEqual, greaterEqualSlice[int32]) - testInt64x8Compare(t, simd.Int64x8.GreaterEqual, greaterEqualSlice[int64]) - testUint8x64Compare(t, simd.Uint8x64.GreaterEqual, greaterEqualSlice[uint8]) - testUint16x32Compare(t, simd.Uint16x32.GreaterEqual, greaterEqualSlice[uint16]) - testUint32x16Compare(t, simd.Uint32x16.GreaterEqual, greaterEqualSlice[uint32]) - testUint64x8Compare(t, simd.Uint64x8.GreaterEqual, greaterEqualSlice[uint64]) - } -} - -func TestEqual(t *testing.T) { - testFloat32x4Compare(t, simd.Float32x4.Equal, equalSlice[float32]) - testFloat32x8Compare(t, simd.Float32x8.Equal, equalSlice[float32]) - testFloat64x2Compare(t, simd.Float64x2.Equal, equalSlice[float64]) - testFloat64x4Compare(t, simd.Float64x4.Equal, equalSlice[float64]) - - testInt16x16Compare(t, simd.Int16x16.Equal, equalSlice[int16]) - testInt16x8Compare(t, simd.Int16x8.Equal, equalSlice[int16]) - testInt32x4Compare(t, simd.Int32x4.Equal, equalSlice[int32]) - testInt32x8Compare(t, simd.Int32x8.Equal, equalSlice[int32]) - testInt64x2Compare(t, simd.Int64x2.Equal, equalSlice[int64]) - testInt64x4Compare(t, simd.Int64x4.Equal, equalSlice[int64]) - testInt8x16Compare(t, simd.Int8x16.Equal, equalSlice[int8]) - testInt8x32Compare(t, simd.Int8x32.Equal, equalSlice[int8]) - - testUint16x16Compare(t, simd.Uint16x16.Equal, equalSlice[uint16]) - testUint16x8Compare(t, simd.Uint16x8.Equal, equalSlice[uint16]) - testUint32x4Compare(t, simd.Uint32x4.Equal, equalSlice[uint32]) - testUint32x8Compare(t, simd.Uint32x8.Equal, equalSlice[uint32]) - testUint64x2Compare(t, simd.Uint64x2.Equal, equalSlice[uint64]) - testUint64x4Compare(t, simd.Uint64x4.Equal, equalSlice[uint64]) - testUint8x16Compare(t, simd.Uint8x16.Equal, equalSlice[uint8]) - testUint8x32Compare(t, simd.Uint8x32.Equal, equalSlice[uint8]) - - if simd.X86.AVX512() { - testFloat32x16Compare(t, simd.Float32x16.Equal, equalSlice[float32]) - testFloat64x8Compare(t, simd.Float64x8.Equal, equalSlice[float64]) - testInt8x64Compare(t, simd.Int8x64.Equal, equalSlice[int8]) - testInt16x32Compare(t, simd.Int16x32.Equal, equalSlice[int16]) - testInt32x16Compare(t, simd.Int32x16.Equal, equalSlice[int32]) - testInt64x8Compare(t, simd.Int64x8.Equal, equalSlice[int64]) - testUint8x64Compare(t, simd.Uint8x64.Equal, equalSlice[uint8]) - testUint16x32Compare(t, simd.Uint16x32.Equal, equalSlice[uint16]) - testUint32x16Compare(t, simd.Uint32x16.Equal, equalSlice[uint32]) - testUint64x8Compare(t, simd.Uint64x8.Equal, equalSlice[uint64]) - } -} - -func TestNotEqual(t *testing.T) { - testFloat32x4Compare(t, simd.Float32x4.NotEqual, notEqualSlice[float32]) - testFloat32x8Compare(t, simd.Float32x8.NotEqual, notEqualSlice[float32]) - testFloat64x2Compare(t, simd.Float64x2.NotEqual, notEqualSlice[float64]) - testFloat64x4Compare(t, simd.Float64x4.NotEqual, notEqualSlice[float64]) - - testInt16x16Compare(t, simd.Int16x16.NotEqual, notEqualSlice[int16]) - testInt16x8Compare(t, simd.Int16x8.NotEqual, notEqualSlice[int16]) - testInt32x4Compare(t, simd.Int32x4.NotEqual, notEqualSlice[int32]) - testInt32x8Compare(t, simd.Int32x8.NotEqual, notEqualSlice[int32]) - testInt64x2Compare(t, simd.Int64x2.NotEqual, notEqualSlice[int64]) - testInt64x4Compare(t, simd.Int64x4.NotEqual, notEqualSlice[int64]) - testInt8x16Compare(t, simd.Int8x16.NotEqual, notEqualSlice[int8]) - testInt8x32Compare(t, simd.Int8x32.NotEqual, notEqualSlice[int8]) - - testUint16x16Compare(t, simd.Uint16x16.NotEqual, notEqualSlice[uint16]) - testUint16x8Compare(t, simd.Uint16x8.NotEqual, notEqualSlice[uint16]) - testUint32x4Compare(t, simd.Uint32x4.NotEqual, notEqualSlice[uint32]) - testUint32x8Compare(t, simd.Uint32x8.NotEqual, notEqualSlice[uint32]) - testUint64x2Compare(t, simd.Uint64x2.NotEqual, notEqualSlice[uint64]) - testUint64x4Compare(t, simd.Uint64x4.NotEqual, notEqualSlice[uint64]) - testUint8x16Compare(t, simd.Uint8x16.NotEqual, notEqualSlice[uint8]) - testUint8x32Compare(t, simd.Uint8x32.NotEqual, notEqualSlice[uint8]) - - if simd.X86.AVX512() { - testFloat32x16Compare(t, simd.Float32x16.NotEqual, notEqualSlice[float32]) - testFloat64x8Compare(t, simd.Float64x8.NotEqual, notEqualSlice[float64]) - testInt8x64Compare(t, simd.Int8x64.NotEqual, notEqualSlice[int8]) - testInt16x32Compare(t, simd.Int16x32.NotEqual, notEqualSlice[int16]) - testInt32x16Compare(t, simd.Int32x16.NotEqual, notEqualSlice[int32]) - testInt64x8Compare(t, simd.Int64x8.NotEqual, notEqualSlice[int64]) - testUint8x64Compare(t, simd.Uint8x64.NotEqual, notEqualSlice[uint8]) - testUint16x32Compare(t, simd.Uint16x32.NotEqual, notEqualSlice[uint16]) - testUint32x16Compare(t, simd.Uint32x16.NotEqual, notEqualSlice[uint32]) - testUint64x8Compare(t, simd.Uint64x8.NotEqual, notEqualSlice[uint64]) - } -} diff --git a/src/simd/internal/simd_test/comparemasked_helpers_test.go b/src/simd/archsimd/internal/simd_test/comparemasked_helpers_test.go rename from src/simd/internal/simd_test/comparemasked_helpers_test.go rename to src/simd/archsimd/internal/simd_test/comparemasked_helpers_test.go index 4c05d10bb320935e6678a6506cf8ce5bd1f24174..7ceee652a9a8a7bc5ad87cf9874df9beb166141b 100644 --- a/src/simd/internal/simd_test/comparemasked_helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/comparemasked_helpers_test.go @@ -9,24 +9,24 @@ package simd_test import ( - "simd" + "simd/archsimd" "testing" ) // testInt8x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt8x16CompareMasked(t *testing.T, - f func(_, _ simd.Int8x16, m simd.Mask8x16) simd.Mask8x16, + f func(_, _ archsimd.Int8x16, m archsimd.Mask8x16) archsimd.Mask8x16, want func(_, _ []int8) []int64) { n := 16 t.Helper() forSlicePairMasked(t, int8s, n, func(x, y []int8, m []bool) bool { t.Helper() - a := simd.LoadInt8x16Slice(x) - b := simd.LoadInt8x16Slice(y) - k := simd.LoadInt8x16Slice(toVect[int8](m)).ToMask() + a := archsimd.LoadInt8x16Slice(x) + b := archsimd.LoadInt8x16Slice(y) + k := archsimd.LoadInt8x16Slice(toVect[int8](m)).ToMask() g := make([]int8, n) - f(a, b, k).AsInt8x16().StoreSlice(g) + f(a, b, k).ToInt8x16().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -40,17 +40,17 @@ // testInt16x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt16x8CompareMasked(t *testing.T, - f func(_, _ simd.Int16x8, m simd.Mask16x8) simd.Mask16x8, + f func(_, _ archsimd.Int16x8, m archsimd.Mask16x8) archsimd.Mask16x8, want func(_, _ []int16) []int64) { n := 8 t.Helper() forSlicePairMasked(t, int16s, n, func(x, y []int16, m []bool) bool { t.Helper() - a := simd.LoadInt16x8Slice(x) - b := simd.LoadInt16x8Slice(y) - k := simd.LoadInt16x8Slice(toVect[int16](m)).ToMask() + a := archsimd.LoadInt16x8Slice(x) + b := archsimd.LoadInt16x8Slice(y) + k := archsimd.LoadInt16x8Slice(toVect[int16](m)).ToMask() g := make([]int16, n) - f(a, b, k).AsInt16x8().StoreSlice(g) + f(a, b, k).ToInt16x8().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -64,17 +64,17 @@ // testInt32x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt32x4CompareMasked(t *testing.T, - f func(_, _ simd.Int32x4, m simd.Mask32x4) simd.Mask32x4, + f func(_, _ archsimd.Int32x4, m archsimd.Mask32x4) archsimd.Mask32x4, want func(_, _ []int32) []int64) { n := 4 t.Helper() forSlicePairMasked(t, int32s, n, func(x, y []int32, m []bool) bool { t.Helper() - a := simd.LoadInt32x4Slice(x) - b := simd.LoadInt32x4Slice(y) - k := simd.LoadInt32x4Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadInt32x4Slice(x) + b := archsimd.LoadInt32x4Slice(y) + k := archsimd.LoadInt32x4Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x4().StoreSlice(g) + f(a, b, k).ToInt32x4().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -88,17 +88,17 @@ // testInt64x2CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt64x2CompareMasked(t *testing.T, - f func(_, _ simd.Int64x2, m simd.Mask64x2) simd.Mask64x2, + f func(_, _ archsimd.Int64x2, m archsimd.Mask64x2) archsimd.Mask64x2, want func(_, _ []int64) []int64) { n := 2 t.Helper() forSlicePairMasked(t, int64s, n, func(x, y []int64, m []bool) bool { t.Helper() - a := simd.LoadInt64x2Slice(x) - b := simd.LoadInt64x2Slice(y) - k := simd.LoadInt64x2Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadInt64x2Slice(x) + b := archsimd.LoadInt64x2Slice(y) + k := archsimd.LoadInt64x2Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x2().StoreSlice(g) + f(a, b, k).ToInt64x2().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -112,17 +112,17 @@ // testUint8x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint8x16CompareMasked(t *testing.T, - f func(_, _ simd.Uint8x16, m simd.Mask8x16) simd.Mask8x16, + f func(_, _ archsimd.Uint8x16, m archsimd.Mask8x16) archsimd.Mask8x16, want func(_, _ []uint8) []int64) { n := 16 t.Helper() forSlicePairMasked(t, uint8s, n, func(x, y []uint8, m []bool) bool { t.Helper() - a := simd.LoadUint8x16Slice(x) - b := simd.LoadUint8x16Slice(y) - k := simd.LoadInt8x16Slice(toVect[int8](m)).ToMask() + a := archsimd.LoadUint8x16Slice(x) + b := archsimd.LoadUint8x16Slice(y) + k := archsimd.LoadInt8x16Slice(toVect[int8](m)).ToMask() g := make([]int8, n) - f(a, b, k).AsInt8x16().StoreSlice(g) + f(a, b, k).ToInt8x16().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -136,17 +136,17 @@ // testUint16x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint16x8CompareMasked(t *testing.T, - f func(_, _ simd.Uint16x8, m simd.Mask16x8) simd.Mask16x8, + f func(_, _ archsimd.Uint16x8, m archsimd.Mask16x8) archsimd.Mask16x8, want func(_, _ []uint16) []int64) { n := 8 t.Helper() forSlicePairMasked(t, uint16s, n, func(x, y []uint16, m []bool) bool { t.Helper() - a := simd.LoadUint16x8Slice(x) - b := simd.LoadUint16x8Slice(y) - k := simd.LoadInt16x8Slice(toVect[int16](m)).ToMask() + a := archsimd.LoadUint16x8Slice(x) + b := archsimd.LoadUint16x8Slice(y) + k := archsimd.LoadInt16x8Slice(toVect[int16](m)).ToMask() g := make([]int16, n) - f(a, b, k).AsInt16x8().StoreSlice(g) + f(a, b, k).ToInt16x8().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -160,17 +160,17 @@ // testUint32x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint32x4CompareMasked(t *testing.T, - f func(_, _ simd.Uint32x4, m simd.Mask32x4) simd.Mask32x4, + f func(_, _ archsimd.Uint32x4, m archsimd.Mask32x4) archsimd.Mask32x4, want func(_, _ []uint32) []int64) { n := 4 t.Helper() forSlicePairMasked(t, uint32s, n, func(x, y []uint32, m []bool) bool { t.Helper() - a := simd.LoadUint32x4Slice(x) - b := simd.LoadUint32x4Slice(y) - k := simd.LoadInt32x4Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadUint32x4Slice(x) + b := archsimd.LoadUint32x4Slice(y) + k := archsimd.LoadInt32x4Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x4().StoreSlice(g) + f(a, b, k).ToInt32x4().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -184,17 +184,17 @@ // testUint64x2CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint64x2CompareMasked(t *testing.T, - f func(_, _ simd.Uint64x2, m simd.Mask64x2) simd.Mask64x2, + f func(_, _ archsimd.Uint64x2, m archsimd.Mask64x2) archsimd.Mask64x2, want func(_, _ []uint64) []int64) { n := 2 t.Helper() forSlicePairMasked(t, uint64s, n, func(x, y []uint64, m []bool) bool { t.Helper() - a := simd.LoadUint64x2Slice(x) - b := simd.LoadUint64x2Slice(y) - k := simd.LoadInt64x2Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadUint64x2Slice(x) + b := archsimd.LoadUint64x2Slice(y) + k := archsimd.LoadInt64x2Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x2().StoreSlice(g) + f(a, b, k).ToInt64x2().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -208,17 +208,17 @@ // testFloat32x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testFloat32x4CompareMasked(t *testing.T, - f func(_, _ simd.Float32x4, m simd.Mask32x4) simd.Mask32x4, + f func(_, _ archsimd.Float32x4, m archsimd.Mask32x4) archsimd.Mask32x4, want func(_, _ []float32) []int64) { n := 4 t.Helper() forSlicePairMasked(t, float32s, n, func(x, y []float32, m []bool) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) - b := simd.LoadFloat32x4Slice(y) - k := simd.LoadInt32x4Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadFloat32x4Slice(x) + b := archsimd.LoadFloat32x4Slice(y) + k := archsimd.LoadInt32x4Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x4().StoreSlice(g) + f(a, b, k).ToInt32x4().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -232,17 +232,17 @@ // testFloat64x2CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testFloat64x2CompareMasked(t *testing.T, - f func(_, _ simd.Float64x2, m simd.Mask64x2) simd.Mask64x2, + f func(_, _ archsimd.Float64x2, m archsimd.Mask64x2) archsimd.Mask64x2, want func(_, _ []float64) []int64) { n := 2 t.Helper() forSlicePairMasked(t, float64s, n, func(x, y []float64, m []bool) bool { t.Helper() - a := simd.LoadFloat64x2Slice(x) - b := simd.LoadFloat64x2Slice(y) - k := simd.LoadInt64x2Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadFloat64x2Slice(x) + b := archsimd.LoadFloat64x2Slice(y) + k := archsimd.LoadInt64x2Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x2().StoreSlice(g) + f(a, b, k).ToInt64x2().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -256,17 +256,17 @@ // testInt8x32CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt8x32CompareMasked(t *testing.T, - f func(_, _ simd.Int8x32, m simd.Mask8x32) simd.Mask8x32, + f func(_, _ archsimd.Int8x32, m archsimd.Mask8x32) archsimd.Mask8x32, want func(_, _ []int8) []int64) { n := 32 t.Helper() forSlicePairMasked(t, int8s, n, func(x, y []int8, m []bool) bool { t.Helper() - a := simd.LoadInt8x32Slice(x) - b := simd.LoadInt8x32Slice(y) - k := simd.LoadInt8x32Slice(toVect[int8](m)).ToMask() + a := archsimd.LoadInt8x32Slice(x) + b := archsimd.LoadInt8x32Slice(y) + k := archsimd.LoadInt8x32Slice(toVect[int8](m)).ToMask() g := make([]int8, n) - f(a, b, k).AsInt8x32().StoreSlice(g) + f(a, b, k).ToInt8x32().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -280,17 +280,17 @@ // testInt16x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt16x16CompareMasked(t *testing.T, - f func(_, _ simd.Int16x16, m simd.Mask16x16) simd.Mask16x16, + f func(_, _ archsimd.Int16x16, m archsimd.Mask16x16) archsimd.Mask16x16, want func(_, _ []int16) []int64) { n := 16 t.Helper() forSlicePairMasked(t, int16s, n, func(x, y []int16, m []bool) bool { t.Helper() - a := simd.LoadInt16x16Slice(x) - b := simd.LoadInt16x16Slice(y) - k := simd.LoadInt16x16Slice(toVect[int16](m)).ToMask() + a := archsimd.LoadInt16x16Slice(x) + b := archsimd.LoadInt16x16Slice(y) + k := archsimd.LoadInt16x16Slice(toVect[int16](m)).ToMask() g := make([]int16, n) - f(a, b, k).AsInt16x16().StoreSlice(g) + f(a, b, k).ToInt16x16().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -304,17 +304,17 @@ // testInt32x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt32x8CompareMasked(t *testing.T, - f func(_, _ simd.Int32x8, m simd.Mask32x8) simd.Mask32x8, + f func(_, _ archsimd.Int32x8, m archsimd.Mask32x8) archsimd.Mask32x8, want func(_, _ []int32) []int64) { n := 8 t.Helper() forSlicePairMasked(t, int32s, n, func(x, y []int32, m []bool) bool { t.Helper() - a := simd.LoadInt32x8Slice(x) - b := simd.LoadInt32x8Slice(y) - k := simd.LoadInt32x8Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadInt32x8Slice(x) + b := archsimd.LoadInt32x8Slice(y) + k := archsimd.LoadInt32x8Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x8().StoreSlice(g) + f(a, b, k).ToInt32x8().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -328,17 +328,17 @@ // testInt64x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt64x4CompareMasked(t *testing.T, - f func(_, _ simd.Int64x4, m simd.Mask64x4) simd.Mask64x4, + f func(_, _ archsimd.Int64x4, m archsimd.Mask64x4) archsimd.Mask64x4, want func(_, _ []int64) []int64) { n := 4 t.Helper() forSlicePairMasked(t, int64s, n, func(x, y []int64, m []bool) bool { t.Helper() - a := simd.LoadInt64x4Slice(x) - b := simd.LoadInt64x4Slice(y) - k := simd.LoadInt64x4Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadInt64x4Slice(x) + b := archsimd.LoadInt64x4Slice(y) + k := archsimd.LoadInt64x4Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x4().StoreSlice(g) + f(a, b, k).ToInt64x4().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -352,17 +352,17 @@ // testUint8x32CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint8x32CompareMasked(t *testing.T, - f func(_, _ simd.Uint8x32, m simd.Mask8x32) simd.Mask8x32, + f func(_, _ archsimd.Uint8x32, m archsimd.Mask8x32) archsimd.Mask8x32, want func(_, _ []uint8) []int64) { n := 32 t.Helper() forSlicePairMasked(t, uint8s, n, func(x, y []uint8, m []bool) bool { t.Helper() - a := simd.LoadUint8x32Slice(x) - b := simd.LoadUint8x32Slice(y) - k := simd.LoadInt8x32Slice(toVect[int8](m)).ToMask() + a := archsimd.LoadUint8x32Slice(x) + b := archsimd.LoadUint8x32Slice(y) + k := archsimd.LoadInt8x32Slice(toVect[int8](m)).ToMask() g := make([]int8, n) - f(a, b, k).AsInt8x32().StoreSlice(g) + f(a, b, k).ToInt8x32().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -376,17 +376,17 @@ // testUint16x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint16x16CompareMasked(t *testing.T, - f func(_, _ simd.Uint16x16, m simd.Mask16x16) simd.Mask16x16, + f func(_, _ archsimd.Uint16x16, m archsimd.Mask16x16) archsimd.Mask16x16, want func(_, _ []uint16) []int64) { n := 16 t.Helper() forSlicePairMasked(t, uint16s, n, func(x, y []uint16, m []bool) bool { t.Helper() - a := simd.LoadUint16x16Slice(x) - b := simd.LoadUint16x16Slice(y) - k := simd.LoadInt16x16Slice(toVect[int16](m)).ToMask() + a := archsimd.LoadUint16x16Slice(x) + b := archsimd.LoadUint16x16Slice(y) + k := archsimd.LoadInt16x16Slice(toVect[int16](m)).ToMask() g := make([]int16, n) - f(a, b, k).AsInt16x16().StoreSlice(g) + f(a, b, k).ToInt16x16().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -400,17 +400,17 @@ // testUint32x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint32x8CompareMasked(t *testing.T, - f func(_, _ simd.Uint32x8, m simd.Mask32x8) simd.Mask32x8, + f func(_, _ archsimd.Uint32x8, m archsimd.Mask32x8) archsimd.Mask32x8, want func(_, _ []uint32) []int64) { n := 8 t.Helper() forSlicePairMasked(t, uint32s, n, func(x, y []uint32, m []bool) bool { t.Helper() - a := simd.LoadUint32x8Slice(x) - b := simd.LoadUint32x8Slice(y) - k := simd.LoadInt32x8Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadUint32x8Slice(x) + b := archsimd.LoadUint32x8Slice(y) + k := archsimd.LoadInt32x8Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x8().StoreSlice(g) + f(a, b, k).ToInt32x8().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -424,17 +424,17 @@ // testUint64x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint64x4CompareMasked(t *testing.T, - f func(_, _ simd.Uint64x4, m simd.Mask64x4) simd.Mask64x4, + f func(_, _ archsimd.Uint64x4, m archsimd.Mask64x4) archsimd.Mask64x4, want func(_, _ []uint64) []int64) { n := 4 t.Helper() forSlicePairMasked(t, uint64s, n, func(x, y []uint64, m []bool) bool { t.Helper() - a := simd.LoadUint64x4Slice(x) - b := simd.LoadUint64x4Slice(y) - k := simd.LoadInt64x4Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadUint64x4Slice(x) + b := archsimd.LoadUint64x4Slice(y) + k := archsimd.LoadInt64x4Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x4().StoreSlice(g) + f(a, b, k).ToInt64x4().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -448,17 +448,17 @@ // testFloat32x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testFloat32x8CompareMasked(t *testing.T, - f func(_, _ simd.Float32x8, m simd.Mask32x8) simd.Mask32x8, + f func(_, _ archsimd.Float32x8, m archsimd.Mask32x8) archsimd.Mask32x8, want func(_, _ []float32) []int64) { n := 8 t.Helper() forSlicePairMasked(t, float32s, n, func(x, y []float32, m []bool) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) - b := simd.LoadFloat32x8Slice(y) - k := simd.LoadInt32x8Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadFloat32x8Slice(x) + b := archsimd.LoadFloat32x8Slice(y) + k := archsimd.LoadInt32x8Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x8().StoreSlice(g) + f(a, b, k).ToInt32x8().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -472,17 +472,17 @@ // testFloat64x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testFloat64x4CompareMasked(t *testing.T, - f func(_, _ simd.Float64x4, m simd.Mask64x4) simd.Mask64x4, + f func(_, _ archsimd.Float64x4, m archsimd.Mask64x4) archsimd.Mask64x4, want func(_, _ []float64) []int64) { n := 4 t.Helper() forSlicePairMasked(t, float64s, n, func(x, y []float64, m []bool) bool { t.Helper() - a := simd.LoadFloat64x4Slice(x) - b := simd.LoadFloat64x4Slice(y) - k := simd.LoadInt64x4Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadFloat64x4Slice(x) + b := archsimd.LoadFloat64x4Slice(y) + k := archsimd.LoadInt64x4Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x4().StoreSlice(g) + f(a, b, k).ToInt64x4().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -496,17 +496,17 @@ // testInt8x64CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt8x64CompareMasked(t *testing.T, - f func(_, _ simd.Int8x64, m simd.Mask8x64) simd.Mask8x64, + f func(_, _ archsimd.Int8x64, m archsimd.Mask8x64) archsimd.Mask8x64, want func(_, _ []int8) []int64) { n := 64 t.Helper() forSlicePairMasked(t, int8s, n, func(x, y []int8, m []bool) bool { t.Helper() - a := simd.LoadInt8x64Slice(x) - b := simd.LoadInt8x64Slice(y) - k := simd.LoadInt8x64Slice(toVect[int8](m)).ToMask() + a := archsimd.LoadInt8x64Slice(x) + b := archsimd.LoadInt8x64Slice(y) + k := archsimd.LoadInt8x64Slice(toVect[int8](m)).ToMask() g := make([]int8, n) - f(a, b, k).AsInt8x64().StoreSlice(g) + f(a, b, k).ToInt8x64().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -520,17 +520,17 @@ // testInt16x32CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt16x32CompareMasked(t *testing.T, - f func(_, _ simd.Int16x32, m simd.Mask16x32) simd.Mask16x32, + f func(_, _ archsimd.Int16x32, m archsimd.Mask16x32) archsimd.Mask16x32, want func(_, _ []int16) []int64) { n := 32 t.Helper() forSlicePairMasked(t, int16s, n, func(x, y []int16, m []bool) bool { t.Helper() - a := simd.LoadInt16x32Slice(x) - b := simd.LoadInt16x32Slice(y) - k := simd.LoadInt16x32Slice(toVect[int16](m)).ToMask() + a := archsimd.LoadInt16x32Slice(x) + b := archsimd.LoadInt16x32Slice(y) + k := archsimd.LoadInt16x32Slice(toVect[int16](m)).ToMask() g := make([]int16, n) - f(a, b, k).AsInt16x32().StoreSlice(g) + f(a, b, k).ToInt16x32().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -544,17 +544,17 @@ // testInt32x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt32x16CompareMasked(t *testing.T, - f func(_, _ simd.Int32x16, m simd.Mask32x16) simd.Mask32x16, + f func(_, _ archsimd.Int32x16, m archsimd.Mask32x16) archsimd.Mask32x16, want func(_, _ []int32) []int64) { n := 16 t.Helper() forSlicePairMasked(t, int32s, n, func(x, y []int32, m []bool) bool { t.Helper() - a := simd.LoadInt32x16Slice(x) - b := simd.LoadInt32x16Slice(y) - k := simd.LoadInt32x16Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadInt32x16Slice(x) + b := archsimd.LoadInt32x16Slice(y) + k := archsimd.LoadInt32x16Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x16().StoreSlice(g) + f(a, b, k).ToInt32x16().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -568,17 +568,17 @@ // testInt64x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testInt64x8CompareMasked(t *testing.T, - f func(_, _ simd.Int64x8, m simd.Mask64x8) simd.Mask64x8, + f func(_, _ archsimd.Int64x8, m archsimd.Mask64x8) archsimd.Mask64x8, want func(_, _ []int64) []int64) { n := 8 t.Helper() forSlicePairMasked(t, int64s, n, func(x, y []int64, m []bool) bool { t.Helper() - a := simd.LoadInt64x8Slice(x) - b := simd.LoadInt64x8Slice(y) - k := simd.LoadInt64x8Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadInt64x8Slice(x) + b := archsimd.LoadInt64x8Slice(y) + k := archsimd.LoadInt64x8Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x8().StoreSlice(g) + f(a, b, k).ToInt64x8().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -592,17 +592,17 @@ // testUint8x64CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint8x64CompareMasked(t *testing.T, - f func(_, _ simd.Uint8x64, m simd.Mask8x64) simd.Mask8x64, + f func(_, _ archsimd.Uint8x64, m archsimd.Mask8x64) archsimd.Mask8x64, want func(_, _ []uint8) []int64) { n := 64 t.Helper() forSlicePairMasked(t, uint8s, n, func(x, y []uint8, m []bool) bool { t.Helper() - a := simd.LoadUint8x64Slice(x) - b := simd.LoadUint8x64Slice(y) - k := simd.LoadInt8x64Slice(toVect[int8](m)).ToMask() + a := archsimd.LoadUint8x64Slice(x) + b := archsimd.LoadUint8x64Slice(y) + k := archsimd.LoadInt8x64Slice(toVect[int8](m)).ToMask() g := make([]int8, n) - f(a, b, k).AsInt8x64().StoreSlice(g) + f(a, b, k).ToInt8x64().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -616,17 +616,17 @@ // testUint16x32CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint16x32CompareMasked(t *testing.T, - f func(_, _ simd.Uint16x32, m simd.Mask16x32) simd.Mask16x32, + f func(_, _ archsimd.Uint16x32, m archsimd.Mask16x32) archsimd.Mask16x32, want func(_, _ []uint16) []int64) { n := 32 t.Helper() forSlicePairMasked(t, uint16s, n, func(x, y []uint16, m []bool) bool { t.Helper() - a := simd.LoadUint16x32Slice(x) - b := simd.LoadUint16x32Slice(y) - k := simd.LoadInt16x32Slice(toVect[int16](m)).ToMask() + a := archsimd.LoadUint16x32Slice(x) + b := archsimd.LoadUint16x32Slice(y) + k := archsimd.LoadInt16x32Slice(toVect[int16](m)).ToMask() g := make([]int16, n) - f(a, b, k).AsInt16x32().StoreSlice(g) + f(a, b, k).ToInt16x32().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -640,17 +640,17 @@ // testUint32x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint32x16CompareMasked(t *testing.T, - f func(_, _ simd.Uint32x16, m simd.Mask32x16) simd.Mask32x16, + f func(_, _ archsimd.Uint32x16, m archsimd.Mask32x16) archsimd.Mask32x16, want func(_, _ []uint32) []int64) { n := 16 t.Helper() forSlicePairMasked(t, uint32s, n, func(x, y []uint32, m []bool) bool { t.Helper() - a := simd.LoadUint32x16Slice(x) - b := simd.LoadUint32x16Slice(y) - k := simd.LoadInt32x16Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadUint32x16Slice(x) + b := archsimd.LoadUint32x16Slice(y) + k := archsimd.LoadInt32x16Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x16().StoreSlice(g) + f(a, b, k).ToInt32x16().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -664,17 +664,17 @@ // testUint64x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testUint64x8CompareMasked(t *testing.T, - f func(_, _ simd.Uint64x8, m simd.Mask64x8) simd.Mask64x8, + f func(_, _ archsimd.Uint64x8, m archsimd.Mask64x8) archsimd.Mask64x8, want func(_, _ []uint64) []int64) { n := 8 t.Helper() forSlicePairMasked(t, uint64s, n, func(x, y []uint64, m []bool) bool { t.Helper() - a := simd.LoadUint64x8Slice(x) - b := simd.LoadUint64x8Slice(y) - k := simd.LoadInt64x8Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadUint64x8Slice(x) + b := archsimd.LoadUint64x8Slice(y) + k := archsimd.LoadInt64x8Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x8().StoreSlice(g) + f(a, b, k).ToInt64x8().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -688,17 +688,17 @@ // testFloat32x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testFloat32x16CompareMasked(t *testing.T, - f func(_, _ simd.Float32x16, m simd.Mask32x16) simd.Mask32x16, + f func(_, _ archsimd.Float32x16, m archsimd.Mask32x16) archsimd.Mask32x16, want func(_, _ []float32) []int64) { n := 16 t.Helper() forSlicePairMasked(t, float32s, n, func(x, y []float32, m []bool) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) - b := simd.LoadFloat32x16Slice(y) - k := simd.LoadInt32x16Slice(toVect[int32](m)).ToMask() + a := archsimd.LoadFloat32x16Slice(x) + b := archsimd.LoadFloat32x16Slice(y) + k := archsimd.LoadInt32x16Slice(toVect[int32](m)).ToMask() g := make([]int32, n) - f(a, b, k).AsInt32x16().StoreSlice(g) + f(a, b, k).ToInt32x16().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { @@ -712,17 +712,17 @@ // testFloat64x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want // The mask is applied to the output of want; anything not in the mask, is zeroed. func testFloat64x8CompareMasked(t *testing.T, - f func(_, _ simd.Float64x8, m simd.Mask64x8) simd.Mask64x8, + f func(_, _ archsimd.Float64x8, m archsimd.Mask64x8) archsimd.Mask64x8, want func(_, _ []float64) []int64) { n := 8 t.Helper() forSlicePairMasked(t, float64s, n, func(x, y []float64, m []bool) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) - b := simd.LoadFloat64x8Slice(y) - k := simd.LoadInt64x8Slice(toVect[int64](m)).ToMask() + a := archsimd.LoadFloat64x8Slice(x) + b := archsimd.LoadFloat64x8Slice(y) + k := archsimd.LoadInt64x8Slice(toVect[int64](m)).ToMask() g := make([]int64, n) - f(a, b, k).AsInt64x8().StoreSlice(g) + f(a, b, k).ToInt64x8().StoreSlice(g) w := want(x, y) for i := range m { if !m[i] { diff --git a/src/simd/internal/simd_test/generate.go b/src/simd/archsimd/internal/simd_test/generate.go rename from src/simd/internal/simd_test/generate.go rename to src/simd/archsimd/internal/simd_test/generate.go diff --git a/src/simd/internal/simd_test/helpers_test.go b/src/simd/archsimd/internal/simd_test/helpers_test.go rename from src/simd/internal/simd_test/helpers_test.go rename to src/simd/archsimd/internal/simd_test/helpers_test.go index 0a246e0d7dda7b9e96dd222b521e738cd1104769..b9d5098dba2a622b94610aafa023a44b55aa15af 100644 --- a/src/simd/internal/simd_test/helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/helpers_test.go @@ -8,7 +8,7 @@ package simd_test import ( "math" - "simd/internal/test_helpers" + "simd/archsimd/internal/test_helpers" "testing" ) diff --git a/src/simd/internal/simd_test/simd_test.go b/src/simd/archsimd/internal/simd_test/simd_test.go rename from src/simd/internal/simd_test/simd_test.go rename to src/simd/archsimd/internal/simd_test/simd_test.go index f51e3dc15f2364987a4675ad2cc9c7b58fd40c95..83925ae789b0f008c93dc267a468edfd1e7d8fbf 100644 --- a/src/simd/internal/simd_test/simd_test.go +++ b/src/simd/archsimd/internal/simd_test/simd_test.go @@ -7,12 +7,22 @@ package simd_test import ( + "fmt" + "os" "reflect" - "simd" + "simd/archsimd" "slices" "testing" ) +func TestMain(m *testing.M) { + if !archsimd.X86.AVX() { + fmt.Fprintln(os.Stderr, "Skipping tests: AVX is not available") + os.Exit(0) + } + os.Exit(m.Run()) +} + var sink any func TestType(t *testing.T) { @@ -23,40 +33,36 @@ // - Type defition is ok // - Type alias is ok // - Type conversion is ok // - Conversion to interface is ok - type alias = simd.Int32x4 - type maskT simd.Mask32x4 + type alias = archsimd.Int32x4 + type maskT archsimd.Mask32x4 type myStruct struct { x alias - y *simd.Int32x4 + y *archsimd.Int32x4 z maskT } vals := [4]int32{1, 2, 3, 4} - v := myStruct{x: simd.LoadInt32x4(&vals)} + v := myStruct{x: archsimd.LoadInt32x4(&vals)} // masking elements 1 and 2. want := []int32{2, 4, 0, 0} - y := simd.LoadInt32x4(&vals) + y := archsimd.LoadInt32x4(&vals) v.y = &y sink = y - if !simd.X86.AVX512GFNI() { + if !archsimd.X86.AVX512GFNI() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } - v.z = maskT(simd.Mask32x4FromBits(0b0011)) - *v.y = v.y.Add(v.x).Masked(simd.Mask32x4(v.z)) + v.z = maskT(archsimd.Mask32x4FromBits(0b0011)) + *v.y = v.y.Add(v.x).Masked(archsimd.Mask32x4(v.z)) got := [4]int32{} v.y.Store(&got) - for i := range 4 { - if want[i] != got[i] { - t.Errorf("Result at %d incorrect: want %d, got %d", i, want[i], got[i]) - } - } + checkSlices(t, got[:], want) } func TestUncomparable(t *testing.T) { // Test that simd vectors are not comparable - var x, y any = simd.LoadUint32x4(&[4]uint32{1, 2, 3, 4}), simd.LoadUint32x4(&[4]uint32{5, 6, 7, 8}) + var x, y any = archsimd.LoadUint32x4(&[4]uint32{1, 2, 3, 4}), archsimd.LoadUint32x4(&[4]uint32{5, 6, 7, 8}) shouldPanic := func(fn func()) { defer func() { if recover() == nil { @@ -73,18 +79,14 @@ // Test that simd intrinsic can be used as a function value. xv := [4]int32{1, 2, 3, 4} yv := [4]int32{5, 6, 7, 8} want := []int32{6, 8, 10, 12} - x := simd.LoadInt32x4(&xv) - y := simd.LoadInt32x4(&yv) - fn := simd.Int32x4.Add + x := archsimd.LoadInt32x4(&xv) + y := archsimd.LoadInt32x4(&yv) + fn := archsimd.Int32x4.Add sink = fn x = fn(x, y) got := [4]int32{} x.Store(&got) - for i := range 4 { - if want[i] != got[i] { - t.Errorf("Result at %d incorrect: want %d, got %d", i, want[i], got[i]) - } - } + checkSlices(t, got[:], want) } func TestReflectMethod(t *testing.T) { @@ -93,30 +95,26 @@ // NOTE: we don't yet support reflect method.Call. xv := [4]int32{1, 2, 3, 4} yv := [4]int32{5, 6, 7, 8} want := []int32{6, 8, 10, 12} - x := simd.LoadInt32x4(&xv) - y := simd.LoadInt32x4(&yv) + x := archsimd.LoadInt32x4(&xv) + y := archsimd.LoadInt32x4(&yv) m, ok := reflect.TypeOf(x).MethodByName("Add") if !ok { t.Fatal("Add method not found") } - fn := m.Func.Interface().(func(x, y simd.Int32x4) simd.Int32x4) + fn := m.Func.Interface().(func(x, y archsimd.Int32x4) archsimd.Int32x4) x = fn(x, y) got := [4]int32{} x.Store(&got) - for i := range 4 { - if want[i] != got[i] { - t.Errorf("Result at %d incorrect: want %d, got %d", i, want[i], got[i]) - } - } + checkSlices(t, got[:], want) } func TestVectorConversion(t *testing.T) { - if !simd.X86.AVX512GFNI() { + if !archsimd.X86.AVX512GFNI() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } xv := [4]int32{1, 2, 3, 4} - x := simd.LoadInt32x4(&xv) + x := archsimd.LoadInt32x4(&xv) xPromoted := x.AsInt64x2() xPromotedDemoted := xPromoted.AsInt32x4() got := [4]int32{} @@ -129,25 +127,21 @@ } } func TestMaskConversion(t *testing.T) { - if !simd.X86.AVX512GFNI() { + if !archsimd.X86.AVX512GFNI() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } - x := simd.LoadInt32x4Slice([]int32{5, 0, 7, 0}) - mask := simd.Int32x4{}.Sub(x).ToMask() - y := simd.LoadInt32x4Slice([]int32{1, 2, 3, 4}).Add(x).Masked(mask) + x := archsimd.LoadInt32x4Slice([]int32{5, 0, 7, 0}) + mask := archsimd.Int32x4{}.Sub(x).ToMask() + y := archsimd.LoadInt32x4Slice([]int32{1, 2, 3, 4}).Add(x).Masked(mask) want := [4]int32{6, 0, 10, 0} got := make([]int32, 4) y.StoreSlice(got) - for i := range 4 { - if want[i] != got[i] { - t.Errorf("Result at %d incorrect: want %d, got %d", i, want[i], got[i]) - } - } + checkSlices(t, got[:], want[:]) } func TestPermute(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } @@ -155,12 +149,8 @@ x := []int64{1, 2, 3, 4, 5, 6, 7, 8} indices := []uint64{7, 6, 5, 4, 3, 2, 1, 0} want := []int64{8, 7, 6, 5, 4, 3, 2, 1} got := make([]int64, 8) - simd.LoadInt64x8Slice(x).Permute(simd.LoadUint64x8Slice(indices)).StoreSlice(got) - for i := range 8 { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } - } + archsimd.LoadInt64x8Slice(x).Permute(archsimd.LoadUint64x8Slice(indices)).StoreSlice(got) + checkSlices(t, got, want) } func TestPermuteOrZero(t *testing.T) { @@ -168,16 +158,12 @@ x := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} indices := []int8{7, 6, 5, 4, 3, 2, 1, 0, -1, 8, -1, 9, -1, 10, -1, 11} want := []uint8{8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 0, 10, 0, 11, 0, 12} got := make([]uint8, len(x)) - simd.LoadUint8x16Slice(x).PermuteOrZero(simd.LoadInt8x16Slice(indices)).StoreSlice(got) - for i := range 8 { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } - } + archsimd.LoadUint8x16Slice(x).PermuteOrZero(archsimd.LoadInt8x16Slice(indices)).StoreSlice(got) + checkSlices(t, got, want) } func TestConcatPermute(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } @@ -186,21 +172,17 @@ y := []int64{-1, -2, -3, -4, -5, -6, -7, -8} indices := []uint64{7 + 8, 6, 5 + 8, 4, 3 + 8, 2, 1 + 8, 0} want := []int64{-8, 7, -6, 5, -4, 3, -2, 1} got := make([]int64, 8) - simd.LoadInt64x8Slice(x).ConcatPermute(simd.LoadInt64x8Slice(y), simd.LoadUint64x8Slice(indices)).StoreSlice(got) - for i := range 8 { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } - } + archsimd.LoadInt64x8Slice(x).ConcatPermute(archsimd.LoadInt64x8Slice(y), archsimd.LoadUint64x8Slice(indices)).StoreSlice(got) + checkSlices(t, got, want) } func TestCompress(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } - v1234 := simd.LoadInt32x4Slice([]int32{1, 2, 3, 4}) - v2400 := v1234.Compress(simd.Mask32x4FromBits(0b1010)) + v1234 := archsimd.LoadInt32x4Slice([]int32{1, 2, 3, 4}) + v2400 := v1234.Compress(archsimd.Mask32x4FromBits(0b1010)) got := make([]int32, 4) v2400.StoreSlice(got) want := []int32{2, 4, 0, 0} @@ -210,12 +192,12 @@ } } func TestExpand(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } - v3400 := simd.LoadInt32x4Slice([]int32{3, 4, 0, 0}) - v2400 := v3400.Expand(simd.Mask32x4FromBits(0b1010)) + v3400 := archsimd.LoadInt32x4Slice([]int32{3, 4, 0, 0}) + v2400 := v3400.Expand(archsimd.Mask32x4FromBits(0b1010)) got := make([]int32, 4) v2400.StoreSlice(got) want := []int32{0, 3, 0, 4} @@ -228,13 +210,13 @@ var testShiftAllVal uint64 = 3 func TestShiftAll(t *testing.T) { got := make([]int32, 4) - simd.LoadInt32x4Slice([]int32{0b11, 0b11, 0b11, 0b11}).ShiftAllLeft(2).StoreSlice(got) + archsimd.LoadInt32x4Slice([]int32{0b11, 0b11, 0b11, 0b11}).ShiftAllLeft(2).StoreSlice(got) for _, v := range got { if v != 0b1100 { t.Errorf("expect 0b1100, got %b", v) } } - simd.LoadInt32x4Slice([]int32{0b11, 0b11, 0b11, 0b11}).ShiftAllLeft(testShiftAllVal).StoreSlice(got) + archsimd.LoadInt32x4Slice([]int32{0b11, 0b11, 0b11, 0b11}).ShiftAllLeft(testShiftAllVal).StoreSlice(got) for _, v := range got { if v != 0b11000 { t.Errorf("expect 0b11000, got %b", v) @@ -245,7 +227,7 @@ func TestSlicesInt8(t *testing.T) { a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - v := simd.LoadInt8x32Slice(a) + v := archsimd.LoadInt8x32Slice(a) b := make([]int8, 32, 32) v.StoreSlice(b) checkSlices(t, a, b) @@ -254,7 +236,7 @@ func TestSlicesInt8SetElem(t *testing.T) { a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - v := simd.LoadInt8x16Slice(a) + v := archsimd.LoadInt8x16Slice(a) v = v.SetElem(3, 13) a[3] = 13 @@ -267,7 +249,7 @@ func TestSlicesInt8GetElem(t *testing.T) { a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - v := simd.LoadInt8x16Slice(a) + v := archsimd.LoadInt8x16Slice(a) e := v.GetElem(2) if e != a[2] { t.Errorf("GetElem(2) = %d != a[2] = %d", e, a[2]) @@ -285,7 +267,7 @@ } }() a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} // TOO SHORT, should panic - v := simd.LoadInt8x32Slice(a) + v := archsimd.LoadInt8x32Slice(a) b := make([]int8, 32, 32) v.StoreSlice(b) checkSlices(t, a, b) @@ -301,7 +283,7 @@ } }() a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} - v := simd.LoadInt8x32Slice(a) + v := archsimd.LoadInt8x32Slice(a) b := make([]int8, 31) // TOO SHORT, should panic v.StoreSlice(b) checkSlices(t, a, b) @@ -309,7 +291,7 @@ } func TestSlicesFloat64(t *testing.T) { a := []float64{1, 2, 3, 4, 5, 6, 7, 8} // too long, should be fine - v := simd.LoadFloat64x4Slice(a) + v := archsimd.LoadFloat64x4Slice(a) b := make([]float64, 4, 4) v.StoreSlice(b) for i := range b { @@ -321,19 +303,19 @@ } // TODO: try to reduce this test to be smaller. func TestMergeLocals(t *testing.T) { - testMergeLocalswrapper(t, simd.Int64x4.Add) + testMergeLocalswrapper(t, archsimd.Int64x4.Add) } //go:noinline func forceSpill() {} -func testMergeLocalswrapper(t *testing.T, op func(simd.Int64x4, simd.Int64x4) simd.Int64x4) { +func testMergeLocalswrapper(t *testing.T, op func(archsimd.Int64x4, archsimd.Int64x4) archsimd.Int64x4) { t.Helper() s0 := []int64{0, 1, 2, 3} s1 := []int64{-1, 0, -1, 0} want := []int64{-1, 1, 1, 3} - v := simd.LoadInt64x4Slice(s0) - m := simd.LoadInt64x4Slice(s1) + v := archsimd.LoadInt64x4Slice(s0) + m := archsimd.LoadInt64x4Slice(s1) forceSpill() got := make([]int64, 4) gotv := op(v, m) @@ -346,14 +328,14 @@ } } func TestBitMaskFromBits(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } results := [2]int64{} want := [2]int64{0, 6} - m := simd.Mask64x2FromBits(0b10) - simd.LoadInt64x2Slice([]int64{1, 2}).Add(simd.LoadInt64x2Slice([]int64{3, 4})).Masked(m).Store(&results) + m := archsimd.Mask64x2FromBits(0b10) + archsimd.LoadInt64x2Slice([]int64{1, 2}).Add(archsimd.LoadInt64x2Slice([]int64{3, 4})).Masked(m).Store(&results) for i := range 2 { if results[i] != want[i] { t.Errorf("Result at %d incorrect: want %v, got %v", i, want[i], results[i]) @@ -364,14 +346,14 @@ var maskForTestBitMaskFromBitsLoad = uint8(0b10) func TestBitMaskFromBitsLoad(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } results := [2]int64{} want := [2]int64{0, 6} - m := simd.Mask64x2FromBits(maskForTestBitMaskFromBitsLoad) - simd.LoadInt64x2Slice([]int64{1, 2}).Add(simd.LoadInt64x2Slice([]int64{3, 4})).Masked(m).Store(&results) + m := archsimd.Mask64x2FromBits(maskForTestBitMaskFromBitsLoad) + archsimd.LoadInt64x2Slice([]int64{1, 2}).Add(archsimd.LoadInt64x2Slice([]int64{3, 4})).Masked(m).Store(&results) for i := range 2 { if results[i] != want[i] { t.Errorf("Result at %d incorrect: want %v, got %v", i, want[i], results[i]) @@ -380,11 +362,11 @@ } } func TestBitMaskToBits(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } - if v := simd.LoadInt16x8Slice([]int16{1, 0, 1, 0, 0, 0, 0, 0}).ToMask().ToBits(); v != 0b101 { + if v := archsimd.LoadInt16x8Slice([]int16{1, 0, 1, 0, 0, 0, 0, 0}).ToMask().ToBits(); v != 0b101 { t.Errorf("Want 0b101, got %b", v) } } @@ -392,11 +374,11 @@ var maskForTestBitMaskFromBitsStore uint8 func TestBitMaskToBitsStore(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } - maskForTestBitMaskFromBitsStore = simd.LoadInt16x8Slice([]int16{1, 0, 1, 0, 0, 0, 0, 0}).ToMask().ToBits() + maskForTestBitMaskFromBitsStore = archsimd.LoadInt16x8Slice([]int16{1, 0, 1, 0, 0, 0, 0, 0}).ToMask().ToBits() if maskForTestBitMaskFromBitsStore != 0b101 { t.Errorf("Want 0b101, got %b", maskForTestBitMaskFromBitsStore) } @@ -406,10 +388,10 @@ func TestMergeFloat(t *testing.T) { k := make([]int64, 4, 4) s := make([]float64, 4, 4) - a := simd.LoadFloat64x4Slice([]float64{1, 2, 3, 4}) - b := simd.LoadFloat64x4Slice([]float64{4, 2, 3, 1}) + a := archsimd.LoadFloat64x4Slice([]float64{1, 2, 3, 4}) + b := archsimd.LoadFloat64x4Slice([]float64{4, 2, 3, 1}) g := a.Greater(b) - g.AsInt64x4().StoreSlice(k) + g.ToInt64x4().StoreSlice(k) c := a.Merge(b, g) c.StoreSlice(s) @@ -419,7 +401,7 @@ checkSlices[float64](t, s, []float64{4, 2, 3, 4}) } func TestMergeFloat512(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } @@ -427,10 +409,10 @@ k := make([]int64, 8, 8) s := make([]float64, 8, 8) - a := simd.LoadFloat64x8Slice([]float64{1, 2, 3, 4, 5, 6, 7, 8}) - b := simd.LoadFloat64x8Slice([]float64{8, 7, 6, 5, 4, 2, 3, 1}) + a := archsimd.LoadFloat64x8Slice([]float64{1, 2, 3, 4, 5, 6, 7, 8}) + b := archsimd.LoadFloat64x8Slice([]float64{8, 7, 6, 5, 4, 2, 3, 1}) g := a.Greater(b) - g.AsInt64x8().StoreSlice(k) + g.ToInt64x8().StoreSlice(k) c := a.Merge(b, g) d := a.Masked(g) @@ -446,12 +428,12 @@ var ro uint8 = 2 func TestRotateAllVariable(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } got := make([]int32, 4) - simd.LoadInt32x4Slice([]int32{0b11, 0b11, 0b11, 0b11}).RotateAllLeft(ro).StoreSlice(got) + archsimd.LoadInt32x4Slice([]int32{0b11, 0b11, 0b11, 0b11}).RotateAllLeft(ro).StoreSlice(got) for _, v := range got { if v != 0b1100 { t.Errorf("Want 0b1100, got %b", v) @@ -461,37 +443,37 @@ } func TestBroadcastUint32x4(t *testing.T) { s := make([]uint32, 4, 4) - simd.BroadcastUint32x4(123456789).StoreSlice(s) + archsimd.BroadcastUint32x4(123456789).StoreSlice(s) checkSlices(t, s, []uint32{123456789, 123456789, 123456789, 123456789}) } func TestBroadcastFloat32x8(t *testing.T) { s := make([]float32, 8, 8) - simd.BroadcastFloat32x8(123456789).StoreSlice(s) + archsimd.BroadcastFloat32x8(123456789).StoreSlice(s) checkSlices(t, s, []float32{123456789, 123456789, 123456789, 123456789, 123456789, 123456789, 123456789, 123456789}) } func TestBroadcastFloat64x2(t *testing.T) { s := make([]float64, 2, 2) - simd.BroadcastFloat64x2(123456789).StoreSlice(s) + archsimd.BroadcastFloat64x2(123456789).StoreSlice(s) checkSlices(t, s, []float64{123456789, 123456789}) } func TestBroadcastUint64x2(t *testing.T) { s := make([]uint64, 2, 2) - simd.BroadcastUint64x2(123456789).StoreSlice(s) + archsimd.BroadcastUint64x2(123456789).StoreSlice(s) checkSlices(t, s, []uint64{123456789, 123456789}) } func TestBroadcastUint16x8(t *testing.T) { s := make([]uint16, 8, 8) - simd.BroadcastUint16x8(12345).StoreSlice(s) + archsimd.BroadcastUint16x8(12345).StoreSlice(s) checkSlices(t, s, []uint16{12345, 12345, 12345, 12345}) } func TestBroadcastInt8x32(t *testing.T) { s := make([]int8, 32, 32) - simd.BroadcastInt8x32(-123).StoreSlice(s) + archsimd.BroadcastInt8x32(-123).StoreSlice(s) checkSlices(t, s, []int8{-123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, -123, @@ -500,7 +482,7 @@ }) } func TestMaskOpt512(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } @@ -508,14 +490,14 @@ k := make([]int64, 8, 8) s := make([]float64, 8, 8) - a := simd.LoadFloat64x8Slice([]float64{2, 0, 2, 0, 2, 0, 2, 0}) - b := simd.LoadFloat64x8Slice([]float64{1, 1, 1, 1, 1, 1, 1, 1}) - c := simd.LoadFloat64x8Slice([]float64{1, 2, 3, 4, 5, 6, 7, 8}) - d := simd.LoadFloat64x8Slice([]float64{2, 4, 6, 8, 10, 12, 14, 16}) + a := archsimd.LoadFloat64x8Slice([]float64{2, 0, 2, 0, 2, 0, 2, 0}) + b := archsimd.LoadFloat64x8Slice([]float64{1, 1, 1, 1, 1, 1, 1, 1}) + c := archsimd.LoadFloat64x8Slice([]float64{1, 2, 3, 4, 5, 6, 7, 8}) + d := archsimd.LoadFloat64x8Slice([]float64{2, 4, 6, 8, 10, 12, 14, 16}) g := a.Greater(b) e := c.Add(d).Masked(g) e.StoreSlice(s) - g.AsInt64x8().StoreSlice(k) + g.ToInt64x8().StoreSlice(k) checkSlices[int64](t, k, []int64{-1, 0, -1, 0, -1, 0, -1, 0}) checkSlices[float64](t, s, []float64{3, 0, 9, 0, 15, 0, 21, 0}) } @@ -524,7 +506,7 @@ // flattenedTranspose tranposes x and y, regarded as a pair of 2x2 // matrices, but then flattens the rows in order, i.e // x: ABCD ==> a: A1B2 // y: 1234 b: C3D4 -func flattenedTranspose(x, y simd.Int32x4) (a, b simd.Int32x4) { +func flattenedTranspose(x, y archsimd.Int32x4) (a, b archsimd.Int32x4) { return x.InterleaveLo(y), x.InterleaveHi(y) } @@ -532,8 +514,8 @@ func TestFlattenedTranspose(t *testing.T) { r := make([]int32, 4, 4) s := make([]int32, 4, 4) - x := simd.LoadInt32x4Slice([]int32{0xA, 0xB, 0xC, 0xD}) - y := simd.LoadInt32x4Slice([]int32{1, 2, 3, 4}) + x := archsimd.LoadInt32x4Slice([]int32{0xA, 0xB, 0xC, 0xD}) + y := archsimd.LoadInt32x4Slice([]int32{1, 2, 3, 4}) a, b := flattenedTranspose(x, y) a.StoreSlice(r) @@ -547,7 +529,7 @@ func TestClearAVXUpperBits(t *testing.T) { // Test that ClearAVXUpperBits is safe even if there are SIMD values // alive (although usually one should not do this). - if !simd.X86.AVX2() { + if !archsimd.X86.AVX2() { t.Skip("Test requires X86.AVX2, not available on this hardware") return } @@ -555,11 +537,11 @@ r := make([]int64, 4) s := make([]int64, 4) - x := simd.LoadInt64x4Slice([]int64{10, 20, 30, 40}) - y := simd.LoadInt64x4Slice([]int64{1, 2, 3, 4}) + x := archsimd.LoadInt64x4Slice([]int64{10, 20, 30, 40}) + y := archsimd.LoadInt64x4Slice([]int64{1, 2, 3, 4}) x.Add(y).StoreSlice(r) - simd.ClearAVXUpperBits() + archsimd.ClearAVXUpperBits() x.Sub(y).StoreSlice(s) checkSlices[int64](t, r, []int64{11, 22, 33, 44}) @@ -567,7 +549,7 @@ checkSlices[int64](t, s, []int64{9, 18, 27, 36}) } func TestLeadingZeros(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } @@ -575,7 +557,7 @@ src := []uint64{0b1111, 0} want := []uint64{60, 64} got := make([]uint64, 2) - simd.LoadUint64x2Slice(src).LeadingZeros().StoreSlice(got) + archsimd.LoadUint64x2Slice(src).LeadingZeros().StoreSlice(got) for i := range 2 { if want[i] != got[i] { t.Errorf("Result incorrect at %d: want %d, got %d", i, want[i], got[i]) @@ -584,8 +566,8 @@ } } func TestIsZero(t *testing.T) { - v1 := simd.LoadUint64x2Slice([]uint64{0, 1}) - v2 := simd.LoadUint64x2Slice([]uint64{0, 0}) + v1 := archsimd.LoadUint64x2Slice([]uint64{0, 1}) + v2 := archsimd.LoadUint64x2Slice([]uint64{0, 0}) if v1.IsZero() { t.Errorf("Result incorrect, want false, got true") } @@ -607,8 +589,8 @@ } } func TestSelect4FromPairConst(t *testing.T) { - x := simd.LoadInt32x4Slice([]int32{0, 1, 2, 3}) - y := simd.LoadInt32x4Slice([]int32{4, 5, 6, 7}) + x := archsimd.LoadInt32x4Slice([]int32{0, 1, 2, 3}) + y := archsimd.LoadInt32x4Slice([]int32{4, 5, 6, 7}) llll := x.SelectFromPair(0, 1, 2, 3, y) hhhh := x.SelectFromPair(4, 5, 6, 7, y) @@ -632,7 +614,7 @@ hllh := x.SelectFromPair(4, 0, 1, 5, y) r := make([]int32, 4, 4) - foo := func(v simd.Int32x4, a, b, c, d int32) { + foo := func(v archsimd.Int32x4, a, b, c, d int32) { v.StoreSlice(r) checkSlices[int32](t, r, []int32{a, b, c, d}) } @@ -659,13 +641,13 @@ foo(hllh, 4, 0, 1, 5) } //go:noinline -func selectFromPairInt32x4(x simd.Int32x4, a, b, c, d uint8, y simd.Int32x4) simd.Int32x4 { +func selectFromPairInt32x4(x archsimd.Int32x4, a, b, c, d uint8, y archsimd.Int32x4) archsimd.Int32x4 { return x.SelectFromPair(a, b, c, d, y) } func TestSelect4FromPairVar(t *testing.T) { - x := simd.LoadInt32x4Slice([]int32{0, 1, 2, 3}) - y := simd.LoadInt32x4Slice([]int32{4, 5, 6, 7}) + x := archsimd.LoadInt32x4Slice([]int32{0, 1, 2, 3}) + y := archsimd.LoadInt32x4Slice([]int32{4, 5, 6, 7}) llll := selectFromPairInt32x4(x, 0, 1, 2, 3, y) hhhh := selectFromPairInt32x4(x, 4, 5, 6, 7, y) @@ -689,7 +671,7 @@ hllh := selectFromPairInt32x4(x, 4, 0, 1, 5, y) r := make([]int32, 4, 4) - foo := func(v simd.Int32x4, a, b, c, d int32) { + foo := func(v archsimd.Int32x4, a, b, c, d int32) { v.StoreSlice(r) checkSlices[int32](t, r, []int32{a, b, c, d}) } @@ -716,8 +698,8 @@ foo(hllh, 4, 0, 1, 5) } func TestSelect4FromPairConstGrouped(t *testing.T) { - x := simd.LoadFloat32x8Slice([]float32{0, 1, 2, 3, 10, 11, 12, 13}) - y := simd.LoadFloat32x8Slice([]float32{4, 5, 6, 7, 14, 15, 16, 17}) + x := archsimd.LoadFloat32x8Slice([]float32{0, 1, 2, 3, 10, 11, 12, 13}) + y := archsimd.LoadFloat32x8Slice([]float32{4, 5, 6, 7, 14, 15, 16, 17}) llll := x.SelectFromPairGrouped(0, 1, 2, 3, y) hhhh := x.SelectFromPairGrouped(4, 5, 6, 7, y) @@ -741,7 +723,7 @@ hllh := x.SelectFromPairGrouped(4, 0, 1, 5, y) r := make([]float32, 8, 8) - foo := func(v simd.Float32x8, a, b, c, d float32) { + foo := func(v archsimd.Float32x8, a, b, c, d float32) { v.StoreSlice(r) checkSlices[float32](t, r, []float32{a, b, c, d, 10 + a, 10 + b, 10 + c, 10 + d}) } @@ -768,12 +750,12 @@ foo(hllh, 4, 0, 1, 5) } func TestSelectFromPairConstGroupedUint32x16(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } - x := simd.LoadUint32x16Slice([]uint32{0, 1, 2, 3, 10, 11, 12, 13, 20, 21, 22, 23, 30, 31, 32, 33}) - y := simd.LoadUint32x16Slice([]uint32{4, 5, 6, 7, 14, 15, 16, 17, 24, 25, 26, 27, 34, 35, 36, 37}) + x := archsimd.LoadUint32x16Slice([]uint32{0, 1, 2, 3, 10, 11, 12, 13, 20, 21, 22, 23, 30, 31, 32, 33}) + y := archsimd.LoadUint32x16Slice([]uint32{4, 5, 6, 7, 14, 15, 16, 17, 24, 25, 26, 27, 34, 35, 36, 37}) llll := x.SelectFromPairGrouped(0, 1, 2, 3, y) hhhh := x.SelectFromPairGrouped(4, 5, 6, 7, y) @@ -797,7 +779,7 @@ hllh := x.SelectFromPairGrouped(4, 0, 1, 5, y) r := make([]uint32, 16, 16) - foo := func(v simd.Uint32x16, a, b, c, d uint32) { + foo := func(v archsimd.Uint32x16, a, b, c, d uint32) { v.StoreSlice(r) checkSlices[uint32](t, r, []uint32{a, b, c, d, 10 + a, 10 + b, 10 + c, 10 + d, @@ -828,8 +810,8 @@ foo(hllh, 4, 0, 1, 5) } func TestSelect128FromPair(t *testing.T) { - x := simd.LoadUint64x4Slice([]uint64{0, 1, 2, 3}) - y := simd.LoadUint64x4Slice([]uint64{4, 5, 6, 7}) + x := archsimd.LoadUint64x4Slice([]uint64{0, 1, 2, 3}) + y := archsimd.LoadUint64x4Slice([]uint64{4, 5, 6, 7}) aa := x.Select128FromPair(0, 0, y) ab := x.Select128FromPair(0, 1, y) @@ -840,7 +822,7 @@ dc := x.Select128FromPair(3, 2, y) r := make([]uint64, 4, 4) - foo := func(v simd.Uint64x4, a, b uint64) { + foo := func(v archsimd.Uint64x4, a, b uint64) { a, b = 2*a, 2*b v.StoreSlice(r) checkSlices[uint64](t, r, []uint64{a, a + 1, b, b + 1}) @@ -855,8 +837,8 @@ foo(dc, 3, 2) } func TestSelect128FromPairError(t *testing.T) { - x := simd.LoadUint64x4Slice([]uint64{0, 1, 2, 3}) - y := simd.LoadUint64x4Slice([]uint64{4, 5, 6, 7}) + x := archsimd.LoadUint64x4Slice([]uint64{0, 1, 2, 3}) + y := archsimd.LoadUint64x4Slice([]uint64{4, 5, 6, 7}) defer func() { if r := recover(); r != nil { @@ -869,13 +851,13 @@ t.Errorf("Should have panicked") } //go:noinline -func select128FromPair(x simd.Uint64x4, lo, hi uint8, y simd.Uint64x4) simd.Uint64x4 { +func select128FromPair(x archsimd.Uint64x4, lo, hi uint8, y archsimd.Uint64x4) archsimd.Uint64x4 { return x.Select128FromPair(lo, hi, y) } func TestSelect128FromPairVar(t *testing.T) { - x := simd.LoadUint64x4Slice([]uint64{0, 1, 2, 3}) - y := simd.LoadUint64x4Slice([]uint64{4, 5, 6, 7}) + x := archsimd.LoadUint64x4Slice([]uint64{0, 1, 2, 3}) + y := archsimd.LoadUint64x4Slice([]uint64{4, 5, 6, 7}) aa := select128FromPair(x, 0, 0, y) ab := select128FromPair(x, 0, 1, y) @@ -886,7 +868,7 @@ dc := select128FromPair(x, 3, 2, y) r := make([]uint64, 4, 4) - foo := func(v simd.Uint64x4, a, b uint64) { + foo := func(v archsimd.Uint64x4, a, b uint64) { a, b = 2*a, 2*b v.StoreSlice(r) checkSlices[uint64](t, r, []uint64{a, a + 1, b, b + 1}) @@ -901,8 +883,8 @@ foo(dc, 3, 2) } func TestSelect2FromPairConst(t *testing.T) { - x := simd.LoadUint64x2Slice([]uint64{0, 1}) - y := simd.LoadUint64x2Slice([]uint64{2, 3}) + x := archsimd.LoadUint64x2Slice([]uint64{0, 1}) + y := archsimd.LoadUint64x2Slice([]uint64{2, 3}) ll := x.SelectFromPair(0, 1, y) hh := x.SelectFromPair(3, 2, y) @@ -911,7 +893,7 @@ hl := x.SelectFromPair(2, 1, y) r := make([]uint64, 2, 2) - foo := func(v simd.Uint64x2, a, b uint64) { + foo := func(v archsimd.Uint64x2, a, b uint64) { v.StoreSlice(r) checkSlices[uint64](t, r, []uint64{a, b}) } @@ -923,8 +905,8 @@ foo(hl, 2, 1) } func TestSelect2FromPairConstGroupedUint(t *testing.T) { - x := simd.LoadUint64x4Slice([]uint64{0, 1, 10, 11}) - y := simd.LoadUint64x4Slice([]uint64{2, 3, 12, 13}) + x := archsimd.LoadUint64x4Slice([]uint64{0, 1, 10, 11}) + y := archsimd.LoadUint64x4Slice([]uint64{2, 3, 12, 13}) ll := x.SelectFromPairGrouped(0, 1, y) hh := x.SelectFromPairGrouped(3, 2, y) @@ -933,7 +915,7 @@ hl := x.SelectFromPairGrouped(2, 1, y) r := make([]uint64, 4, 4) - foo := func(v simd.Uint64x4, a, b uint64) { + foo := func(v archsimd.Uint64x4, a, b uint64) { v.StoreSlice(r) checkSlices[uint64](t, r, []uint64{a, b, a + 10, b + 10}) } @@ -945,8 +927,8 @@ foo(hl, 2, 1) } func TestSelect2FromPairConstGroupedFloat(t *testing.T) { - x := simd.LoadFloat64x4Slice([]float64{0, 1, 10, 11}) - y := simd.LoadFloat64x4Slice([]float64{2, 3, 12, 13}) + x := archsimd.LoadFloat64x4Slice([]float64{0, 1, 10, 11}) + y := archsimd.LoadFloat64x4Slice([]float64{2, 3, 12, 13}) ll := x.SelectFromPairGrouped(0, 1, y) hh := x.SelectFromPairGrouped(3, 2, y) @@ -955,7 +937,7 @@ hl := x.SelectFromPairGrouped(2, 1, y) r := make([]float64, 4, 4) - foo := func(v simd.Float64x4, a, b float64) { + foo := func(v archsimd.Float64x4, a, b float64) { v.StoreSlice(r) checkSlices[float64](t, r, []float64{a, b, a + 10, b + 10}) } @@ -967,8 +949,8 @@ foo(hl, 2, 1) } func TestSelect2FromPairConstGroupedInt(t *testing.T) { - x := simd.LoadInt64x4Slice([]int64{0, 1, 10, 11}) - y := simd.LoadInt64x4Slice([]int64{2, 3, 12, 13}) + x := archsimd.LoadInt64x4Slice([]int64{0, 1, 10, 11}) + y := archsimd.LoadInt64x4Slice([]int64{2, 3, 12, 13}) ll := x.SelectFromPairGrouped(0, 1, y) hh := x.SelectFromPairGrouped(3, 2, y) @@ -977,7 +959,7 @@ hl := x.SelectFromPairGrouped(2, 1, y) r := make([]int64, 4, 4) - foo := func(v simd.Int64x4, a, b int64) { + foo := func(v archsimd.Int64x4, a, b int64) { v.StoreSlice(r) checkSlices[int64](t, r, []int64{a, b, a + 10, b + 10}) } @@ -989,13 +971,13 @@ foo(hl, 2, 1) } func TestSelect2FromPairConstGroupedInt512(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } - x := simd.LoadInt64x8Slice([]int64{0, 1, 10, 11, 20, 21, 30, 31}) - y := simd.LoadInt64x8Slice([]int64{2, 3, 12, 13, 22, 23, 32, 33}) + x := archsimd.LoadInt64x8Slice([]int64{0, 1, 10, 11, 20, 21, 30, 31}) + y := archsimd.LoadInt64x8Slice([]int64{2, 3, 12, 13, 22, 23, 32, 33}) ll := x.SelectFromPairGrouped(0, 1, y) hh := x.SelectFromPairGrouped(3, 2, y) @@ -1004,7 +986,7 @@ hl := x.SelectFromPairGrouped(2, 1, y) r := make([]int64, 8, 8) - foo := func(v simd.Int64x8, a, b int64) { + foo := func(v archsimd.Int64x8, a, b int64) { v.StoreSlice(r) checkSlices[int64](t, r, []int64{a, b, a + 10, b + 10, a + 20, b + 20, a + 30, b + 30}) } @@ -1016,10 +998,10 @@ foo(hl, 2, 1) } func TestString(t *testing.T) { - x := simd.LoadUint32x4Slice([]uint32{0, 1, 2, 3}) - y := simd.LoadInt64x4Slice([]int64{-4, -5, -6, -7}) - z := simd.LoadFloat32x4Slice([]float32{0.5, 1.5, -2.5, 3.5e9}) - w := simd.LoadFloat64x4Slice([]float64{0.5, 1.5, -2.5, 3.5e9}) + x := archsimd.LoadUint32x4Slice([]uint32{0, 1, 2, 3}) + y := archsimd.LoadInt64x4Slice([]int64{-4, -5, -6, -7}) + z := archsimd.LoadFloat32x4Slice([]float32{0.5, 1.5, -2.5, 3.5e9}) + w := archsimd.LoadFloat64x4Slice([]float64{0.5, 1.5, -2.5, 3.5e9}) sx := "{0,1,2,3}" sy := "{-4,-5,-6,-7}" @@ -1051,7 +1033,7 @@ } // applyTo3 returns a 16-element slice of the results of // applying f to the respective elements of vectors x, y, and z. -func applyTo3(x, y, z simd.Int32x16, f func(x, y, z int32) int32) []int32 { +func applyTo3(x, y, z archsimd.Int32x16, f func(x, y, z int32) int32) []int32 { ax, ay, az := a(), a(), a() x.StoreSlice(ax) y.StoreSlice(ay) @@ -1066,7 +1048,7 @@ } // applyTo3 returns a 16-element slice of the results of // applying f to the respective elements of vectors x, y, z, and w. -func applyTo4(x, y, z, w simd.Int32x16, f func(x, y, z, w int32) int32) []int32 { +func applyTo4(x, y, z, w archsimd.Int32x16, f func(x, y, z, w int32) int32) []int32 { ax, ay, az, aw := a(), a(), a(), a() x.StoreSlice(ax) y.StoreSlice(ay) @@ -1081,7 +1063,7 @@ return r } func TestSelectTernOptInt32x16(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } @@ -1091,13 +1073,13 @@ az := []int32{0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1} aw := []int32{0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1} am := []int32{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} - x := simd.LoadInt32x16Slice(ax) - y := simd.LoadInt32x16Slice(ay) - z := simd.LoadInt32x16Slice(az) - w := simd.LoadInt32x16Slice(aw) - m := simd.LoadInt32x16Slice(am) + x := archsimd.LoadInt32x16Slice(ax) + y := archsimd.LoadInt32x16Slice(ay) + z := archsimd.LoadInt32x16Slice(az) + w := archsimd.LoadInt32x16Slice(aw) + m := archsimd.LoadInt32x16Slice(am) - foo := func(v simd.Int32x16, s []int32) { + foo := func(v archsimd.Int32x16, s []int32) { r := make([]int32, 16, 16) v.StoreSlice(r) checkSlices[int32](t, r, s) @@ -1123,13 +1105,13 @@ foo(t2, applyTo3(x, y, z, ft2)) } func TestMaskedMerge(t *testing.T) { - x := simd.LoadInt64x4Slice([]int64{1, 2, 3, 4}) - y := simd.LoadInt64x4Slice([]int64{5, 6, 1, 1}) - z := simd.LoadInt64x4Slice([]int64{-1, -2, -3, -4}) + x := archsimd.LoadInt64x4Slice([]int64{1, 2, 3, 4}) + y := archsimd.LoadInt64x4Slice([]int64{5, 6, 1, 1}) + z := archsimd.LoadInt64x4Slice([]int64{-1, -2, -3, -4}) res := make([]int64, 4) expected := []int64{6, 8, -3, -4} mask := x.Less(y) - if simd.X86.AVX512() { + if archsimd.X86.AVX512() { x.Add(y).Merge(z, mask).StoreSlice(res) } else { x.Add(y).Merge(z, mask).StoreSlice(res) @@ -1142,7 +1124,7 @@ } } func TestDotProductQuadruple(t *testing.T) { - if !simd.X86.AVXVNNI() { + if !archsimd.X86.AVXVNNI() { t.Skip("Test requires X86.AVXVNNI, not available on this hardware") return } @@ -1160,9 +1142,9 @@ zd[i] = 3 wanted1[i] = 30 wanted2[i] = 30 } - x := simd.LoadInt8x16Slice(xd) - y := simd.LoadUint8x16Slice(yd) - z := simd.LoadInt32x4Slice(zd) + x := archsimd.LoadInt8x16Slice(xd) + y := archsimd.LoadUint8x16Slice(yd) + z := archsimd.LoadInt32x4Slice(zd) x.DotProductQuadruple(y).StoreSlice(res1) x.DotProductQuadruple(y).Add(z).StoreSlice(res1) for i := range 4 { @@ -1179,70 +1161,64 @@ func TestPermuteScalars(t *testing.T) { x := []int32{11, 12, 13, 14} want := []int32{12, 13, 14, 11} got := make([]int32, 4) - simd.LoadInt32x4Slice(x).PermuteScalars(1, 2, 3, 0).StoreSlice(got) - for i := range 4 { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } - } + archsimd.LoadInt32x4Slice(x).PermuteScalars(1, 2, 3, 0).StoreSlice(got) + checkSlices(t, got, want) } func TestPermuteScalarsGrouped(t *testing.T) { x := []int32{11, 12, 13, 14, 21, 22, 23, 24} want := []int32{12, 13, 14, 11, 22, 23, 24, 21} got := make([]int32, 8) - simd.LoadInt32x8Slice(x).PermuteScalarsGrouped(1, 2, 3, 0).StoreSlice(got) - for i := range 8 { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } - } + archsimd.LoadInt32x8Slice(x).PermuteScalarsGrouped(1, 2, 3, 0).StoreSlice(got) + checkSlices(t, got, want) } func TestPermuteScalarsHi(t *testing.T) { x := []int16{-1, -2, -3, -4, 11, 12, 13, 14} want := []int16{-1, -2, -3, -4, 12, 13, 14, 11} got := make([]int16, len(x)) - simd.LoadInt16x8Slice(x).PermuteScalarsHi(1, 2, 3, 0).StoreSlice(got) - for i := range got { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } - } + archsimd.LoadInt16x8Slice(x).PermuteScalarsHi(1, 2, 3, 0).StoreSlice(got) + checkSlices(t, got, want) } func TestPermuteScalarsLo(t *testing.T) { x := []int16{11, 12, 13, 14, 4, 5, 6, 7} want := []int16{12, 13, 14, 11, 4, 5, 6, 7} got := make([]int16, len(x)) - simd.LoadInt16x8Slice(x).PermuteScalarsLo(1, 2, 3, 0).StoreSlice(got) - for i := range got { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } - } + archsimd.LoadInt16x8Slice(x).PermuteScalarsLo(1, 2, 3, 0).StoreSlice(got) + checkSlices(t, got, want) } func TestPermuteScalarsHiGrouped(t *testing.T) { x := []int16{-1, -2, -3, -4, 11, 12, 13, 14, -11, -12, -13, -14, 111, 112, 113, 114} want := []int16{-1, -2, -3, -4, 12, 13, 14, 11, -11, -12, -13, -14, 112, 113, 114, 111} got := make([]int16, len(x)) - simd.LoadInt16x16Slice(x).PermuteScalarsHiGrouped(1, 2, 3, 0).StoreSlice(got) - for i := range got { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } - } + archsimd.LoadInt16x16Slice(x).PermuteScalarsHiGrouped(1, 2, 3, 0).StoreSlice(got) + checkSlices(t, got, want) } func TestPermuteScalarsLoGrouped(t *testing.T) { x := []int16{11, 12, 13, 14, 4, 5, 6, 7, 111, 112, 113, 114, 14, 15, 16, 17} want := []int16{12, 13, 14, 11, 4, 5, 6, 7, 112, 113, 114, 111, 14, 15, 16, 17} got := make([]int16, len(x)) - simd.LoadInt16x16Slice(x).PermuteScalarsLoGrouped(1, 2, 3, 0).StoreSlice(got) - for i := range got { - if want[i] != got[i] { - t.Errorf("want and got differ at index %d, want=%d, got=%d", i, want[i], got[i]) - } + archsimd.LoadInt16x16Slice(x).PermuteScalarsLoGrouped(1, 2, 3, 0).StoreSlice(got) + checkSlices(t, got, want) +} + +func TestClMul(t *testing.T) { + var x = archsimd.LoadUint64x2Slice([]uint64{1, 5}) + var y = archsimd.LoadUint64x2Slice([]uint64{3, 9}) + + foo := func(v archsimd.Uint64x2, s []uint64) { + r := make([]uint64, 2, 2) + v.StoreSlice(r) + checkSlices[uint64](t, r, s) } + + foo(x.CarrylessMultiply(0, 0, y), []uint64{3, 0}) + foo(x.CarrylessMultiply(0, 1, y), []uint64{9, 0}) + foo(x.CarrylessMultiply(1, 0, y), []uint64{15, 0}) + foo(x.CarrylessMultiply(1, 1, y), []uint64{45, 0}) + foo(y.CarrylessMultiply(0, 0, y), []uint64{5, 0}) + } diff --git a/src/simd/internal/simd_test/simulation_helpers_test.go b/src/simd/archsimd/internal/simd_test/simulation_helpers_test.go rename from src/simd/internal/simd_test/simulation_helpers_test.go rename to src/simd/archsimd/internal/simd_test/simulation_helpers_test.go diff --git a/src/simd/internal/simd_test/slicepart_test.go b/src/simd/archsimd/internal/simd_test/slicepart_test.go rename from src/simd/internal/simd_test/slicepart_test.go rename to src/simd/archsimd/internal/simd_test/slicepart_test.go index b7a4a4f71b12d0b01266641bc0f8e77bb494545c..9c7805c41510426c316f76aaa998c07d19ae3052 100644 --- a/src/simd/internal/simd_test/slicepart_test.go +++ b/src/simd/archsimd/internal/simd_test/slicepart_test.go @@ -7,13 +7,13 @@ package simd_test import ( - "simd" + "simd/archsimd" "testing" ) func TestSlicePartInt8x16(t *testing.T) { Do(t, 16, func(a, c []int8) { - u := simd.LoadInt8x16SlicePart(a) + u := archsimd.LoadInt8x16SlicePart(a) u.StoreSlice(c) }) } @@ -24,7 +24,7 @@ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} b := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} for i := 32; i >= 0; i-- { - u := simd.LoadInt8x32SlicePart(a[:i]) + u := archsimd.LoadInt8x32SlicePart(a[:i]) c := make([]int8, 32, 32) u.StoreSlice(c) checkSlices(t, c, b) @@ -38,7 +38,7 @@ func TestSlicePartUint8x16(t *testing.T) { a := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} b := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} for i := 16; i >= 0; i-- { - u := simd.LoadUint8x16SlicePart(a[:i]) + u := archsimd.LoadUint8x16SlicePart(a[:i]) c := make([]uint8, 32, 32) u.StoreSlice(c) checkSlices(t, c, b) @@ -54,7 +54,7 @@ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} b := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} for i := 32; i >= 0; i-- { - u := simd.LoadUint8x32SlicePart(a[:i]) + u := archsimd.LoadUint8x32SlicePart(a[:i]) c := make([]uint8, 32, 32) u.StoreSlice(c) checkSlices(t, c, b) @@ -68,7 +68,7 @@ func TestSlicePartInt16x8(t *testing.T) { a := []int16{1, 2, 3, 4, 5, 6, 7, 8} b := []int16{1, 2, 3, 4, 5, 6, 7, 8} for i := 8; i >= 0; i-- { - u := simd.LoadInt16x8SlicePart(a[:i]) + u := archsimd.LoadInt16x8SlicePart(a[:i]) c := make([]int16, 16, 16) u.StoreSlice(c) checkSlices(t, c, b) @@ -82,7 +82,7 @@ func TestSlicePartInt16x16(t *testing.T) { a := []int16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} b := []int16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} for i := 16; i >= 0; i-- { - u := simd.LoadInt16x16SlicePart(a[:i]) + u := archsimd.LoadInt16x16SlicePart(a[:i]) c := make([]int16, 16, 16) u.StoreSlice(c) checkSlices(t, c, b) @@ -96,7 +96,7 @@ func TestSlicesPartStoreInt8x16(t *testing.T) { a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} b := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} for i := 16; i >= 0; i-- { - v := simd.LoadInt8x16Slice(a) + v := archsimd.LoadInt8x16Slice(a) c := make([]int8, 32, 32) v.StoreSlicePart(c[:i]) checkSlices(t, c, b) @@ -110,7 +110,7 @@ func TestSlicesPartStoreInt16x8(t *testing.T) { a := []int16{1, 2, 3, 4, 5, 6, 7, 8} b := []int16{1, 2, 3, 4, 5, 6, 7, 8} for i := 8; i >= 0; i-- { - v := simd.LoadInt16x8Slice(a) + v := archsimd.LoadInt16x8Slice(a) c := make([]int16, 32, 32) v.StoreSlicePart(c[:i]) checkSlices(t, c, b) @@ -124,7 +124,7 @@ func TestSlicesPartStoreInt16x16(t *testing.T) { a := []int16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} b := []int16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} for i := 16; i >= 0; i-- { - v := simd.LoadInt16x16Slice(a) + v := archsimd.LoadInt16x16Slice(a) c := make([]int16, 32, 32) v.StoreSlicePart(c[:i]) checkSlices(t, c, b) @@ -138,7 +138,7 @@ func TestSlicesPartStoreUint8x16(t *testing.T) { a := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} b := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} for i := 16; i >= 0; i-- { - v := simd.LoadUint8x16Slice(a) + v := archsimd.LoadUint8x16Slice(a) c := make([]uint8, 32, 32) v.StoreSlicePart(c[:i]) checkSlices(t, c, b) @@ -152,7 +152,7 @@ func TestSlicesPartStoreUint16x16(t *testing.T) { a := []uint16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} b := []uint16{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} for i := 16; i >= 0; i-- { - v := simd.LoadUint16x16Slice(a) + v := archsimd.LoadUint16x16Slice(a) c := make([]uint16, 32, 32) v.StoreSlicePart(c[:i]) checkSlices(t, c, b) @@ -168,7 +168,7 @@ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} b := []uint8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32} for i := 32; i >= 0; i-- { - v := simd.LoadUint8x32Slice(a) + v := archsimd.LoadUint8x32Slice(a) c := make([]uint8, 32, 32) v.StoreSlicePart(c[:i]) checkSlices(t, c, b) @@ -187,7 +187,7 @@ for i := range a { // Test the load first // e is a partial slice. e := a[i:] - v := simd.LoadInt32x4SlicePart(e) + v := archsimd.LoadInt32x4SlicePart(e) // d contains what a ought to contain d := make([]int32, L) for j := 0; j < len(e) && j < len(d); j++ { @@ -228,7 +228,7 @@ for i := range a { // Test the load first // e is a partial slice. e := a[i:] - v := simd.LoadUint64x4SlicePart(e) + v := archsimd.LoadUint64x4SlicePart(e) // d contains what a ought to contain d := make([]uint64, L) for j := 0; j < len(e) && j < len(d); j++ { @@ -269,7 +269,7 @@ for i := range a { // Test the load first // e is a partial slice. e := a[i:] - v := simd.LoadFloat64x2SlicePart(e) + v := archsimd.LoadFloat64x2SlicePart(e) // d contains what a ought to contain d := make([]float64, L) for j := 0; j < len(e) && j < len(d); j++ { @@ -310,7 +310,7 @@ for i := range a { // Test the load first // e is a partial slice. e := a[i:] - v := simd.LoadFloat32x8SlicePart(e) + v := archsimd.LoadFloat32x8SlicePart(e) // d contains what a ought to contain d := make([]float32, L) for j := 0; j < len(e) && j < len(d); j++ { @@ -345,7 +345,7 @@ // 512-bit load func TestSlicePartInt64(t *testing.T) { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { t.Skip("Test requires X86.AVX512, not available on this hardware") return } @@ -357,7 +357,7 @@ for i := range a { // Test the load first // e is a partial slice. e := a[i:] - v := simd.LoadInt64x8SlicePart(e) + v := archsimd.LoadInt64x8SlicePart(e) // d contains what a ought to contain d := make([]int64, L) for j := 0; j < len(e) && j < len(d); j++ { diff --git a/src/simd/internal/simd_test/ternary_helpers_test.go b/src/simd/archsimd/internal/simd_test/ternary_helpers_test.go rename from src/simd/internal/simd_test/ternary_helpers_test.go rename to src/simd/archsimd/internal/simd_test/ternary_helpers_test.go index 401270c7bdcc8d271edee96075310a6c25d9c76a..c37f9ef0ca78ad51ffcde28981e16dd2b2f6cb31 100644 --- a/src/simd/internal/simd_test/ternary_helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/ternary_helpers_test.go @@ -9,19 +9,19 @@ package simd_test import ( - "simd" + "simd/archsimd" "testing" ) // testInt8x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt8x16Ternary(t *testing.T, f func(_, _, _ simd.Int8x16) simd.Int8x16, want func(_, _, _ []int8) []int8) { +func testInt8x16Ternary(t *testing.T, f func(_, _, _ archsimd.Int8x16) archsimd.Int8x16, want func(_, _, _ []int8) []int8) { n := 16 t.Helper() forSliceTriple(t, int8s, n, func(x, y, z []int8) bool { t.Helper() - a := simd.LoadInt8x16Slice(x) - b := simd.LoadInt8x16Slice(y) - c := simd.LoadInt8x16Slice(z) + a := archsimd.LoadInt8x16Slice(x) + b := archsimd.LoadInt8x16Slice(y) + c := archsimd.LoadInt8x16Slice(z) g := make([]int8, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -30,14 +30,14 @@ }) } // testInt16x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt16x8Ternary(t *testing.T, f func(_, _, _ simd.Int16x8) simd.Int16x8, want func(_, _, _ []int16) []int16) { +func testInt16x8Ternary(t *testing.T, f func(_, _, _ archsimd.Int16x8) archsimd.Int16x8, want func(_, _, _ []int16) []int16) { n := 8 t.Helper() forSliceTriple(t, int16s, n, func(x, y, z []int16) bool { t.Helper() - a := simd.LoadInt16x8Slice(x) - b := simd.LoadInt16x8Slice(y) - c := simd.LoadInt16x8Slice(z) + a := archsimd.LoadInt16x8Slice(x) + b := archsimd.LoadInt16x8Slice(y) + c := archsimd.LoadInt16x8Slice(z) g := make([]int16, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -46,14 +46,14 @@ }) } // testInt32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt32x4Ternary(t *testing.T, f func(_, _, _ simd.Int32x4) simd.Int32x4, want func(_, _, _ []int32) []int32) { +func testInt32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Int32x4) archsimd.Int32x4, want func(_, _, _ []int32) []int32) { n := 4 t.Helper() forSliceTriple(t, int32s, n, func(x, y, z []int32) bool { t.Helper() - a := simd.LoadInt32x4Slice(x) - b := simd.LoadInt32x4Slice(y) - c := simd.LoadInt32x4Slice(z) + a := archsimd.LoadInt32x4Slice(x) + b := archsimd.LoadInt32x4Slice(y) + c := archsimd.LoadInt32x4Slice(z) g := make([]int32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -62,14 +62,14 @@ }) } // testInt64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt64x2Ternary(t *testing.T, f func(_, _, _ simd.Int64x2) simd.Int64x2, want func(_, _, _ []int64) []int64) { +func testInt64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Int64x2) archsimd.Int64x2, want func(_, _, _ []int64) []int64) { n := 2 t.Helper() forSliceTriple(t, int64s, n, func(x, y, z []int64) bool { t.Helper() - a := simd.LoadInt64x2Slice(x) - b := simd.LoadInt64x2Slice(y) - c := simd.LoadInt64x2Slice(z) + a := archsimd.LoadInt64x2Slice(x) + b := archsimd.LoadInt64x2Slice(y) + c := archsimd.LoadInt64x2Slice(z) g := make([]int64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -78,14 +78,14 @@ }) } // testUint8x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint8x16Ternary(t *testing.T, f func(_, _, _ simd.Uint8x16) simd.Uint8x16, want func(_, _, _ []uint8) []uint8) { +func testUint8x16Ternary(t *testing.T, f func(_, _, _ archsimd.Uint8x16) archsimd.Uint8x16, want func(_, _, _ []uint8) []uint8) { n := 16 t.Helper() forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool { t.Helper() - a := simd.LoadUint8x16Slice(x) - b := simd.LoadUint8x16Slice(y) - c := simd.LoadUint8x16Slice(z) + a := archsimd.LoadUint8x16Slice(x) + b := archsimd.LoadUint8x16Slice(y) + c := archsimd.LoadUint8x16Slice(z) g := make([]uint8, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -94,14 +94,14 @@ }) } // testUint16x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint16x8Ternary(t *testing.T, f func(_, _, _ simd.Uint16x8) simd.Uint16x8, want func(_, _, _ []uint16) []uint16) { +func testUint16x8Ternary(t *testing.T, f func(_, _, _ archsimd.Uint16x8) archsimd.Uint16x8, want func(_, _, _ []uint16) []uint16) { n := 8 t.Helper() forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool { t.Helper() - a := simd.LoadUint16x8Slice(x) - b := simd.LoadUint16x8Slice(y) - c := simd.LoadUint16x8Slice(z) + a := archsimd.LoadUint16x8Slice(x) + b := archsimd.LoadUint16x8Slice(y) + c := archsimd.LoadUint16x8Slice(z) g := make([]uint16, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -110,14 +110,14 @@ }) } // testUint32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint32x4Ternary(t *testing.T, f func(_, _, _ simd.Uint32x4) simd.Uint32x4, want func(_, _, _ []uint32) []uint32) { +func testUint32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Uint32x4) archsimd.Uint32x4, want func(_, _, _ []uint32) []uint32) { n := 4 t.Helper() forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool { t.Helper() - a := simd.LoadUint32x4Slice(x) - b := simd.LoadUint32x4Slice(y) - c := simd.LoadUint32x4Slice(z) + a := archsimd.LoadUint32x4Slice(x) + b := archsimd.LoadUint32x4Slice(y) + c := archsimd.LoadUint32x4Slice(z) g := make([]uint32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -126,14 +126,14 @@ }) } // testUint64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint64x2Ternary(t *testing.T, f func(_, _, _ simd.Uint64x2) simd.Uint64x2, want func(_, _, _ []uint64) []uint64) { +func testUint64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Uint64x2) archsimd.Uint64x2, want func(_, _, _ []uint64) []uint64) { n := 2 t.Helper() forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool { t.Helper() - a := simd.LoadUint64x2Slice(x) - b := simd.LoadUint64x2Slice(y) - c := simd.LoadUint64x2Slice(z) + a := archsimd.LoadUint64x2Slice(x) + b := archsimd.LoadUint64x2Slice(y) + c := archsimd.LoadUint64x2Slice(z) g := make([]uint64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -142,14 +142,14 @@ }) } // testFloat32x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat32x4Ternary(t *testing.T, f func(_, _, _ simd.Float32x4) simd.Float32x4, want func(_, _, _ []float32) []float32) { +func testFloat32x4Ternary(t *testing.T, f func(_, _, _ archsimd.Float32x4) archsimd.Float32x4, want func(_, _, _ []float32) []float32) { n := 4 t.Helper() forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) - b := simd.LoadFloat32x4Slice(y) - c := simd.LoadFloat32x4Slice(z) + a := archsimd.LoadFloat32x4Slice(x) + b := archsimd.LoadFloat32x4Slice(y) + c := archsimd.LoadFloat32x4Slice(z) g := make([]float32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -158,14 +158,14 @@ }) } // testFloat64x2Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat64x2Ternary(t *testing.T, f func(_, _, _ simd.Float64x2) simd.Float64x2, want func(_, _, _ []float64) []float64) { +func testFloat64x2Ternary(t *testing.T, f func(_, _, _ archsimd.Float64x2) archsimd.Float64x2, want func(_, _, _ []float64) []float64) { n := 2 t.Helper() forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { t.Helper() - a := simd.LoadFloat64x2Slice(x) - b := simd.LoadFloat64x2Slice(y) - c := simd.LoadFloat64x2Slice(z) + a := archsimd.LoadFloat64x2Slice(x) + b := archsimd.LoadFloat64x2Slice(y) + c := archsimd.LoadFloat64x2Slice(z) g := make([]float64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -174,14 +174,14 @@ }) } // testInt8x32Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt8x32Ternary(t *testing.T, f func(_, _, _ simd.Int8x32) simd.Int8x32, want func(_, _, _ []int8) []int8) { +func testInt8x32Ternary(t *testing.T, f func(_, _, _ archsimd.Int8x32) archsimd.Int8x32, want func(_, _, _ []int8) []int8) { n := 32 t.Helper() forSliceTriple(t, int8s, n, func(x, y, z []int8) bool { t.Helper() - a := simd.LoadInt8x32Slice(x) - b := simd.LoadInt8x32Slice(y) - c := simd.LoadInt8x32Slice(z) + a := archsimd.LoadInt8x32Slice(x) + b := archsimd.LoadInt8x32Slice(y) + c := archsimd.LoadInt8x32Slice(z) g := make([]int8, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -190,14 +190,14 @@ }) } // testInt16x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt16x16Ternary(t *testing.T, f func(_, _, _ simd.Int16x16) simd.Int16x16, want func(_, _, _ []int16) []int16) { +func testInt16x16Ternary(t *testing.T, f func(_, _, _ archsimd.Int16x16) archsimd.Int16x16, want func(_, _, _ []int16) []int16) { n := 16 t.Helper() forSliceTriple(t, int16s, n, func(x, y, z []int16) bool { t.Helper() - a := simd.LoadInt16x16Slice(x) - b := simd.LoadInt16x16Slice(y) - c := simd.LoadInt16x16Slice(z) + a := archsimd.LoadInt16x16Slice(x) + b := archsimd.LoadInt16x16Slice(y) + c := archsimd.LoadInt16x16Slice(z) g := make([]int16, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -206,14 +206,14 @@ }) } // testInt32x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt32x8Ternary(t *testing.T, f func(_, _, _ simd.Int32x8) simd.Int32x8, want func(_, _, _ []int32) []int32) { +func testInt32x8Ternary(t *testing.T, f func(_, _, _ archsimd.Int32x8) archsimd.Int32x8, want func(_, _, _ []int32) []int32) { n := 8 t.Helper() forSliceTriple(t, int32s, n, func(x, y, z []int32) bool { t.Helper() - a := simd.LoadInt32x8Slice(x) - b := simd.LoadInt32x8Slice(y) - c := simd.LoadInt32x8Slice(z) + a := archsimd.LoadInt32x8Slice(x) + b := archsimd.LoadInt32x8Slice(y) + c := archsimd.LoadInt32x8Slice(z) g := make([]int32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -222,14 +222,14 @@ }) } // testInt64x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt64x4Ternary(t *testing.T, f func(_, _, _ simd.Int64x4) simd.Int64x4, want func(_, _, _ []int64) []int64) { +func testInt64x4Ternary(t *testing.T, f func(_, _, _ archsimd.Int64x4) archsimd.Int64x4, want func(_, _, _ []int64) []int64) { n := 4 t.Helper() forSliceTriple(t, int64s, n, func(x, y, z []int64) bool { t.Helper() - a := simd.LoadInt64x4Slice(x) - b := simd.LoadInt64x4Slice(y) - c := simd.LoadInt64x4Slice(z) + a := archsimd.LoadInt64x4Slice(x) + b := archsimd.LoadInt64x4Slice(y) + c := archsimd.LoadInt64x4Slice(z) g := make([]int64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -238,14 +238,14 @@ }) } // testUint8x32Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint8x32Ternary(t *testing.T, f func(_, _, _ simd.Uint8x32) simd.Uint8x32, want func(_, _, _ []uint8) []uint8) { +func testUint8x32Ternary(t *testing.T, f func(_, _, _ archsimd.Uint8x32) archsimd.Uint8x32, want func(_, _, _ []uint8) []uint8) { n := 32 t.Helper() forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool { t.Helper() - a := simd.LoadUint8x32Slice(x) - b := simd.LoadUint8x32Slice(y) - c := simd.LoadUint8x32Slice(z) + a := archsimd.LoadUint8x32Slice(x) + b := archsimd.LoadUint8x32Slice(y) + c := archsimd.LoadUint8x32Slice(z) g := make([]uint8, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -254,14 +254,14 @@ }) } // testUint16x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint16x16Ternary(t *testing.T, f func(_, _, _ simd.Uint16x16) simd.Uint16x16, want func(_, _, _ []uint16) []uint16) { +func testUint16x16Ternary(t *testing.T, f func(_, _, _ archsimd.Uint16x16) archsimd.Uint16x16, want func(_, _, _ []uint16) []uint16) { n := 16 t.Helper() forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool { t.Helper() - a := simd.LoadUint16x16Slice(x) - b := simd.LoadUint16x16Slice(y) - c := simd.LoadUint16x16Slice(z) + a := archsimd.LoadUint16x16Slice(x) + b := archsimd.LoadUint16x16Slice(y) + c := archsimd.LoadUint16x16Slice(z) g := make([]uint16, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -270,14 +270,14 @@ }) } // testUint32x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint32x8Ternary(t *testing.T, f func(_, _, _ simd.Uint32x8) simd.Uint32x8, want func(_, _, _ []uint32) []uint32) { +func testUint32x8Ternary(t *testing.T, f func(_, _, _ archsimd.Uint32x8) archsimd.Uint32x8, want func(_, _, _ []uint32) []uint32) { n := 8 t.Helper() forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool { t.Helper() - a := simd.LoadUint32x8Slice(x) - b := simd.LoadUint32x8Slice(y) - c := simd.LoadUint32x8Slice(z) + a := archsimd.LoadUint32x8Slice(x) + b := archsimd.LoadUint32x8Slice(y) + c := archsimd.LoadUint32x8Slice(z) g := make([]uint32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -286,14 +286,14 @@ }) } // testUint64x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint64x4Ternary(t *testing.T, f func(_, _, _ simd.Uint64x4) simd.Uint64x4, want func(_, _, _ []uint64) []uint64) { +func testUint64x4Ternary(t *testing.T, f func(_, _, _ archsimd.Uint64x4) archsimd.Uint64x4, want func(_, _, _ []uint64) []uint64) { n := 4 t.Helper() forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool { t.Helper() - a := simd.LoadUint64x4Slice(x) - b := simd.LoadUint64x4Slice(y) - c := simd.LoadUint64x4Slice(z) + a := archsimd.LoadUint64x4Slice(x) + b := archsimd.LoadUint64x4Slice(y) + c := archsimd.LoadUint64x4Slice(z) g := make([]uint64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -302,14 +302,14 @@ }) } // testFloat32x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat32x8Ternary(t *testing.T, f func(_, _, _ simd.Float32x8) simd.Float32x8, want func(_, _, _ []float32) []float32) { +func testFloat32x8Ternary(t *testing.T, f func(_, _, _ archsimd.Float32x8) archsimd.Float32x8, want func(_, _, _ []float32) []float32) { n := 8 t.Helper() forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) - b := simd.LoadFloat32x8Slice(y) - c := simd.LoadFloat32x8Slice(z) + a := archsimd.LoadFloat32x8Slice(x) + b := archsimd.LoadFloat32x8Slice(y) + c := archsimd.LoadFloat32x8Slice(z) g := make([]float32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -318,14 +318,14 @@ }) } // testFloat64x4Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat64x4Ternary(t *testing.T, f func(_, _, _ simd.Float64x4) simd.Float64x4, want func(_, _, _ []float64) []float64) { +func testFloat64x4Ternary(t *testing.T, f func(_, _, _ archsimd.Float64x4) archsimd.Float64x4, want func(_, _, _ []float64) []float64) { n := 4 t.Helper() forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { t.Helper() - a := simd.LoadFloat64x4Slice(x) - b := simd.LoadFloat64x4Slice(y) - c := simd.LoadFloat64x4Slice(z) + a := archsimd.LoadFloat64x4Slice(x) + b := archsimd.LoadFloat64x4Slice(y) + c := archsimd.LoadFloat64x4Slice(z) g := make([]float64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -334,14 +334,14 @@ }) } // testInt8x64Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt8x64Ternary(t *testing.T, f func(_, _, _ simd.Int8x64) simd.Int8x64, want func(_, _, _ []int8) []int8) { +func testInt8x64Ternary(t *testing.T, f func(_, _, _ archsimd.Int8x64) archsimd.Int8x64, want func(_, _, _ []int8) []int8) { n := 64 t.Helper() forSliceTriple(t, int8s, n, func(x, y, z []int8) bool { t.Helper() - a := simd.LoadInt8x64Slice(x) - b := simd.LoadInt8x64Slice(y) - c := simd.LoadInt8x64Slice(z) + a := archsimd.LoadInt8x64Slice(x) + b := archsimd.LoadInt8x64Slice(y) + c := archsimd.LoadInt8x64Slice(z) g := make([]int8, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -350,14 +350,14 @@ }) } // testInt16x32Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt16x32Ternary(t *testing.T, f func(_, _, _ simd.Int16x32) simd.Int16x32, want func(_, _, _ []int16) []int16) { +func testInt16x32Ternary(t *testing.T, f func(_, _, _ archsimd.Int16x32) archsimd.Int16x32, want func(_, _, _ []int16) []int16) { n := 32 t.Helper() forSliceTriple(t, int16s, n, func(x, y, z []int16) bool { t.Helper() - a := simd.LoadInt16x32Slice(x) - b := simd.LoadInt16x32Slice(y) - c := simd.LoadInt16x32Slice(z) + a := archsimd.LoadInt16x32Slice(x) + b := archsimd.LoadInt16x32Slice(y) + c := archsimd.LoadInt16x32Slice(z) g := make([]int16, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -366,14 +366,14 @@ }) } // testInt32x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt32x16Ternary(t *testing.T, f func(_, _, _ simd.Int32x16) simd.Int32x16, want func(_, _, _ []int32) []int32) { +func testInt32x16Ternary(t *testing.T, f func(_, _, _ archsimd.Int32x16) archsimd.Int32x16, want func(_, _, _ []int32) []int32) { n := 16 t.Helper() forSliceTriple(t, int32s, n, func(x, y, z []int32) bool { t.Helper() - a := simd.LoadInt32x16Slice(x) - b := simd.LoadInt32x16Slice(y) - c := simd.LoadInt32x16Slice(z) + a := archsimd.LoadInt32x16Slice(x) + b := archsimd.LoadInt32x16Slice(y) + c := archsimd.LoadInt32x16Slice(z) g := make([]int32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -382,14 +382,14 @@ }) } // testInt64x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testInt64x8Ternary(t *testing.T, f func(_, _, _ simd.Int64x8) simd.Int64x8, want func(_, _, _ []int64) []int64) { +func testInt64x8Ternary(t *testing.T, f func(_, _, _ archsimd.Int64x8) archsimd.Int64x8, want func(_, _, _ []int64) []int64) { n := 8 t.Helper() forSliceTriple(t, int64s, n, func(x, y, z []int64) bool { t.Helper() - a := simd.LoadInt64x8Slice(x) - b := simd.LoadInt64x8Slice(y) - c := simd.LoadInt64x8Slice(z) + a := archsimd.LoadInt64x8Slice(x) + b := archsimd.LoadInt64x8Slice(y) + c := archsimd.LoadInt64x8Slice(z) g := make([]int64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -398,14 +398,14 @@ }) } // testUint8x64Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint8x64Ternary(t *testing.T, f func(_, _, _ simd.Uint8x64) simd.Uint8x64, want func(_, _, _ []uint8) []uint8) { +func testUint8x64Ternary(t *testing.T, f func(_, _, _ archsimd.Uint8x64) archsimd.Uint8x64, want func(_, _, _ []uint8) []uint8) { n := 64 t.Helper() forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool { t.Helper() - a := simd.LoadUint8x64Slice(x) - b := simd.LoadUint8x64Slice(y) - c := simd.LoadUint8x64Slice(z) + a := archsimd.LoadUint8x64Slice(x) + b := archsimd.LoadUint8x64Slice(y) + c := archsimd.LoadUint8x64Slice(z) g := make([]uint8, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -414,14 +414,14 @@ }) } // testUint16x32Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint16x32Ternary(t *testing.T, f func(_, _, _ simd.Uint16x32) simd.Uint16x32, want func(_, _, _ []uint16) []uint16) { +func testUint16x32Ternary(t *testing.T, f func(_, _, _ archsimd.Uint16x32) archsimd.Uint16x32, want func(_, _, _ []uint16) []uint16) { n := 32 t.Helper() forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool { t.Helper() - a := simd.LoadUint16x32Slice(x) - b := simd.LoadUint16x32Slice(y) - c := simd.LoadUint16x32Slice(z) + a := archsimd.LoadUint16x32Slice(x) + b := archsimd.LoadUint16x32Slice(y) + c := archsimd.LoadUint16x32Slice(z) g := make([]uint16, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -430,14 +430,14 @@ }) } // testUint32x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint32x16Ternary(t *testing.T, f func(_, _, _ simd.Uint32x16) simd.Uint32x16, want func(_, _, _ []uint32) []uint32) { +func testUint32x16Ternary(t *testing.T, f func(_, _, _ archsimd.Uint32x16) archsimd.Uint32x16, want func(_, _, _ []uint32) []uint32) { n := 16 t.Helper() forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool { t.Helper() - a := simd.LoadUint32x16Slice(x) - b := simd.LoadUint32x16Slice(y) - c := simd.LoadUint32x16Slice(z) + a := archsimd.LoadUint32x16Slice(x) + b := archsimd.LoadUint32x16Slice(y) + c := archsimd.LoadUint32x16Slice(z) g := make([]uint32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -446,14 +446,14 @@ }) } // testUint64x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testUint64x8Ternary(t *testing.T, f func(_, _, _ simd.Uint64x8) simd.Uint64x8, want func(_, _, _ []uint64) []uint64) { +func testUint64x8Ternary(t *testing.T, f func(_, _, _ archsimd.Uint64x8) archsimd.Uint64x8, want func(_, _, _ []uint64) []uint64) { n := 8 t.Helper() forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool { t.Helper() - a := simd.LoadUint64x8Slice(x) - b := simd.LoadUint64x8Slice(y) - c := simd.LoadUint64x8Slice(z) + a := archsimd.LoadUint64x8Slice(x) + b := archsimd.LoadUint64x8Slice(y) + c := archsimd.LoadUint64x8Slice(z) g := make([]uint64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -462,14 +462,14 @@ }) } // testFloat32x16Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat32x16Ternary(t *testing.T, f func(_, _, _ simd.Float32x16) simd.Float32x16, want func(_, _, _ []float32) []float32) { +func testFloat32x16Ternary(t *testing.T, f func(_, _, _ archsimd.Float32x16) archsimd.Float32x16, want func(_, _, _ []float32) []float32) { n := 16 t.Helper() forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) - b := simd.LoadFloat32x16Slice(y) - c := simd.LoadFloat32x16Slice(z) + a := archsimd.LoadFloat32x16Slice(x) + b := archsimd.LoadFloat32x16Slice(y) + c := archsimd.LoadFloat32x16Slice(z) g := make([]float32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -478,14 +478,14 @@ }) } // testFloat64x8Ternary tests the simd ternary method f against the expected behavior generated by want -func testFloat64x8Ternary(t *testing.T, f func(_, _, _ simd.Float64x8) simd.Float64x8, want func(_, _, _ []float64) []float64) { +func testFloat64x8Ternary(t *testing.T, f func(_, _, _ archsimd.Float64x8) archsimd.Float64x8, want func(_, _, _ []float64) []float64) { n := 8 t.Helper() forSliceTriple(t, float64s, n, func(x, y, z []float64) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) - b := simd.LoadFloat64x8Slice(y) - c := simd.LoadFloat64x8Slice(z) + a := archsimd.LoadFloat64x8Slice(x) + b := archsimd.LoadFloat64x8Slice(y) + c := archsimd.LoadFloat64x8Slice(z) g := make([]float64, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -495,14 +495,14 @@ } // testFloat32x4TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x4TernaryFlaky(t *testing.T, f func(x, y, z simd.Float32x4) simd.Float32x4, want func(x, y, z []float32) []float32, flakiness float64) { +func testFloat32x4TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float32x4) archsimd.Float32x4, want func(x, y, z []float32) []float32, flakiness float64) { n := 4 t.Helper() forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) - b := simd.LoadFloat32x4Slice(y) - c := simd.LoadFloat32x4Slice(z) + a := archsimd.LoadFloat32x4Slice(x) + b := archsimd.LoadFloat32x4Slice(y) + c := archsimd.LoadFloat32x4Slice(z) g := make([]float32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -512,14 +512,14 @@ } // testFloat32x8TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x8TernaryFlaky(t *testing.T, f func(x, y, z simd.Float32x8) simd.Float32x8, want func(x, y, z []float32) []float32, flakiness float64) { +func testFloat32x8TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float32x8) archsimd.Float32x8, want func(x, y, z []float32) []float32, flakiness float64) { n := 8 t.Helper() forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) - b := simd.LoadFloat32x8Slice(y) - c := simd.LoadFloat32x8Slice(z) + a := archsimd.LoadFloat32x8Slice(x) + b := archsimd.LoadFloat32x8Slice(y) + c := archsimd.LoadFloat32x8Slice(z) g := make([]float32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) @@ -529,14 +529,14 @@ } // testFloat32x16TernaryFlaky tests the simd ternary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x16TernaryFlaky(t *testing.T, f func(x, y, z simd.Float32x16) simd.Float32x16, want func(x, y, z []float32) []float32, flakiness float64) { +func testFloat32x16TernaryFlaky(t *testing.T, f func(x, y, z archsimd.Float32x16) archsimd.Float32x16, want func(x, y, z []float32) []float32, flakiness float64) { n := 16 t.Helper() forSliceTriple(t, float32s, n, func(x, y, z []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) - b := simd.LoadFloat32x16Slice(y) - c := simd.LoadFloat32x16Slice(z) + a := archsimd.LoadFloat32x16Slice(x) + b := archsimd.LoadFloat32x16Slice(y) + c := archsimd.LoadFloat32x16Slice(z) g := make([]float32, n) f(a, b, c).StoreSlice(g) w := want(x, y, z) diff --git a/src/simd/internal/simd_test/ternary_test.go b/src/simd/internal/simd_test/ternary_test.go deleted file mode 100644 index 6b563cef75245a110bad309ebd46bd862e94f7d7..0000000000000000000000000000000000000000 --- a/src/simd/internal/simd_test/ternary_test.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build goexperiment.simd && amd64 - -package simd_test - -import ( - "simd" - "testing" -) - -func TestFMA(t *testing.T) { - if simd.X86.AVX512() { - testFloat32x4TernaryFlaky(t, simd.Float32x4.MulAdd, fmaSlice[float32], 0.001) - testFloat32x8TernaryFlaky(t, simd.Float32x8.MulAdd, fmaSlice[float32], 0.001) - testFloat32x16TernaryFlaky(t, simd.Float32x16.MulAdd, fmaSlice[float32], 0.001) - testFloat64x2Ternary(t, simd.Float64x2.MulAdd, fmaSlice[float64]) - testFloat64x4Ternary(t, simd.Float64x4.MulAdd, fmaSlice[float64]) - testFloat64x8Ternary(t, simd.Float64x8.MulAdd, fmaSlice[float64]) - } -} diff --git a/src/simd/internal/simd_test/transpose_test.go b/src/simd/archsimd/internal/simd_test/transpose_test.go rename from src/simd/internal/simd_test/transpose_test.go rename to src/simd/archsimd/internal/simd_test/transpose_test.go index cdf818e9979b61d764eea880a87cb1eaf3fdf1e4..5e1571ef7349aca8ed35d74ec414c44fab8a3192 100644 --- a/src/simd/internal/simd_test/transpose_test.go +++ b/src/simd/archsimd/internal/simd_test/transpose_test.go @@ -8,11 +8,11 @@ package simd_test import ( "fmt" - "simd" + "simd/archsimd" "testing" ) -func Transpose4(a0, a1, a2, a3 simd.Int32x4) (b0, b1, b2, b3 simd.Int32x4) { +func Transpose4(a0, a1, a2, a3 archsimd.Int32x4) (b0, b1, b2, b3 archsimd.Int32x4) { t0, t1 := a0.InterleaveLo(a1), a0.InterleaveHi(a1) t2, t3 := a2.InterleaveLo(a3), a2.InterleaveHi(a3) @@ -34,7 +34,7 @@ b3 = t1.SelectFromPair(2, 3, 6, 7, t3) // uppers return } -func Transpose8(a0, a1, a2, a3, a4, a5, a6, a7 simd.Int32x8) (b0, b1, b2, b3, b4, b5, b6, b7 simd.Int32x8) { +func Transpose8(a0, a1, a2, a3, a4, a5, a6, a7 archsimd.Int32x8) (b0, b1, b2, b3, b4, b5, b6, b7 archsimd.Int32x8) { t0, t1 := a0.InterleaveLoGrouped(a1), a0.InterleaveHiGrouped(a1) t2, t3 := a2.InterleaveLoGrouped(a3), a2.InterleaveHiGrouped(a3) t4, t5 := a4.InterleaveLoGrouped(a5), a4.InterleaveHiGrouped(a5) @@ -81,10 +81,10 @@ func TestTranspose4(t *testing.T) { r := make([]int32, 16, 16) - w := simd.LoadInt32x4Slice([]int32{0xA, 0xB, 0xC, 0xD}) - x := simd.LoadInt32x4Slice([]int32{1, 2, 3, 4}) - y := simd.LoadInt32x4Slice([]int32{0xE, 0xF, 0x10, 0x11}) - z := simd.LoadInt32x4Slice([]int32{5, 6, 7, 8}) + w := archsimd.LoadInt32x4Slice([]int32{0xA, 0xB, 0xC, 0xD}) + x := archsimd.LoadInt32x4Slice([]int32{1, 2, 3, 4}) + y := archsimd.LoadInt32x4Slice([]int32{0xE, 0xF, 0x10, 0x11}) + z := archsimd.LoadInt32x4Slice([]int32{5, 6, 7, 8}) a, b, c, d := Transpose4(w, x, y, z) a.StoreSlice(r[0:]) @@ -109,19 +109,19 @@ for i := int32(1); i <= 64; i++ { a = append(a, i) } - p := simd.LoadInt32x8Slice(a[0:]) - q := simd.LoadInt32x8Slice(a[8:]) - r := simd.LoadInt32x8Slice(a[16:]) - s := simd.LoadInt32x8Slice(a[24:]) + p := archsimd.LoadInt32x8Slice(a[0:]) + q := archsimd.LoadInt32x8Slice(a[8:]) + r := archsimd.LoadInt32x8Slice(a[16:]) + s := archsimd.LoadInt32x8Slice(a[24:]) - w := simd.LoadInt32x8Slice(a[32:]) - x := simd.LoadInt32x8Slice(a[40:]) - y := simd.LoadInt32x8Slice(a[48:]) - z := simd.LoadInt32x8Slice(a[56:]) + w := archsimd.LoadInt32x8Slice(a[32:]) + x := archsimd.LoadInt32x8Slice(a[40:]) + y := archsimd.LoadInt32x8Slice(a[48:]) + z := archsimd.LoadInt32x8Slice(a[56:]) p, q, r, s, w, x, y, z = Transpose8(p, q, r, s, w, x, y, z) - foo := func(a simd.Int32x8, z int32) { + foo := func(a archsimd.Int32x8, z int32) { a.StoreSlice(m) var o []int32 for i := int32(0); i < 8; i++ { @@ -726,10 +726,10 @@ panic("Early bounds check failure") } // transpose diagonal d0, d1, d2, d3 := - simd.LoadInt32x4Slice(r0[i:]), - simd.LoadInt32x4Slice(r1[i:]), - simd.LoadInt32x4Slice(r2[i:]), - simd.LoadInt32x4Slice(r3[i:]) + archsimd.LoadInt32x4Slice(r0[i:]), + archsimd.LoadInt32x4Slice(r1[i:]), + archsimd.LoadInt32x4Slice(r2[i:]), + archsimd.LoadInt32x4Slice(r3[i:]) d0, d1, d2, d3 = Transpose4(d0, d1, d2, d3) @@ -743,20 +743,20 @@ j := 0 for ; j < i; j += B { a0, a1, a2, a3 := m[j], m[j+1], m[j+2], m[j+3] u0, u1, u2, u3 := - simd.LoadInt32x4Slice(a0[i:]), - simd.LoadInt32x4Slice(a1[i:]), - simd.LoadInt32x4Slice(a2[i:]), - simd.LoadInt32x4Slice(a3[i:]) + archsimd.LoadInt32x4Slice(a0[i:]), + archsimd.LoadInt32x4Slice(a1[i:]), + archsimd.LoadInt32x4Slice(a2[i:]), + archsimd.LoadInt32x4Slice(a3[i:]) u0, u1, u2, u3 = Transpose4(u0, u1, u2, u3) - l0 := simd.LoadInt32x4Slice(r0[j:]) + l0 := archsimd.LoadInt32x4Slice(r0[j:]) u0.StoreSlice(r0[j:]) - l1 := simd.LoadInt32x4Slice(r1[j:]) + l1 := archsimd.LoadInt32x4Slice(r1[j:]) u1.StoreSlice(r1[j:]) - l2 := simd.LoadInt32x4Slice(r2[j:]) + l2 := archsimd.LoadInt32x4Slice(r2[j:]) u2.StoreSlice(r2[j:]) - l3 := simd.LoadInt32x4Slice(r3[j:]) + l3 := archsimd.LoadInt32x4Slice(r3[j:]) u3.StoreSlice(r3[j:]) u0, u1, u2, u3 = Transpose4(l0, l1, l2, l3) @@ -790,14 +790,14 @@ panic("Early bounds check failure") } // transpose diagonal d0, d1, d2, d3, d4, d5, d6, d7 := - simd.LoadInt32x8Slice(r0[i:]), - simd.LoadInt32x8Slice(r1[i:]), - simd.LoadInt32x8Slice(r2[i:]), - simd.LoadInt32x8Slice(r3[i:]), - simd.LoadInt32x8Slice(r4[i:]), - simd.LoadInt32x8Slice(r5[i:]), - simd.LoadInt32x8Slice(r6[i:]), - simd.LoadInt32x8Slice(r7[i:]) + archsimd.LoadInt32x8Slice(r0[i:]), + archsimd.LoadInt32x8Slice(r1[i:]), + archsimd.LoadInt32x8Slice(r2[i:]), + archsimd.LoadInt32x8Slice(r3[i:]), + archsimd.LoadInt32x8Slice(r4[i:]), + archsimd.LoadInt32x8Slice(r5[i:]), + archsimd.LoadInt32x8Slice(r6[i:]), + archsimd.LoadInt32x8Slice(r7[i:]) d0, d1, d2, d3, d4, d5, d6, d7 = Transpose8(d0, d1, d2, d3, d4, d5, d6, d7) @@ -815,32 +815,32 @@ j := 0 for ; j < i; j += B { a7, a0, a1, a2, a3, a4, a5, a6 := m[j+7], m[j], m[j+1], m[j+2], m[j+3], m[j+4], m[j+5], m[j+6] u0, u1, u2, u3, u4, u5, u6, u7 := - simd.LoadInt32x8Slice(a0[i:]), - simd.LoadInt32x8Slice(a1[i:]), - simd.LoadInt32x8Slice(a2[i:]), - simd.LoadInt32x8Slice(a3[i:]), - simd.LoadInt32x8Slice(a4[i:]), - simd.LoadInt32x8Slice(a5[i:]), - simd.LoadInt32x8Slice(a6[i:]), - simd.LoadInt32x8Slice(a7[i:]) + archsimd.LoadInt32x8Slice(a0[i:]), + archsimd.LoadInt32x8Slice(a1[i:]), + archsimd.LoadInt32x8Slice(a2[i:]), + archsimd.LoadInt32x8Slice(a3[i:]), + archsimd.LoadInt32x8Slice(a4[i:]), + archsimd.LoadInt32x8Slice(a5[i:]), + archsimd.LoadInt32x8Slice(a6[i:]), + archsimd.LoadInt32x8Slice(a7[i:]) u0, u1, u2, u3, u4, u5, u6, u7 = Transpose8(u0, u1, u2, u3, u4, u5, u6, u7) - l0 := simd.LoadInt32x8Slice(r0[j:]) + l0 := archsimd.LoadInt32x8Slice(r0[j:]) u0.StoreSlice(r0[j:]) - l1 := simd.LoadInt32x8Slice(r1[j:]) + l1 := archsimd.LoadInt32x8Slice(r1[j:]) u1.StoreSlice(r1[j:]) - l2 := simd.LoadInt32x8Slice(r2[j:]) + l2 := archsimd.LoadInt32x8Slice(r2[j:]) u2.StoreSlice(r2[j:]) - l3 := simd.LoadInt32x8Slice(r3[j:]) + l3 := archsimd.LoadInt32x8Slice(r3[j:]) u3.StoreSlice(r3[j:]) - l4 := simd.LoadInt32x8Slice(r4[j:]) + l4 := archsimd.LoadInt32x8Slice(r4[j:]) u4.StoreSlice(r4[j:]) - l5 := simd.LoadInt32x8Slice(r5[j:]) + l5 := archsimd.LoadInt32x8Slice(r5[j:]) u5.StoreSlice(r5[j:]) - l6 := simd.LoadInt32x8Slice(r6[j:]) + l6 := archsimd.LoadInt32x8Slice(r6[j:]) u6.StoreSlice(r6[j:]) - l7 := simd.LoadInt32x8Slice(r7[j:]) + l7 := archsimd.LoadInt32x8Slice(r7[j:]) u7.StoreSlice(r7[j:]) u0, u1, u2, u3, u4, u5, u6, u7 = Transpose8(l0, l1, l2, l3, l4, l5, l6, l7) diff --git a/src/simd/internal/simd_test/unary_helpers_test.go b/src/simd/archsimd/internal/simd_test/unary_helpers_test.go rename from src/simd/internal/simd_test/unary_helpers_test.go rename to src/simd/archsimd/internal/simd_test/unary_helpers_test.go index d99fd3c505419121f2291c525c25f1bf4ec0cc74..e2610ad98b1e5ef8204cce062d44d98bbdff98d2 100644 --- a/src/simd/internal/simd_test/unary_helpers_test.go +++ b/src/simd/archsimd/internal/simd_test/unary_helpers_test.go @@ -9,17 +9,17 @@ package simd_test import ( - "simd" + "simd/archsimd" "testing" ) // testInt8x16Unary tests the simd unary method f against the expected behavior generated by want -func testInt8x16Unary(t *testing.T, f func(_ simd.Int8x16) simd.Int8x16, want func(_ []int8) []int8) { +func testInt8x16Unary(t *testing.T, f func(_ archsimd.Int8x16) archsimd.Int8x16, want func(_ []int8) []int8) { n := 16 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() - a := simd.LoadInt8x16Slice(x) + a := archsimd.LoadInt8x16Slice(x) g := make([]int8, n) f(a).StoreSlice(g) w := want(x) @@ -28,12 +28,12 @@ }) } // testInt16x8Unary tests the simd unary method f against the expected behavior generated by want -func testInt16x8Unary(t *testing.T, f func(_ simd.Int16x8) simd.Int16x8, want func(_ []int16) []int16) { +func testInt16x8Unary(t *testing.T, f func(_ archsimd.Int16x8) archsimd.Int16x8, want func(_ []int16) []int16) { n := 8 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x8Slice(x) + a := archsimd.LoadInt16x8Slice(x) g := make([]int16, n) f(a).StoreSlice(g) w := want(x) @@ -42,12 +42,12 @@ }) } // testInt32x4Unary tests the simd unary method f against the expected behavior generated by want -func testInt32x4Unary(t *testing.T, f func(_ simd.Int32x4) simd.Int32x4, want func(_ []int32) []int32) { +func testInt32x4Unary(t *testing.T, f func(_ archsimd.Int32x4) archsimd.Int32x4, want func(_ []int32) []int32) { n := 4 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x4Slice(x) + a := archsimd.LoadInt32x4Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -56,12 +56,12 @@ }) } // testInt64x2Unary tests the simd unary method f against the expected behavior generated by want -func testInt64x2Unary(t *testing.T, f func(_ simd.Int64x2) simd.Int64x2, want func(_ []int64) []int64) { +func testInt64x2Unary(t *testing.T, f func(_ archsimd.Int64x2) archsimd.Int64x2, want func(_ []int64) []int64) { n := 2 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := simd.LoadInt64x2Slice(x) + a := archsimd.LoadInt64x2Slice(x) g := make([]int64, n) f(a).StoreSlice(g) w := want(x) @@ -70,12 +70,12 @@ }) } // testUint8x16Unary tests the simd unary method f against the expected behavior generated by want -func testUint8x16Unary(t *testing.T, f func(_ simd.Uint8x16) simd.Uint8x16, want func(_ []uint8) []uint8) { +func testUint8x16Unary(t *testing.T, f func(_ archsimd.Uint8x16) archsimd.Uint8x16, want func(_ []uint8) []uint8) { n := 16 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() - a := simd.LoadUint8x16Slice(x) + a := archsimd.LoadUint8x16Slice(x) g := make([]uint8, n) f(a).StoreSlice(g) w := want(x) @@ -84,12 +84,12 @@ }) } // testUint16x8Unary tests the simd unary method f against the expected behavior generated by want -func testUint16x8Unary(t *testing.T, f func(_ simd.Uint16x8) simd.Uint16x8, want func(_ []uint16) []uint16) { +func testUint16x8Unary(t *testing.T, f func(_ archsimd.Uint16x8) archsimd.Uint16x8, want func(_ []uint16) []uint16) { n := 8 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x8Slice(x) + a := archsimd.LoadUint16x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -98,12 +98,12 @@ }) } // testUint32x4Unary tests the simd unary method f against the expected behavior generated by want -func testUint32x4Unary(t *testing.T, f func(_ simd.Uint32x4) simd.Uint32x4, want func(_ []uint32) []uint32) { +func testUint32x4Unary(t *testing.T, f func(_ archsimd.Uint32x4) archsimd.Uint32x4, want func(_ []uint32) []uint32) { n := 4 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x4Slice(x) + a := archsimd.LoadUint32x4Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -112,12 +112,12 @@ }) } // testUint64x2Unary tests the simd unary method f against the expected behavior generated by want -func testUint64x2Unary(t *testing.T, f func(_ simd.Uint64x2) simd.Uint64x2, want func(_ []uint64) []uint64) { +func testUint64x2Unary(t *testing.T, f func(_ archsimd.Uint64x2) archsimd.Uint64x2, want func(_ []uint64) []uint64) { n := 2 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := simd.LoadUint64x2Slice(x) + a := archsimd.LoadUint64x2Slice(x) g := make([]uint64, n) f(a).StoreSlice(g) w := want(x) @@ -126,12 +126,12 @@ }) } // testFloat32x4Unary tests the simd unary method f against the expected behavior generated by want -func testFloat32x4Unary(t *testing.T, f func(_ simd.Float32x4) simd.Float32x4, want func(_ []float32) []float32) { +func testFloat32x4Unary(t *testing.T, f func(_ archsimd.Float32x4) archsimd.Float32x4, want func(_ []float32) []float32) { n := 4 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) + a := archsimd.LoadFloat32x4Slice(x) g := make([]float32, n) f(a).StoreSlice(g) w := want(x) @@ -140,12 +140,12 @@ }) } // testFloat64x2Unary tests the simd unary method f against the expected behavior generated by want -func testFloat64x2Unary(t *testing.T, f func(_ simd.Float64x2) simd.Float64x2, want func(_ []float64) []float64) { +func testFloat64x2Unary(t *testing.T, f func(_ archsimd.Float64x2) archsimd.Float64x2, want func(_ []float64) []float64) { n := 2 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x2Slice(x) + a := archsimd.LoadFloat64x2Slice(x) g := make([]float64, n) f(a).StoreSlice(g) w := want(x) @@ -154,12 +154,12 @@ }) } // testInt8x32Unary tests the simd unary method f against the expected behavior generated by want -func testInt8x32Unary(t *testing.T, f func(_ simd.Int8x32) simd.Int8x32, want func(_ []int8) []int8) { +func testInt8x32Unary(t *testing.T, f func(_ archsimd.Int8x32) archsimd.Int8x32, want func(_ []int8) []int8) { n := 32 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() - a := simd.LoadInt8x32Slice(x) + a := archsimd.LoadInt8x32Slice(x) g := make([]int8, n) f(a).StoreSlice(g) w := want(x) @@ -168,12 +168,12 @@ }) } // testInt16x16Unary tests the simd unary method f against the expected behavior generated by want -func testInt16x16Unary(t *testing.T, f func(_ simd.Int16x16) simd.Int16x16, want func(_ []int16) []int16) { +func testInt16x16Unary(t *testing.T, f func(_ archsimd.Int16x16) archsimd.Int16x16, want func(_ []int16) []int16) { n := 16 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x16Slice(x) + a := archsimd.LoadInt16x16Slice(x) g := make([]int16, n) f(a).StoreSlice(g) w := want(x) @@ -182,12 +182,12 @@ }) } // testInt32x8Unary tests the simd unary method f against the expected behavior generated by want -func testInt32x8Unary(t *testing.T, f func(_ simd.Int32x8) simd.Int32x8, want func(_ []int32) []int32) { +func testInt32x8Unary(t *testing.T, f func(_ archsimd.Int32x8) archsimd.Int32x8, want func(_ []int32) []int32) { n := 8 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x8Slice(x) + a := archsimd.LoadInt32x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -196,12 +196,12 @@ }) } // testInt64x4Unary tests the simd unary method f against the expected behavior generated by want -func testInt64x4Unary(t *testing.T, f func(_ simd.Int64x4) simd.Int64x4, want func(_ []int64) []int64) { +func testInt64x4Unary(t *testing.T, f func(_ archsimd.Int64x4) archsimd.Int64x4, want func(_ []int64) []int64) { n := 4 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := simd.LoadInt64x4Slice(x) + a := archsimd.LoadInt64x4Slice(x) g := make([]int64, n) f(a).StoreSlice(g) w := want(x) @@ -210,12 +210,12 @@ }) } // testUint8x32Unary tests the simd unary method f against the expected behavior generated by want -func testUint8x32Unary(t *testing.T, f func(_ simd.Uint8x32) simd.Uint8x32, want func(_ []uint8) []uint8) { +func testUint8x32Unary(t *testing.T, f func(_ archsimd.Uint8x32) archsimd.Uint8x32, want func(_ []uint8) []uint8) { n := 32 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() - a := simd.LoadUint8x32Slice(x) + a := archsimd.LoadUint8x32Slice(x) g := make([]uint8, n) f(a).StoreSlice(g) w := want(x) @@ -224,12 +224,12 @@ }) } // testUint16x16Unary tests the simd unary method f against the expected behavior generated by want -func testUint16x16Unary(t *testing.T, f func(_ simd.Uint16x16) simd.Uint16x16, want func(_ []uint16) []uint16) { +func testUint16x16Unary(t *testing.T, f func(_ archsimd.Uint16x16) archsimd.Uint16x16, want func(_ []uint16) []uint16) { n := 16 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x16Slice(x) + a := archsimd.LoadUint16x16Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -238,12 +238,12 @@ }) } // testUint32x8Unary tests the simd unary method f against the expected behavior generated by want -func testUint32x8Unary(t *testing.T, f func(_ simd.Uint32x8) simd.Uint32x8, want func(_ []uint32) []uint32) { +func testUint32x8Unary(t *testing.T, f func(_ archsimd.Uint32x8) archsimd.Uint32x8, want func(_ []uint32) []uint32) { n := 8 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x8Slice(x) + a := archsimd.LoadUint32x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -252,12 +252,12 @@ }) } // testUint64x4Unary tests the simd unary method f against the expected behavior generated by want -func testUint64x4Unary(t *testing.T, f func(_ simd.Uint64x4) simd.Uint64x4, want func(_ []uint64) []uint64) { +func testUint64x4Unary(t *testing.T, f func(_ archsimd.Uint64x4) archsimd.Uint64x4, want func(_ []uint64) []uint64) { n := 4 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := simd.LoadUint64x4Slice(x) + a := archsimd.LoadUint64x4Slice(x) g := make([]uint64, n) f(a).StoreSlice(g) w := want(x) @@ -266,12 +266,12 @@ }) } // testFloat32x8Unary tests the simd unary method f against the expected behavior generated by want -func testFloat32x8Unary(t *testing.T, f func(_ simd.Float32x8) simd.Float32x8, want func(_ []float32) []float32) { +func testFloat32x8Unary(t *testing.T, f func(_ archsimd.Float32x8) archsimd.Float32x8, want func(_ []float32) []float32) { n := 8 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) + a := archsimd.LoadFloat32x8Slice(x) g := make([]float32, n) f(a).StoreSlice(g) w := want(x) @@ -280,12 +280,12 @@ }) } // testFloat64x4Unary tests the simd unary method f against the expected behavior generated by want -func testFloat64x4Unary(t *testing.T, f func(_ simd.Float64x4) simd.Float64x4, want func(_ []float64) []float64) { +func testFloat64x4Unary(t *testing.T, f func(_ archsimd.Float64x4) archsimd.Float64x4, want func(_ []float64) []float64) { n := 4 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x4Slice(x) + a := archsimd.LoadFloat64x4Slice(x) g := make([]float64, n) f(a).StoreSlice(g) w := want(x) @@ -294,12 +294,12 @@ }) } // testInt8x64Unary tests the simd unary method f against the expected behavior generated by want -func testInt8x64Unary(t *testing.T, f func(_ simd.Int8x64) simd.Int8x64, want func(_ []int8) []int8) { +func testInt8x64Unary(t *testing.T, f func(_ archsimd.Int8x64) archsimd.Int8x64, want func(_ []int8) []int8) { n := 64 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() - a := simd.LoadInt8x64Slice(x) + a := archsimd.LoadInt8x64Slice(x) g := make([]int8, n) f(a).StoreSlice(g) w := want(x) @@ -308,12 +308,12 @@ }) } // testInt16x32Unary tests the simd unary method f against the expected behavior generated by want -func testInt16x32Unary(t *testing.T, f func(_ simd.Int16x32) simd.Int16x32, want func(_ []int16) []int16) { +func testInt16x32Unary(t *testing.T, f func(_ archsimd.Int16x32) archsimd.Int16x32, want func(_ []int16) []int16) { n := 32 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x32Slice(x) + a := archsimd.LoadInt16x32Slice(x) g := make([]int16, n) f(a).StoreSlice(g) w := want(x) @@ -322,12 +322,12 @@ }) } // testInt32x16Unary tests the simd unary method f against the expected behavior generated by want -func testInt32x16Unary(t *testing.T, f func(_ simd.Int32x16) simd.Int32x16, want func(_ []int32) []int32) { +func testInt32x16Unary(t *testing.T, f func(_ archsimd.Int32x16) archsimd.Int32x16, want func(_ []int32) []int32) { n := 16 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x16Slice(x) + a := archsimd.LoadInt32x16Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -336,12 +336,12 @@ }) } // testInt64x8Unary tests the simd unary method f against the expected behavior generated by want -func testInt64x8Unary(t *testing.T, f func(_ simd.Int64x8) simd.Int64x8, want func(_ []int64) []int64) { +func testInt64x8Unary(t *testing.T, f func(_ archsimd.Int64x8) archsimd.Int64x8, want func(_ []int64) []int64) { n := 8 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := simd.LoadInt64x8Slice(x) + a := archsimd.LoadInt64x8Slice(x) g := make([]int64, n) f(a).StoreSlice(g) w := want(x) @@ -350,12 +350,12 @@ }) } // testUint8x64Unary tests the simd unary method f against the expected behavior generated by want -func testUint8x64Unary(t *testing.T, f func(_ simd.Uint8x64) simd.Uint8x64, want func(_ []uint8) []uint8) { +func testUint8x64Unary(t *testing.T, f func(_ archsimd.Uint8x64) archsimd.Uint8x64, want func(_ []uint8) []uint8) { n := 64 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() - a := simd.LoadUint8x64Slice(x) + a := archsimd.LoadUint8x64Slice(x) g := make([]uint8, n) f(a).StoreSlice(g) w := want(x) @@ -364,12 +364,12 @@ }) } // testUint16x32Unary tests the simd unary method f against the expected behavior generated by want -func testUint16x32Unary(t *testing.T, f func(_ simd.Uint16x32) simd.Uint16x32, want func(_ []uint16) []uint16) { +func testUint16x32Unary(t *testing.T, f func(_ archsimd.Uint16x32) archsimd.Uint16x32, want func(_ []uint16) []uint16) { n := 32 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x32Slice(x) + a := archsimd.LoadUint16x32Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -378,12 +378,12 @@ }) } // testUint32x16Unary tests the simd unary method f against the expected behavior generated by want -func testUint32x16Unary(t *testing.T, f func(_ simd.Uint32x16) simd.Uint32x16, want func(_ []uint32) []uint32) { +func testUint32x16Unary(t *testing.T, f func(_ archsimd.Uint32x16) archsimd.Uint32x16, want func(_ []uint32) []uint32) { n := 16 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x16Slice(x) + a := archsimd.LoadUint32x16Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -392,12 +392,12 @@ }) } // testUint64x8Unary tests the simd unary method f against the expected behavior generated by want -func testUint64x8Unary(t *testing.T, f func(_ simd.Uint64x8) simd.Uint64x8, want func(_ []uint64) []uint64) { +func testUint64x8Unary(t *testing.T, f func(_ archsimd.Uint64x8) archsimd.Uint64x8, want func(_ []uint64) []uint64) { n := 8 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := simd.LoadUint64x8Slice(x) + a := archsimd.LoadUint64x8Slice(x) g := make([]uint64, n) f(a).StoreSlice(g) w := want(x) @@ -406,12 +406,12 @@ }) } // testFloat32x16Unary tests the simd unary method f against the expected behavior generated by want -func testFloat32x16Unary(t *testing.T, f func(_ simd.Float32x16) simd.Float32x16, want func(_ []float32) []float32) { +func testFloat32x16Unary(t *testing.T, f func(_ archsimd.Float32x16) archsimd.Float32x16, want func(_ []float32) []float32) { n := 16 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) + a := archsimd.LoadFloat32x16Slice(x) g := make([]float32, n) f(a).StoreSlice(g) w := want(x) @@ -420,12 +420,12 @@ }) } // testFloat64x8Unary tests the simd unary method f against the expected behavior generated by want -func testFloat64x8Unary(t *testing.T, f func(_ simd.Float64x8) simd.Float64x8, want func(_ []float64) []float64) { +func testFloat64x8Unary(t *testing.T, f func(_ archsimd.Float64x8) archsimd.Float64x8, want func(_ []float64) []float64) { n := 8 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) + a := archsimd.LoadFloat64x8Slice(x) g := make([]float64, n) f(a).StoreSlice(g) w := want(x) @@ -435,12 +435,12 @@ } // testInt8x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt8x16ConvertToInt32(t *testing.T, f func(x simd.Int8x16) simd.Int32x16, want func(x []int8) []int32) { +func testInt8x16ConvertToInt32(t *testing.T, f func(x archsimd.Int8x16) archsimd.Int32x16, want func(x []int8) []int32) { n := 16 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() - a := simd.LoadInt8x16Slice(x) + a := archsimd.LoadInt8x16Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -450,12 +450,12 @@ } // testInt16x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt16x8ConvertToInt32(t *testing.T, f func(x simd.Int16x8) simd.Int32x8, want func(x []int16) []int32) { +func testInt16x8ConvertToInt32(t *testing.T, f func(x archsimd.Int16x8) archsimd.Int32x8, want func(x []int16) []int32) { n := 8 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x8Slice(x) + a := archsimd.LoadInt16x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -465,12 +465,12 @@ } // testInt32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt32x4ConvertToInt32(t *testing.T, f func(x simd.Int32x4) simd.Int32x4, want func(x []int32) []int32) { +func testInt32x4ConvertToInt32(t *testing.T, f func(x archsimd.Int32x4) archsimd.Int32x4, want func(x []int32) []int32) { n := 4 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x4Slice(x) + a := archsimd.LoadInt32x4Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -480,12 +480,12 @@ } // testUint8x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint8x16ConvertToInt32(t *testing.T, f func(x simd.Uint8x16) simd.Int32x16, want func(x []uint8) []int32) { +func testUint8x16ConvertToInt32(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Int32x16, want func(x []uint8) []int32) { n := 16 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() - a := simd.LoadUint8x16Slice(x) + a := archsimd.LoadUint8x16Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -495,12 +495,12 @@ } // testUint16x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint16x8ConvertToInt32(t *testing.T, f func(x simd.Uint16x8) simd.Int32x8, want func(x []uint16) []int32) { +func testUint16x8ConvertToInt32(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Int32x8, want func(x []uint16) []int32) { n := 8 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x8Slice(x) + a := archsimd.LoadUint16x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -510,12 +510,12 @@ } // testUint32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint32x4ConvertToInt32(t *testing.T, f func(x simd.Uint32x4) simd.Int32x4, want func(x []uint32) []int32) { +func testUint32x4ConvertToInt32(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Int32x4, want func(x []uint32) []int32) { n := 4 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x4Slice(x) + a := archsimd.LoadUint32x4Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -525,12 +525,12 @@ } // testFloat32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat32x4ConvertToInt32(t *testing.T, f func(x simd.Float32x4) simd.Int32x4, want func(x []float32) []int32) { +func testFloat32x4ConvertToInt32(t *testing.T, f func(x archsimd.Float32x4) archsimd.Int32x4, want func(x []float32) []int32) { n := 4 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) + a := archsimd.LoadFloat32x4Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -540,12 +540,12 @@ } // testInt16x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt16x16ConvertToInt32(t *testing.T, f func(x simd.Int16x16) simd.Int32x16, want func(x []int16) []int32) { +func testInt16x16ConvertToInt32(t *testing.T, f func(x archsimd.Int16x16) archsimd.Int32x16, want func(x []int16) []int32) { n := 16 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x16Slice(x) + a := archsimd.LoadInt16x16Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -555,12 +555,12 @@ } // testInt32x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt32x8ConvertToInt32(t *testing.T, f func(x simd.Int32x8) simd.Int32x8, want func(x []int32) []int32) { +func testInt32x8ConvertToInt32(t *testing.T, f func(x archsimd.Int32x8) archsimd.Int32x8, want func(x []int32) []int32) { n := 8 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x8Slice(x) + a := archsimd.LoadInt32x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -570,12 +570,12 @@ } // testInt64x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt64x4ConvertToInt32(t *testing.T, f func(x simd.Int64x4) simd.Int32x4, want func(x []int64) []int32) { +func testInt64x4ConvertToInt32(t *testing.T, f func(x archsimd.Int64x4) archsimd.Int32x4, want func(x []int64) []int32) { n := 4 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := simd.LoadInt64x4Slice(x) + a := archsimd.LoadInt64x4Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -585,12 +585,12 @@ } // testUint16x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint16x16ConvertToInt32(t *testing.T, f func(x simd.Uint16x16) simd.Int32x16, want func(x []uint16) []int32) { +func testUint16x16ConvertToInt32(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Int32x16, want func(x []uint16) []int32) { n := 16 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x16Slice(x) + a := archsimd.LoadUint16x16Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -600,12 +600,12 @@ } // testUint32x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint32x8ConvertToInt32(t *testing.T, f func(x simd.Uint32x8) simd.Int32x8, want func(x []uint32) []int32) { +func testUint32x8ConvertToInt32(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Int32x8, want func(x []uint32) []int32) { n := 8 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x8Slice(x) + a := archsimd.LoadUint32x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -615,12 +615,12 @@ } // testUint64x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint64x4ConvertToInt32(t *testing.T, f func(x simd.Uint64x4) simd.Int32x4, want func(x []uint64) []int32) { +func testUint64x4ConvertToInt32(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Int32x4, want func(x []uint64) []int32) { n := 4 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := simd.LoadUint64x4Slice(x) + a := archsimd.LoadUint64x4Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -630,12 +630,12 @@ } // testFloat32x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat32x8ConvertToInt32(t *testing.T, f func(x simd.Float32x8) simd.Int32x8, want func(x []float32) []int32) { +func testFloat32x8ConvertToInt32(t *testing.T, f func(x archsimd.Float32x8) archsimd.Int32x8, want func(x []float32) []int32) { n := 8 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) + a := archsimd.LoadFloat32x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -645,12 +645,12 @@ } // testFloat64x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat64x4ConvertToInt32(t *testing.T, f func(x simd.Float64x4) simd.Int32x4, want func(x []float64) []int32) { +func testFloat64x4ConvertToInt32(t *testing.T, f func(x archsimd.Float64x4) archsimd.Int32x4, want func(x []float64) []int32) { n := 4 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x4Slice(x) + a := archsimd.LoadFloat64x4Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -660,12 +660,12 @@ } // testInt32x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt32x16ConvertToInt32(t *testing.T, f func(x simd.Int32x16) simd.Int32x16, want func(x []int32) []int32) { +func testInt32x16ConvertToInt32(t *testing.T, f func(x archsimd.Int32x16) archsimd.Int32x16, want func(x []int32) []int32) { n := 16 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x16Slice(x) + a := archsimd.LoadInt32x16Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -675,12 +675,12 @@ } // testInt64x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt64x8ConvertToInt32(t *testing.T, f func(x simd.Int64x8) simd.Int32x8, want func(x []int64) []int32) { +func testInt64x8ConvertToInt32(t *testing.T, f func(x archsimd.Int64x8) archsimd.Int32x8, want func(x []int64) []int32) { n := 8 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := simd.LoadInt64x8Slice(x) + a := archsimd.LoadInt64x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -690,12 +690,12 @@ } // testUint32x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint32x16ConvertToInt32(t *testing.T, f func(x simd.Uint32x16) simd.Int32x16, want func(x []uint32) []int32) { +func testUint32x16ConvertToInt32(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Int32x16, want func(x []uint32) []int32) { n := 16 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x16Slice(x) + a := archsimd.LoadUint32x16Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -705,12 +705,12 @@ } // testUint64x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint64x8ConvertToInt32(t *testing.T, f func(x simd.Uint64x8) simd.Int32x8, want func(x []uint64) []int32) { +func testUint64x8ConvertToInt32(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Int32x8, want func(x []uint64) []int32) { n := 8 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := simd.LoadUint64x8Slice(x) + a := archsimd.LoadUint64x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -720,12 +720,12 @@ } // testFloat32x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat32x16ConvertToInt32(t *testing.T, f func(x simd.Float32x16) simd.Int32x16, want func(x []float32) []int32) { +func testFloat32x16ConvertToInt32(t *testing.T, f func(x archsimd.Float32x16) archsimd.Int32x16, want func(x []float32) []int32) { n := 16 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) + a := archsimd.LoadFloat32x16Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -735,12 +735,12 @@ } // testFloat64x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat64x8ConvertToInt32(t *testing.T, f func(x simd.Float64x8) simd.Int32x8, want func(x []float64) []int32) { +func testFloat64x8ConvertToInt32(t *testing.T, f func(x archsimd.Float64x8) archsimd.Int32x8, want func(x []float64) []int32) { n := 8 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) + a := archsimd.LoadFloat64x8Slice(x) g := make([]int32, n) f(a).StoreSlice(g) w := want(x) @@ -750,12 +750,12 @@ } // testInt8x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt8x16ConvertToUint32(t *testing.T, f func(x simd.Int8x16) simd.Uint32x16, want func(x []int8) []uint32) { +func testInt8x16ConvertToUint32(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint32x16, want func(x []int8) []uint32) { n := 16 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() - a := simd.LoadInt8x16Slice(x) + a := archsimd.LoadInt8x16Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -765,12 +765,12 @@ } // testInt16x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt16x8ConvertToUint32(t *testing.T, f func(x simd.Int16x8) simd.Uint32x8, want func(x []int16) []uint32) { +func testInt16x8ConvertToUint32(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint32x8, want func(x []int16) []uint32) { n := 8 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x8Slice(x) + a := archsimd.LoadInt16x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -780,12 +780,12 @@ } // testInt32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt32x4ConvertToUint32(t *testing.T, f func(x simd.Int32x4) simd.Uint32x4, want func(x []int32) []uint32) { +func testInt32x4ConvertToUint32(t *testing.T, f func(x archsimd.Int32x4) archsimd.Uint32x4, want func(x []int32) []uint32) { n := 4 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x4Slice(x) + a := archsimd.LoadInt32x4Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -795,12 +795,12 @@ } // testUint8x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint8x16ConvertToUint32(t *testing.T, f func(x simd.Uint8x16) simd.Uint32x16, want func(x []uint8) []uint32) { +func testUint8x16ConvertToUint32(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint32x16, want func(x []uint8) []uint32) { n := 16 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() - a := simd.LoadUint8x16Slice(x) + a := archsimd.LoadUint8x16Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -810,12 +810,12 @@ } // testUint16x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint16x8ConvertToUint32(t *testing.T, f func(x simd.Uint16x8) simd.Uint32x8, want func(x []uint16) []uint32) { +func testUint16x8ConvertToUint32(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint32x8, want func(x []uint16) []uint32) { n := 8 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x8Slice(x) + a := archsimd.LoadUint16x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -825,12 +825,12 @@ } // testUint32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint32x4ConvertToUint32(t *testing.T, f func(x simd.Uint32x4) simd.Uint32x4, want func(x []uint32) []uint32) { +func testUint32x4ConvertToUint32(t *testing.T, f func(x archsimd.Uint32x4) archsimd.Uint32x4, want func(x []uint32) []uint32) { n := 4 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x4Slice(x) + a := archsimd.LoadUint32x4Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -840,12 +840,12 @@ } // testFloat32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat32x4ConvertToUint32(t *testing.T, f func(x simd.Float32x4) simd.Uint32x4, want func(x []float32) []uint32) { +func testFloat32x4ConvertToUint32(t *testing.T, f func(x archsimd.Float32x4) archsimd.Uint32x4, want func(x []float32) []uint32) { n := 4 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) + a := archsimd.LoadFloat32x4Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -855,12 +855,12 @@ } // testInt16x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt16x16ConvertToUint32(t *testing.T, f func(x simd.Int16x16) simd.Uint32x16, want func(x []int16) []uint32) { +func testInt16x16ConvertToUint32(t *testing.T, f func(x archsimd.Int16x16) archsimd.Uint32x16, want func(x []int16) []uint32) { n := 16 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x16Slice(x) + a := archsimd.LoadInt16x16Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -870,12 +870,12 @@ } // testInt32x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt32x8ConvertToUint32(t *testing.T, f func(x simd.Int32x8) simd.Uint32x8, want func(x []int32) []uint32) { +func testInt32x8ConvertToUint32(t *testing.T, f func(x archsimd.Int32x8) archsimd.Uint32x8, want func(x []int32) []uint32) { n := 8 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x8Slice(x) + a := archsimd.LoadInt32x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -885,12 +885,12 @@ } // testInt64x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt64x4ConvertToUint32(t *testing.T, f func(x simd.Int64x4) simd.Uint32x4, want func(x []int64) []uint32) { +func testInt64x4ConvertToUint32(t *testing.T, f func(x archsimd.Int64x4) archsimd.Uint32x4, want func(x []int64) []uint32) { n := 4 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := simd.LoadInt64x4Slice(x) + a := archsimd.LoadInt64x4Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -900,12 +900,12 @@ } // testUint16x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint16x16ConvertToUint32(t *testing.T, f func(x simd.Uint16x16) simd.Uint32x16, want func(x []uint16) []uint32) { +func testUint16x16ConvertToUint32(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Uint32x16, want func(x []uint16) []uint32) { n := 16 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x16Slice(x) + a := archsimd.LoadUint16x16Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -915,12 +915,12 @@ } // testUint32x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint32x8ConvertToUint32(t *testing.T, f func(x simd.Uint32x8) simd.Uint32x8, want func(x []uint32) []uint32) { +func testUint32x8ConvertToUint32(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Uint32x8, want func(x []uint32) []uint32) { n := 8 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x8Slice(x) + a := archsimd.LoadUint32x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -930,12 +930,12 @@ } // testUint64x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint64x4ConvertToUint32(t *testing.T, f func(x simd.Uint64x4) simd.Uint32x4, want func(x []uint64) []uint32) { +func testUint64x4ConvertToUint32(t *testing.T, f func(x archsimd.Uint64x4) archsimd.Uint32x4, want func(x []uint64) []uint32) { n := 4 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := simd.LoadUint64x4Slice(x) + a := archsimd.LoadUint64x4Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -945,12 +945,12 @@ } // testFloat32x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat32x8ConvertToUint32(t *testing.T, f func(x simd.Float32x8) simd.Uint32x8, want func(x []float32) []uint32) { +func testFloat32x8ConvertToUint32(t *testing.T, f func(x archsimd.Float32x8) archsimd.Uint32x8, want func(x []float32) []uint32) { n := 8 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) + a := archsimd.LoadFloat32x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -960,12 +960,12 @@ } // testFloat64x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat64x4ConvertToUint32(t *testing.T, f func(x simd.Float64x4) simd.Uint32x4, want func(x []float64) []uint32) { +func testFloat64x4ConvertToUint32(t *testing.T, f func(x archsimd.Float64x4) archsimd.Uint32x4, want func(x []float64) []uint32) { n := 4 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x4Slice(x) + a := archsimd.LoadFloat64x4Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -975,12 +975,12 @@ } // testInt32x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt32x16ConvertToUint32(t *testing.T, f func(x simd.Int32x16) simd.Uint32x16, want func(x []int32) []uint32) { +func testInt32x16ConvertToUint32(t *testing.T, f func(x archsimd.Int32x16) archsimd.Uint32x16, want func(x []int32) []uint32) { n := 16 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x16Slice(x) + a := archsimd.LoadInt32x16Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -990,12 +990,12 @@ } // testInt64x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt64x8ConvertToUint32(t *testing.T, f func(x simd.Int64x8) simd.Uint32x8, want func(x []int64) []uint32) { +func testInt64x8ConvertToUint32(t *testing.T, f func(x archsimd.Int64x8) archsimd.Uint32x8, want func(x []int64) []uint32) { n := 8 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := simd.LoadInt64x8Slice(x) + a := archsimd.LoadInt64x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -1005,12 +1005,12 @@ } // testUint32x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint32x16ConvertToUint32(t *testing.T, f func(x simd.Uint32x16) simd.Uint32x16, want func(x []uint32) []uint32) { +func testUint32x16ConvertToUint32(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Uint32x16, want func(x []uint32) []uint32) { n := 16 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x16Slice(x) + a := archsimd.LoadUint32x16Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -1020,12 +1020,12 @@ } // testUint64x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint64x8ConvertToUint32(t *testing.T, f func(x simd.Uint64x8) simd.Uint32x8, want func(x []uint64) []uint32) { +func testUint64x8ConvertToUint32(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Uint32x8, want func(x []uint64) []uint32) { n := 8 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := simd.LoadUint64x8Slice(x) + a := archsimd.LoadUint64x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -1035,12 +1035,12 @@ } // testFloat32x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat32x16ConvertToUint32(t *testing.T, f func(x simd.Float32x16) simd.Uint32x16, want func(x []float32) []uint32) { +func testFloat32x16ConvertToUint32(t *testing.T, f func(x archsimd.Float32x16) archsimd.Uint32x16, want func(x []float32) []uint32) { n := 16 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) + a := archsimd.LoadFloat32x16Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -1050,12 +1050,12 @@ } // testFloat64x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat64x8ConvertToUint32(t *testing.T, f func(x simd.Float64x8) simd.Uint32x8, want func(x []float64) []uint32) { +func testFloat64x8ConvertToUint32(t *testing.T, f func(x archsimd.Float64x8) archsimd.Uint32x8, want func(x []float64) []uint32) { n := 8 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) + a := archsimd.LoadFloat64x8Slice(x) g := make([]uint32, n) f(a).StoreSlice(g) w := want(x) @@ -1065,12 +1065,12 @@ } // testInt8x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt8x16ConvertToUint16(t *testing.T, f func(x simd.Int8x16) simd.Uint16x16, want func(x []int8) []uint16) { +func testInt8x16ConvertToUint16(t *testing.T, f func(x archsimd.Int8x16) archsimd.Uint16x16, want func(x []int8) []uint16) { n := 16 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() - a := simd.LoadInt8x16Slice(x) + a := archsimd.LoadInt8x16Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1080,12 +1080,12 @@ } // testInt16x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt16x8ConvertToUint16(t *testing.T, f func(x simd.Int16x8) simd.Uint16x8, want func(x []int16) []uint16) { +func testInt16x8ConvertToUint16(t *testing.T, f func(x archsimd.Int16x8) archsimd.Uint16x8, want func(x []int16) []uint16) { n := 8 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x8Slice(x) + a := archsimd.LoadInt16x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1095,12 +1095,12 @@ } // testUint8x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint8x16ConvertToUint16(t *testing.T, f func(x simd.Uint8x16) simd.Uint16x16, want func(x []uint8) []uint16) { +func testUint8x16ConvertToUint16(t *testing.T, f func(x archsimd.Uint8x16) archsimd.Uint16x16, want func(x []uint8) []uint16) { n := 16 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() - a := simd.LoadUint8x16Slice(x) + a := archsimd.LoadUint8x16Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1110,12 +1110,12 @@ } // testUint16x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint16x8ConvertToUint16(t *testing.T, f func(x simd.Uint16x8) simd.Uint16x8, want func(x []uint16) []uint16) { +func testUint16x8ConvertToUint16(t *testing.T, f func(x archsimd.Uint16x8) archsimd.Uint16x8, want func(x []uint16) []uint16) { n := 8 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x8Slice(x) + a := archsimd.LoadUint16x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1125,12 +1125,12 @@ } // testInt8x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt8x32ConvertToUint16(t *testing.T, f func(x simd.Int8x32) simd.Uint16x32, want func(x []int8) []uint16) { +func testInt8x32ConvertToUint16(t *testing.T, f func(x archsimd.Int8x32) archsimd.Uint16x32, want func(x []int8) []uint16) { n := 32 t.Helper() forSlice(t, int8s, n, func(x []int8) bool { t.Helper() - a := simd.LoadInt8x32Slice(x) + a := archsimd.LoadInt8x32Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1140,12 +1140,12 @@ } // testInt16x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt16x16ConvertToUint16(t *testing.T, f func(x simd.Int16x16) simd.Uint16x16, want func(x []int16) []uint16) { +func testInt16x16ConvertToUint16(t *testing.T, f func(x archsimd.Int16x16) archsimd.Uint16x16, want func(x []int16) []uint16) { n := 16 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x16Slice(x) + a := archsimd.LoadInt16x16Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1155,12 +1155,12 @@ } // testInt32x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt32x8ConvertToUint16(t *testing.T, f func(x simd.Int32x8) simd.Uint16x8, want func(x []int32) []uint16) { +func testInt32x8ConvertToUint16(t *testing.T, f func(x archsimd.Int32x8) archsimd.Uint16x8, want func(x []int32) []uint16) { n := 8 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x8Slice(x) + a := archsimd.LoadInt32x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1170,12 +1170,12 @@ } // testUint8x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint8x32ConvertToUint16(t *testing.T, f func(x simd.Uint8x32) simd.Uint16x32, want func(x []uint8) []uint16) { +func testUint8x32ConvertToUint16(t *testing.T, f func(x archsimd.Uint8x32) archsimd.Uint16x32, want func(x []uint8) []uint16) { n := 32 t.Helper() forSlice(t, uint8s, n, func(x []uint8) bool { t.Helper() - a := simd.LoadUint8x32Slice(x) + a := archsimd.LoadUint8x32Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1185,12 +1185,12 @@ } // testUint16x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint16x16ConvertToUint16(t *testing.T, f func(x simd.Uint16x16) simd.Uint16x16, want func(x []uint16) []uint16) { +func testUint16x16ConvertToUint16(t *testing.T, f func(x archsimd.Uint16x16) archsimd.Uint16x16, want func(x []uint16) []uint16) { n := 16 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x16Slice(x) + a := archsimd.LoadUint16x16Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1200,12 +1200,12 @@ } // testUint32x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint32x8ConvertToUint16(t *testing.T, f func(x simd.Uint32x8) simd.Uint16x8, want func(x []uint32) []uint16) { +func testUint32x8ConvertToUint16(t *testing.T, f func(x archsimd.Uint32x8) archsimd.Uint16x8, want func(x []uint32) []uint16) { n := 8 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x8Slice(x) + a := archsimd.LoadUint32x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1215,12 +1215,12 @@ } // testFloat32x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat32x8ConvertToUint16(t *testing.T, f func(x simd.Float32x8) simd.Uint16x8, want func(x []float32) []uint16) { +func testFloat32x8ConvertToUint16(t *testing.T, f func(x archsimd.Float32x8) archsimd.Uint16x8, want func(x []float32) []uint16) { n := 8 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) + a := archsimd.LoadFloat32x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1230,12 +1230,12 @@ } // testInt16x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt16x32ConvertToUint16(t *testing.T, f func(x simd.Int16x32) simd.Uint16x32, want func(x []int16) []uint16) { +func testInt16x32ConvertToUint16(t *testing.T, f func(x archsimd.Int16x32) archsimd.Uint16x32, want func(x []int16) []uint16) { n := 32 t.Helper() forSlice(t, int16s, n, func(x []int16) bool { t.Helper() - a := simd.LoadInt16x32Slice(x) + a := archsimd.LoadInt16x32Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1245,12 +1245,12 @@ } // testInt32x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt32x16ConvertToUint16(t *testing.T, f func(x simd.Int32x16) simd.Uint16x16, want func(x []int32) []uint16) { +func testInt32x16ConvertToUint16(t *testing.T, f func(x archsimd.Int32x16) archsimd.Uint16x16, want func(x []int32) []uint16) { n := 16 t.Helper() forSlice(t, int32s, n, func(x []int32) bool { t.Helper() - a := simd.LoadInt32x16Slice(x) + a := archsimd.LoadInt32x16Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1260,12 +1260,12 @@ } // testInt64x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testInt64x8ConvertToUint16(t *testing.T, f func(x simd.Int64x8) simd.Uint16x8, want func(x []int64) []uint16) { +func testInt64x8ConvertToUint16(t *testing.T, f func(x archsimd.Int64x8) archsimd.Uint16x8, want func(x []int64) []uint16) { n := 8 t.Helper() forSlice(t, int64s, n, func(x []int64) bool { t.Helper() - a := simd.LoadInt64x8Slice(x) + a := archsimd.LoadInt64x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1275,12 +1275,12 @@ } // testUint16x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint16x32ConvertToUint16(t *testing.T, f func(x simd.Uint16x32) simd.Uint16x32, want func(x []uint16) []uint16) { +func testUint16x32ConvertToUint16(t *testing.T, f func(x archsimd.Uint16x32) archsimd.Uint16x32, want func(x []uint16) []uint16) { n := 32 t.Helper() forSlice(t, uint16s, n, func(x []uint16) bool { t.Helper() - a := simd.LoadUint16x32Slice(x) + a := archsimd.LoadUint16x32Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1290,12 +1290,12 @@ } // testUint32x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint32x16ConvertToUint16(t *testing.T, f func(x simd.Uint32x16) simd.Uint16x16, want func(x []uint32) []uint16) { +func testUint32x16ConvertToUint16(t *testing.T, f func(x archsimd.Uint32x16) archsimd.Uint16x16, want func(x []uint32) []uint16) { n := 16 t.Helper() forSlice(t, uint32s, n, func(x []uint32) bool { t.Helper() - a := simd.LoadUint32x16Slice(x) + a := archsimd.LoadUint32x16Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1305,12 +1305,12 @@ } // testUint64x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testUint64x8ConvertToUint16(t *testing.T, f func(x simd.Uint64x8) simd.Uint16x8, want func(x []uint64) []uint16) { +func testUint64x8ConvertToUint16(t *testing.T, f func(x archsimd.Uint64x8) archsimd.Uint16x8, want func(x []uint64) []uint16) { n := 8 t.Helper() forSlice(t, uint64s, n, func(x []uint64) bool { t.Helper() - a := simd.LoadUint64x8Slice(x) + a := archsimd.LoadUint64x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1320,12 +1320,12 @@ } // testFloat32x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat32x16ConvertToUint16(t *testing.T, f func(x simd.Float32x16) simd.Uint16x16, want func(x []float32) []uint16) { +func testFloat32x16ConvertToUint16(t *testing.T, f func(x archsimd.Float32x16) archsimd.Uint16x16, want func(x []float32) []uint16) { n := 16 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) + a := archsimd.LoadFloat32x16Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1335,12 +1335,12 @@ } // testFloat64x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want // This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width. -func testFloat64x8ConvertToUint16(t *testing.T, f func(x simd.Float64x8) simd.Uint16x8, want func(x []float64) []uint16) { +func testFloat64x8ConvertToUint16(t *testing.T, f func(x archsimd.Float64x8) archsimd.Uint16x8, want func(x []float64) []uint16) { n := 8 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) + a := archsimd.LoadFloat64x8Slice(x) g := make([]uint16, n) f(a).StoreSlice(g) w := want(x) @@ -1350,12 +1350,12 @@ } // testFloat32x4UnaryFlaky tests the simd unary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x4UnaryFlaky(t *testing.T, f func(x simd.Float32x4) simd.Float32x4, want func(x []float32) []float32, flakiness float64) { +func testFloat32x4UnaryFlaky(t *testing.T, f func(x archsimd.Float32x4) archsimd.Float32x4, want func(x []float32) []float32, flakiness float64) { n := 4 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x4Slice(x) + a := archsimd.LoadFloat32x4Slice(x) g := make([]float32, n) f(a).StoreSlice(g) w := want(x) @@ -1365,12 +1365,12 @@ } // testFloat64x2UnaryFlaky tests the simd unary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat64x2UnaryFlaky(t *testing.T, f func(x simd.Float64x2) simd.Float64x2, want func(x []float64) []float64, flakiness float64) { +func testFloat64x2UnaryFlaky(t *testing.T, f func(x archsimd.Float64x2) archsimd.Float64x2, want func(x []float64) []float64, flakiness float64) { n := 2 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x2Slice(x) + a := archsimd.LoadFloat64x2Slice(x) g := make([]float64, n) f(a).StoreSlice(g) w := want(x) @@ -1380,12 +1380,12 @@ } // testFloat32x8UnaryFlaky tests the simd unary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x8UnaryFlaky(t *testing.T, f func(x simd.Float32x8) simd.Float32x8, want func(x []float32) []float32, flakiness float64) { +func testFloat32x8UnaryFlaky(t *testing.T, f func(x archsimd.Float32x8) archsimd.Float32x8, want func(x []float32) []float32, flakiness float64) { n := 8 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x8Slice(x) + a := archsimd.LoadFloat32x8Slice(x) g := make([]float32, n) f(a).StoreSlice(g) w := want(x) @@ -1395,12 +1395,12 @@ } // testFloat64x4UnaryFlaky tests the simd unary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat64x4UnaryFlaky(t *testing.T, f func(x simd.Float64x4) simd.Float64x4, want func(x []float64) []float64, flakiness float64) { +func testFloat64x4UnaryFlaky(t *testing.T, f func(x archsimd.Float64x4) archsimd.Float64x4, want func(x []float64) []float64, flakiness float64) { n := 4 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x4Slice(x) + a := archsimd.LoadFloat64x4Slice(x) g := make([]float64, n) f(a).StoreSlice(g) w := want(x) @@ -1410,12 +1410,12 @@ } // testFloat32x16UnaryFlaky tests the simd unary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat32x16UnaryFlaky(t *testing.T, f func(x simd.Float32x16) simd.Float32x16, want func(x []float32) []float32, flakiness float64) { +func testFloat32x16UnaryFlaky(t *testing.T, f func(x archsimd.Float32x16) archsimd.Float32x16, want func(x []float32) []float32, flakiness float64) { n := 16 t.Helper() forSlice(t, float32s, n, func(x []float32) bool { t.Helper() - a := simd.LoadFloat32x16Slice(x) + a := archsimd.LoadFloat32x16Slice(x) g := make([]float32, n) f(a).StoreSlice(g) w := want(x) @@ -1425,12 +1425,12 @@ } // testFloat64x8UnaryFlaky tests the simd unary method f against the expected behavior generated by want, // but using a flakiness parameter because we haven't exactly figured out how simd floating point works -func testFloat64x8UnaryFlaky(t *testing.T, f func(x simd.Float64x8) simd.Float64x8, want func(x []float64) []float64, flakiness float64) { +func testFloat64x8UnaryFlaky(t *testing.T, f func(x archsimd.Float64x8) archsimd.Float64x8, want func(x []float64) []float64, flakiness float64) { n := 8 t.Helper() forSlice(t, float64s, n, func(x []float64) bool { t.Helper() - a := simd.LoadFloat64x8Slice(x) + a := archsimd.LoadFloat64x8Slice(x) g := make([]float64, n) f(a).StoreSlice(g) w := want(x) diff --git a/src/simd/internal/simd_test/unary_test.go b/src/simd/internal/simd_test/unary_test.go deleted file mode 100644 index ea4c1149922a4d286cf39f7ec13171b8d18dca15..0000000000000000000000000000000000000000 --- a/src/simd/internal/simd_test/unary_test.go +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build goexperiment.simd && amd64 - -package simd_test - -import ( - "math" - "simd" - "testing" -) - -func TestCeil(t *testing.T) { - testFloat32x4Unary(t, simd.Float32x4.Ceil, ceilSlice[float32]) - testFloat32x8Unary(t, simd.Float32x8.Ceil, ceilSlice[float32]) - testFloat64x2Unary(t, simd.Float64x2.Ceil, ceilSlice[float64]) - testFloat64x4Unary(t, simd.Float64x4.Ceil, ceilSlice[float64]) - if simd.X86.AVX512() { - // testFloat32x16Unary(t, simd.Float32x16.Ceil, ceilSlice[float32]) // missing - // testFloat64x8Unary(t, simd.Float64x8.Ceil, ceilSlice[float64]) // missing - } -} - -func TestFloor(t *testing.T) { - testFloat32x4Unary(t, simd.Float32x4.Floor, floorSlice[float32]) - testFloat32x8Unary(t, simd.Float32x8.Floor, floorSlice[float32]) - testFloat64x2Unary(t, simd.Float64x2.Floor, floorSlice[float64]) - testFloat64x4Unary(t, simd.Float64x4.Floor, floorSlice[float64]) - if simd.X86.AVX512() { - // testFloat32x16Unary(t, simd.Float32x16.Floor, floorSlice[float32]) // missing - // testFloat64x8Unary(t, simd.Float64x8.Floor, floorSlice[float64]) // missing - } -} - -func TestTrunc(t *testing.T) { - testFloat32x4Unary(t, simd.Float32x4.Trunc, truncSlice[float32]) - testFloat32x8Unary(t, simd.Float32x8.Trunc, truncSlice[float32]) - testFloat64x2Unary(t, simd.Float64x2.Trunc, truncSlice[float64]) - testFloat64x4Unary(t, simd.Float64x4.Trunc, truncSlice[float64]) - if simd.X86.AVX512() { - // testFloat32x16Unary(t, simd.Float32x16.Trunc, truncSlice[float32]) // missing - // testFloat64x8Unary(t, simd.Float64x8.Trunc, truncSlice[float64]) // missing - } -} - -func TestRound(t *testing.T) { - testFloat32x4Unary(t, simd.Float32x4.RoundToEven, roundSlice[float32]) - testFloat32x8Unary(t, simd.Float32x8.RoundToEven, roundSlice[float32]) - testFloat64x2Unary(t, simd.Float64x2.RoundToEven, roundSlice[float64]) - testFloat64x4Unary(t, simd.Float64x4.RoundToEven, roundSlice[float64]) - if simd.X86.AVX512() { - // testFloat32x16Unary(t, simd.Float32x16.Round, roundSlice[float32]) // missing - // testFloat64x8Unary(t, simd.Float64x8.Round, roundSlice[float64]) // missing - } -} - -func TestSqrt(t *testing.T) { - testFloat32x4Unary(t, simd.Float32x4.Sqrt, sqrtSlice[float32]) - testFloat32x8Unary(t, simd.Float32x8.Sqrt, sqrtSlice[float32]) - testFloat64x2Unary(t, simd.Float64x2.Sqrt, sqrtSlice[float64]) - testFloat64x4Unary(t, simd.Float64x4.Sqrt, sqrtSlice[float64]) - if simd.X86.AVX512() { - testFloat32x16Unary(t, simd.Float32x16.Sqrt, sqrtSlice[float32]) - testFloat64x8Unary(t, simd.Float64x8.Sqrt, sqrtSlice[float64]) - } -} - -func TestNot(t *testing.T) { - testInt8x16Unary(t, simd.Int8x16.Not, map1[int8](not)) - testInt8x32Unary(t, simd.Int8x32.Not, map1[int8](not)) - testInt16x8Unary(t, simd.Int16x8.Not, map1[int16](not)) - testInt16x16Unary(t, simd.Int16x16.Not, map1[int16](not)) - testInt32x4Unary(t, simd.Int32x4.Not, map1[int32](not)) - testInt32x8Unary(t, simd.Int32x8.Not, map1[int32](not)) -} - -func TestAbsolute(t *testing.T) { - testInt8x16Unary(t, simd.Int8x16.Abs, map1[int8](abs)) - testInt8x32Unary(t, simd.Int8x32.Abs, map1[int8](abs)) - testInt16x8Unary(t, simd.Int16x8.Abs, map1[int16](abs)) - testInt16x16Unary(t, simd.Int16x16.Abs, map1[int16](abs)) - testInt32x4Unary(t, simd.Int32x4.Abs, map1[int32](abs)) - testInt32x8Unary(t, simd.Int32x8.Abs, map1[int32](abs)) - if simd.X86.AVX512() { - testInt8x64Unary(t, simd.Int8x64.Abs, map1[int8](abs)) - testInt16x32Unary(t, simd.Int16x32.Abs, map1[int16](abs)) - testInt32x16Unary(t, simd.Int32x16.Abs, map1[int32](abs)) - testInt64x2Unary(t, simd.Int64x2.Abs, map1[int64](abs)) - testInt64x4Unary(t, simd.Int64x4.Abs, map1[int64](abs)) - testInt64x8Unary(t, simd.Int64x8.Abs, map1[int64](abs)) - } -} - -func TestCeilScaledResidue(t *testing.T) { - if !simd.X86.AVX512() { - t.Skip("Needs AVX512") - } - testFloat64x8UnaryFlaky(t, - func(x simd.Float64x8) simd.Float64x8 { return x.CeilScaledResidue(0) }, - map1(ceilResidueForPrecision[float64](0)), - 0.001) - testFloat64x8UnaryFlaky(t, - func(x simd.Float64x8) simd.Float64x8 { return x.CeilScaledResidue(1) }, - map1(ceilResidueForPrecision[float64](1)), - 0.001) - testFloat64x8Unary(t, - func(x simd.Float64x8) simd.Float64x8 { return x.Sub(x.CeilScaled(0)) }, - map1[float64](func(x float64) float64 { return x - math.Ceil(x) })) -} - -func TestToUint32(t *testing.T) { - if !simd.X86.AVX512() { - t.Skip("Needs AVX512") - } - testFloat32x4ConvertToUint32(t, simd.Float32x4.ConvertToUint32, map1[float32](toUint32)) - testFloat32x8ConvertToUint32(t, simd.Float32x8.ConvertToUint32, map1[float32](toUint32)) - testFloat32x16ConvertToUint32(t, simd.Float32x16.ConvertToUint32, map1[float32](toUint32)) -} - -func TestToInt32(t *testing.T) { - testFloat32x4ConvertToInt32(t, simd.Float32x4.ConvertToInt32, map1[float32](toInt32)) - testFloat32x8ConvertToInt32(t, simd.Float32x8.ConvertToInt32, map1[float32](toInt32)) -} - -func TestConverts(t *testing.T) { - testUint8x16ConvertToUint16(t, simd.Uint8x16.ExtendToUint16, map1[uint8](toUint16)) - testUint16x8ConvertToUint32(t, simd.Uint16x8.ExtendToUint32, map1[uint16](toUint32)) -} - -func TestConvertsAVX512(t *testing.T) { - if !simd.X86.AVX512() { - t.Skip("Needs AVX512") - } - testUint8x32ConvertToUint16(t, simd.Uint8x32.ExtendToUint16, map1[uint8](toUint16)) -} diff --git a/src/simd/internal/test_helpers/checkslices.go b/src/simd/archsimd/internal/test_helpers/checkslices.go rename from src/simd/internal/test_helpers/checkslices.go rename to src/simd/archsimd/internal/test_helpers/checkslices.go diff --git a/src/simd/maskmerge_gen_amd64.go b/src/simd/archsimd/maskmerge_gen_amd64.go rename from src/simd/maskmerge_gen_amd64.go rename to src/simd/archsimd/maskmerge_gen_amd64.go index 71a617c4250de682d48868047c845ed2ee40b5cb..5e9ea394b37fd68907579c0b2707bd9c4cd25f60 100644 --- a/src/simd/maskmerge_gen_amd64.go +++ b/src/simd/archsimd/maskmerge_gen_amd64.go @@ -2,29 +2,29 @@ // Code generated by 'go run genfiles.go'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd // Masked returns x but with elements zeroed where mask is false. func (x Int8x16) Masked(mask Mask8x16) Int8x16 { - im := mask.AsInt8x16() + im := mask.ToInt8x16() return im.And(x) } // Merge returns x but with elements set to y where mask is false. func (x Int8x16) Merge(y Int8x16, mask Mask8x16) Int8x16 { - im := mask.AsInt8x16() + im := mask.ToInt8x16() return y.blend(x, im) } // Masked returns x but with elements zeroed where mask is false. func (x Int16x8) Masked(mask Mask16x8) Int16x8 { - im := mask.AsInt16x8() + im := mask.ToInt16x8() return im.And(x) } // Merge returns x but with elements set to y where mask is false. func (x Int16x8) Merge(y Int16x8, mask Mask16x8) Int16x8 { - im := mask.AsInt16x8().AsInt8x16() + im := mask.ToInt16x8().AsInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsInt16x8() @@ -32,13 +32,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int32x4) Masked(mask Mask32x4) Int32x4 { - im := mask.AsInt32x4() + im := mask.ToInt32x4() return im.And(x) } // Merge returns x but with elements set to y where mask is false. func (x Int32x4) Merge(y Int32x4, mask Mask32x4) Int32x4 { - im := mask.AsInt32x4().AsInt8x16() + im := mask.ToInt32x4().AsInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsInt32x4() @@ -46,13 +46,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int64x2) Masked(mask Mask64x2) Int64x2 { - im := mask.AsInt64x2() + im := mask.ToInt64x2() return im.And(x) } // Merge returns x but with elements set to y where mask is false. func (x Int64x2) Merge(y Int64x2, mask Mask64x2) Int64x2 { - im := mask.AsInt64x2().AsInt8x16() + im := mask.ToInt64x2().AsInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsInt64x2() @@ -60,13 +60,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint8x16) Masked(mask Mask8x16) Uint8x16 { - im := mask.AsInt8x16() + im := mask.ToInt8x16() return x.AsInt8x16().And(im).AsUint8x16() } // Merge returns x but with elements set to y where mask is false. func (x Uint8x16) Merge(y Uint8x16, mask Mask8x16) Uint8x16 { - im := mask.AsInt8x16() + im := mask.ToInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsUint8x16() @@ -74,13 +74,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint16x8) Masked(mask Mask16x8) Uint16x8 { - im := mask.AsInt16x8() + im := mask.ToInt16x8() return x.AsInt16x8().And(im).AsUint16x8() } // Merge returns x but with elements set to y where mask is false. func (x Uint16x8) Merge(y Uint16x8, mask Mask16x8) Uint16x8 { - im := mask.AsInt16x8().AsInt8x16() + im := mask.ToInt16x8().AsInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsUint16x8() @@ -88,13 +88,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint32x4) Masked(mask Mask32x4) Uint32x4 { - im := mask.AsInt32x4() + im := mask.ToInt32x4() return x.AsInt32x4().And(im).AsUint32x4() } // Merge returns x but with elements set to y where mask is false. func (x Uint32x4) Merge(y Uint32x4, mask Mask32x4) Uint32x4 { - im := mask.AsInt32x4().AsInt8x16() + im := mask.ToInt32x4().AsInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsUint32x4() @@ -102,13 +102,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint64x2) Masked(mask Mask64x2) Uint64x2 { - im := mask.AsInt64x2() + im := mask.ToInt64x2() return x.AsInt64x2().And(im).AsUint64x2() } // Merge returns x but with elements set to y where mask is false. func (x Uint64x2) Merge(y Uint64x2, mask Mask64x2) Uint64x2 { - im := mask.AsInt64x2().AsInt8x16() + im := mask.ToInt64x2().AsInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsUint64x2() @@ -116,13 +116,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Float32x4) Masked(mask Mask32x4) Float32x4 { - im := mask.AsInt32x4() + im := mask.ToInt32x4() return x.AsInt32x4().And(im).AsFloat32x4() } // Merge returns x but with elements set to y where mask is false. func (x Float32x4) Merge(y Float32x4, mask Mask32x4) Float32x4 { - im := mask.AsInt32x4().AsInt8x16() + im := mask.ToInt32x4().AsInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsFloat32x4() @@ -130,13 +130,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Float64x2) Masked(mask Mask64x2) Float64x2 { - im := mask.AsInt64x2() + im := mask.ToInt64x2() return x.AsInt64x2().And(im).AsFloat64x2() } // Merge returns x but with elements set to y where mask is false. func (x Float64x2) Merge(y Float64x2, mask Mask64x2) Float64x2 { - im := mask.AsInt64x2().AsInt8x16() + im := mask.ToInt64x2().AsInt8x16() ix := x.AsInt8x16() iy := y.AsInt8x16() return iy.blend(ix, im).AsFloat64x2() @@ -144,25 +144,25 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int8x32) Masked(mask Mask8x32) Int8x32 { - im := mask.AsInt8x32() + im := mask.ToInt8x32() return im.And(x) } // Merge returns x but with elements set to y where mask is false. func (x Int8x32) Merge(y Int8x32, mask Mask8x32) Int8x32 { - im := mask.AsInt8x32() + im := mask.ToInt8x32() return y.blend(x, im) } // Masked returns x but with elements zeroed where mask is false. func (x Int16x16) Masked(mask Mask16x16) Int16x16 { - im := mask.AsInt16x16() + im := mask.ToInt16x16() return im.And(x) } // Merge returns x but with elements set to y where mask is false. func (x Int16x16) Merge(y Int16x16, mask Mask16x16) Int16x16 { - im := mask.AsInt16x16().AsInt8x32() + im := mask.ToInt16x16().AsInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsInt16x16() @@ -170,13 +170,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int32x8) Masked(mask Mask32x8) Int32x8 { - im := mask.AsInt32x8() + im := mask.ToInt32x8() return im.And(x) } // Merge returns x but with elements set to y where mask is false. func (x Int32x8) Merge(y Int32x8, mask Mask32x8) Int32x8 { - im := mask.AsInt32x8().AsInt8x32() + im := mask.ToInt32x8().AsInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsInt32x8() @@ -184,13 +184,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int64x4) Masked(mask Mask64x4) Int64x4 { - im := mask.AsInt64x4() + im := mask.ToInt64x4() return im.And(x) } // Merge returns x but with elements set to y where mask is false. func (x Int64x4) Merge(y Int64x4, mask Mask64x4) Int64x4 { - im := mask.AsInt64x4().AsInt8x32() + im := mask.ToInt64x4().AsInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsInt64x4() @@ -198,13 +198,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint8x32) Masked(mask Mask8x32) Uint8x32 { - im := mask.AsInt8x32() + im := mask.ToInt8x32() return x.AsInt8x32().And(im).AsUint8x32() } // Merge returns x but with elements set to y where mask is false. func (x Uint8x32) Merge(y Uint8x32, mask Mask8x32) Uint8x32 { - im := mask.AsInt8x32() + im := mask.ToInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsUint8x32() @@ -212,13 +212,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint16x16) Masked(mask Mask16x16) Uint16x16 { - im := mask.AsInt16x16() + im := mask.ToInt16x16() return x.AsInt16x16().And(im).AsUint16x16() } // Merge returns x but with elements set to y where mask is false. func (x Uint16x16) Merge(y Uint16x16, mask Mask16x16) Uint16x16 { - im := mask.AsInt16x16().AsInt8x32() + im := mask.ToInt16x16().AsInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsUint16x16() @@ -226,13 +226,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint32x8) Masked(mask Mask32x8) Uint32x8 { - im := mask.AsInt32x8() + im := mask.ToInt32x8() return x.AsInt32x8().And(im).AsUint32x8() } // Merge returns x but with elements set to y where mask is false. func (x Uint32x8) Merge(y Uint32x8, mask Mask32x8) Uint32x8 { - im := mask.AsInt32x8().AsInt8x32() + im := mask.ToInt32x8().AsInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsUint32x8() @@ -240,13 +240,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint64x4) Masked(mask Mask64x4) Uint64x4 { - im := mask.AsInt64x4() + im := mask.ToInt64x4() return x.AsInt64x4().And(im).AsUint64x4() } // Merge returns x but with elements set to y where mask is false. func (x Uint64x4) Merge(y Uint64x4, mask Mask64x4) Uint64x4 { - im := mask.AsInt64x4().AsInt8x32() + im := mask.ToInt64x4().AsInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsUint64x4() @@ -254,13 +254,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Float32x8) Masked(mask Mask32x8) Float32x8 { - im := mask.AsInt32x8() + im := mask.ToInt32x8() return x.AsInt32x8().And(im).AsFloat32x8() } // Merge returns x but with elements set to y where mask is false. func (x Float32x8) Merge(y Float32x8, mask Mask32x8) Float32x8 { - im := mask.AsInt32x8().AsInt8x32() + im := mask.ToInt32x8().AsInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsFloat32x8() @@ -268,13 +268,13 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Float64x4) Masked(mask Mask64x4) Float64x4 { - im := mask.AsInt64x4() + im := mask.ToInt64x4() return x.AsInt64x4().And(im).AsFloat64x4() } // Merge returns x but with elements set to y where mask is false. func (x Float64x4) Merge(y Float64x4, mask Mask64x4) Float64x4 { - im := mask.AsInt64x4().AsInt8x32() + im := mask.ToInt64x4().AsInt8x32() ix := x.AsInt8x32() iy := y.AsInt8x32() return iy.blend(ix, im).AsFloat64x4() @@ -282,7 +282,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int8x64) Masked(mask Mask8x64) Int8x64 { - im := mask.AsInt8x64() + im := mask.ToInt8x64() return im.And(x) } @@ -293,7 +293,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int16x32) Masked(mask Mask16x32) Int16x32 { - im := mask.AsInt16x32() + im := mask.ToInt16x32() return im.And(x) } @@ -304,7 +304,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int32x16) Masked(mask Mask32x16) Int32x16 { - im := mask.AsInt32x16() + im := mask.ToInt32x16() return im.And(x) } @@ -315,7 +315,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Int64x8) Masked(mask Mask64x8) Int64x8 { - im := mask.AsInt64x8() + im := mask.ToInt64x8() return im.And(x) } @@ -326,7 +326,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint8x64) Masked(mask Mask8x64) Uint8x64 { - im := mask.AsInt8x64() + im := mask.ToInt8x64() return x.AsInt8x64().And(im).AsUint8x64() } @@ -339,7 +339,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint16x32) Masked(mask Mask16x32) Uint16x32 { - im := mask.AsInt16x32() + im := mask.ToInt16x32() return x.AsInt16x32().And(im).AsUint16x32() } @@ -352,7 +352,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint32x16) Masked(mask Mask32x16) Uint32x16 { - im := mask.AsInt32x16() + im := mask.ToInt32x16() return x.AsInt32x16().And(im).AsUint32x16() } @@ -365,7 +365,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Uint64x8) Masked(mask Mask64x8) Uint64x8 { - im := mask.AsInt64x8() + im := mask.ToInt64x8() return x.AsInt64x8().And(im).AsUint64x8() } @@ -378,7 +378,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Float32x16) Masked(mask Mask32x16) Float32x16 { - im := mask.AsInt32x16() + im := mask.ToInt32x16() return x.AsInt32x16().And(im).AsFloat32x16() } @@ -391,7 +391,7 @@ } // Masked returns x but with elements zeroed where mask is false. func (x Float64x8) Masked(mask Mask64x8) Float64x8 { - im := mask.AsInt64x8() + im := mask.ToInt64x8() return x.AsInt64x8().And(im).AsFloat64x8() } diff --git a/src/simd/ops_amd64.go b/src/simd/archsimd/ops_amd64.go rename from src/simd/ops_amd64.go rename to src/simd/archsimd/ops_amd64.go index 82774e05adfdf6cc1df791267322a859f2eedb7e..acd5719e6e5d9ba792632287cfd4f77ff6a13023 100644 --- a/src/simd/ops_amd64.go +++ b/src/simd/archsimd/ops_amd64.go @@ -2,7 +2,7 @@ // Code generated by x/arch/internal/simdgen using 'go run . -xedPath $XED_PATH -o godefs -goroot $GOROOT go.yaml types.yaml categories.yaml'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd /* AESDecryptLastRound */ @@ -8652,8 +8652,8 @@ // Uint32x16 converts from Uint64x8 to Uint32x16 func (from Uint64x8) AsUint32x16() (to Uint32x16) -// AsInt8x16 converts from Mask8x16 to Int8x16 -func (from Mask8x16) AsInt8x16() (to Int8x16) +// ToInt8x16 converts from Mask8x16 to Int8x16 +func (from Mask8x16) ToInt8x16() (to Int8x16) // asMask converts from Int8x16 to Mask8x16 func (from Int8x16) asMask() (to Mask8x16) @@ -8662,8 +8662,8 @@ func (x Mask8x16) And(y Mask8x16) Mask8x16 func (x Mask8x16) Or(y Mask8x16) Mask8x16 -// AsInt8x32 converts from Mask8x32 to Int8x32 -func (from Mask8x32) AsInt8x32() (to Int8x32) +// ToInt8x32 converts from Mask8x32 to Int8x32 +func (from Mask8x32) ToInt8x32() (to Int8x32) // asMask converts from Int8x32 to Mask8x32 func (from Int8x32) asMask() (to Mask8x32) @@ -8672,8 +8672,8 @@ func (x Mask8x32) And(y Mask8x32) Mask8x32 func (x Mask8x32) Or(y Mask8x32) Mask8x32 -// AsInt8x64 converts from Mask8x64 to Int8x64 -func (from Mask8x64) AsInt8x64() (to Int8x64) +// ToInt8x64 converts from Mask8x64 to Int8x64 +func (from Mask8x64) ToInt8x64() (to Int8x64) // asMask converts from Int8x64 to Mask8x64 func (from Int8x64) asMask() (to Mask8x64) @@ -8682,8 +8682,8 @@ func (x Mask8x64) And(y Mask8x64) Mask8x64 func (x Mask8x64) Or(y Mask8x64) Mask8x64 -// AsInt16x8 converts from Mask16x8 to Int16x8 -func (from Mask16x8) AsInt16x8() (to Int16x8) +// ToInt16x8 converts from Mask16x8 to Int16x8 +func (from Mask16x8) ToInt16x8() (to Int16x8) // asMask converts from Int16x8 to Mask16x8 func (from Int16x8) asMask() (to Mask16x8) @@ -8692,8 +8692,8 @@ func (x Mask16x8) And(y Mask16x8) Mask16x8 func (x Mask16x8) Or(y Mask16x8) Mask16x8 -// AsInt16x16 converts from Mask16x16 to Int16x16 -func (from Mask16x16) AsInt16x16() (to Int16x16) +// ToInt16x16 converts from Mask16x16 to Int16x16 +func (from Mask16x16) ToInt16x16() (to Int16x16) // asMask converts from Int16x16 to Mask16x16 func (from Int16x16) asMask() (to Mask16x16) @@ -8702,8 +8702,8 @@ func (x Mask16x16) And(y Mask16x16) Mask16x16 func (x Mask16x16) Or(y Mask16x16) Mask16x16 -// AsInt16x32 converts from Mask16x32 to Int16x32 -func (from Mask16x32) AsInt16x32() (to Int16x32) +// ToInt16x32 converts from Mask16x32 to Int16x32 +func (from Mask16x32) ToInt16x32() (to Int16x32) // asMask converts from Int16x32 to Mask16x32 func (from Int16x32) asMask() (to Mask16x32) @@ -8712,8 +8712,8 @@ func (x Mask16x32) And(y Mask16x32) Mask16x32 func (x Mask16x32) Or(y Mask16x32) Mask16x32 -// AsInt32x4 converts from Mask32x4 to Int32x4 -func (from Mask32x4) AsInt32x4() (to Int32x4) +// ToInt32x4 converts from Mask32x4 to Int32x4 +func (from Mask32x4) ToInt32x4() (to Int32x4) // asMask converts from Int32x4 to Mask32x4 func (from Int32x4) asMask() (to Mask32x4) @@ -8722,8 +8722,8 @@ func (x Mask32x4) And(y Mask32x4) Mask32x4 func (x Mask32x4) Or(y Mask32x4) Mask32x4 -// AsInt32x8 converts from Mask32x8 to Int32x8 -func (from Mask32x8) AsInt32x8() (to Int32x8) +// ToInt32x8 converts from Mask32x8 to Int32x8 +func (from Mask32x8) ToInt32x8() (to Int32x8) // asMask converts from Int32x8 to Mask32x8 func (from Int32x8) asMask() (to Mask32x8) @@ -8732,8 +8732,8 @@ func (x Mask32x8) And(y Mask32x8) Mask32x8 func (x Mask32x8) Or(y Mask32x8) Mask32x8 -// AsInt32x16 converts from Mask32x16 to Int32x16 -func (from Mask32x16) AsInt32x16() (to Int32x16) +// ToInt32x16 converts from Mask32x16 to Int32x16 +func (from Mask32x16) ToInt32x16() (to Int32x16) // asMask converts from Int32x16 to Mask32x16 func (from Int32x16) asMask() (to Mask32x16) @@ -8742,8 +8742,8 @@ func (x Mask32x16) And(y Mask32x16) Mask32x16 func (x Mask32x16) Or(y Mask32x16) Mask32x16 -// AsInt64x2 converts from Mask64x2 to Int64x2 -func (from Mask64x2) AsInt64x2() (to Int64x2) +// ToInt64x2 converts from Mask64x2 to Int64x2 +func (from Mask64x2) ToInt64x2() (to Int64x2) // asMask converts from Int64x2 to Mask64x2 func (from Int64x2) asMask() (to Mask64x2) @@ -8752,8 +8752,8 @@ func (x Mask64x2) And(y Mask64x2) Mask64x2 func (x Mask64x2) Or(y Mask64x2) Mask64x2 -// AsInt64x4 converts from Mask64x4 to Int64x4 -func (from Mask64x4) AsInt64x4() (to Int64x4) +// ToInt64x4 converts from Mask64x4 to Int64x4 +func (from Mask64x4) ToInt64x4() (to Int64x4) // asMask converts from Int64x4 to Mask64x4 func (from Int64x4) asMask() (to Mask64x4) @@ -8762,8 +8762,8 @@ func (x Mask64x4) And(y Mask64x4) Mask64x4 func (x Mask64x4) Or(y Mask64x4) Mask64x4 -// AsInt64x8 converts from Mask64x8 to Int64x8 -func (from Mask64x8) AsInt64x8() (to Int64x8) +// ToInt64x8 converts from Mask64x8 to Int64x8 +func (from Mask64x8) ToInt64x8() (to Int64x8) // asMask converts from Int64x8 to Mask64x8 func (from Int64x8) asMask() (to Mask64x8) diff --git a/src/simd/ops_internal_amd64.go b/src/simd/archsimd/ops_internal_amd64.go rename from src/simd/ops_internal_amd64.go rename to src/simd/archsimd/ops_internal_amd64.go index e54c3b200637acae8c0c7957986b2502eb09a9f5..566b88d510d885232fd905daa8372466b2a401c4 100644 --- a/src/simd/ops_internal_amd64.go +++ b/src/simd/archsimd/ops_internal_amd64.go @@ -2,7 +2,7 @@ // Code generated by x/arch/internal/simdgen using 'go run . -xedPath $XED_PATH -o godefs -goroot $GOROOT go.yaml types.yaml categories.yaml'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd /* blend */ @@ -51,6 +51,44 @@ // This operation is applied selectively under a write mask. // // Asm: VPBLENDMQ, CPU Feature: AVX512 func (x Int64x8) blendMasked(y Int64x8, mask Mask64x8) Int64x8 + +/* carrylessMultiply */ + +// carrylessMultiply computes one of four possible Galois polynomial +// products of selected high and low halves of x and y, +// depending on the value of xyHiLo, returning the 128-bit +// product in the concatenated two elements of the result. +// Bit 0 selects the low (0) or high (1) element of x and +// bit 4 selects the low (0x00) or high (0x10) element of y. +// +// xyHiLo results in better performance when it's a constant, a non-constant value will be translated into a jump table. +// +// Asm: VPCLMULQDQ, CPU Feature: AVX +func (x Uint64x2) carrylessMultiply(xyHiLo uint8, y Uint64x2) Uint64x2 + +// carrylessMultiply computes one of two possible Galois polynomial +// products of selected high and low halves of each of the two +// 128-bit lanes of x and y, depending on the value of xyHiLo, +// and returns the four 128-bit products in the result's lanes. +// Bit 0 selects the low (0) or high (1) elements of x's lanes and +// bit 4 selects the low (0x00) or high (0x10) elements of y's lanes. +// +// xyHiLo results in better performance when it's a constant, a non-constant value will be translated into a jump table. +// +// Asm: VPCLMULQDQ, CPU Feature: AVX512VPCLMULQDQ +func (x Uint64x4) carrylessMultiply(xyHiLo uint8, y Uint64x4) Uint64x4 + +// carrylessMultiply computes one of four possible Galois polynomial +// products of selected high and low halves of each of the four +// 128-bit lanes of x and y, depending on the value of xyHiLo, +// and returns the four 128-bit products in the result's lanes. +// Bit 0 selects the low (0) or high (1) elements of x's lanes and +// bit 4 selects the low (0x00) or high (0x10) elements of y's lanes. +// +// xyHiLo results in better performance when it's a constant, a non-constant value will be translated into a jump table. +// +// Asm: VPCLMULQDQ, CPU Feature: AVX512VPCLMULQDQ +func (x Uint64x8) carrylessMultiply(xyHiLo uint8, y Uint64x8) Uint64x8 /* concatSelectedConstant */ diff --git a/src/simd/other_gen_amd64.go b/src/simd/archsimd/other_gen_amd64.go rename from src/simd/other_gen_amd64.go rename to src/simd/archsimd/other_gen_amd64.go index da11b227df302e58e34cb7b446af4a391ac9eb26..8d04409197c78cbc5f5e91f85752aff72747bc19 100644 --- a/src/simd/other_gen_amd64.go +++ b/src/simd/archsimd/other_gen_amd64.go @@ -2,7 +2,7 @@ // Code generated by 'go run genfiles.go'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd // BroadcastInt8x16 returns a vector with the input // x assigned to all elements of the output. @@ -294,36 +294,6 @@ func (from Int64x2) ToMask() (to Mask64x2) { return from.NotEqual(Int64x2{}) } -// ToMask converts from Uint8x16 to Mask8x16, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint8x16) ToMask() (to Mask8x16) { - return from.NotEqual(Uint8x16{}) -} - -// ToMask converts from Uint16x8 to Mask16x8, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint16x8) ToMask() (to Mask16x8) { - return from.NotEqual(Uint16x8{}) -} - -// ToMask converts from Uint32x4 to Mask32x4, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint32x4) ToMask() (to Mask32x4) { - return from.NotEqual(Uint32x4{}) -} - -// ToMask converts from Uint64x2 to Mask64x2, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint64x2) ToMask() (to Mask64x2) { - return from.NotEqual(Uint64x2{}) -} - -// ToMask converts from Float32x4 to Mask32x4, mask element is set to true when the corresponding vector element is non-zero. -func (from Float32x4) ToMask() (to Mask32x4) { - return from.NotEqual(Float32x4{}) -} - -// ToMask converts from Float64x2 to Mask64x2, mask element is set to true when the corresponding vector element is non-zero. -func (from Float64x2) ToMask() (to Mask64x2) { - return from.NotEqual(Float64x2{}) -} - // ToMask converts from Int8x32 to Mask8x32, mask element is set to true when the corresponding vector element is non-zero. func (from Int8x32) ToMask() (to Mask8x32) { return from.NotEqual(Int8x32{}) @@ -344,36 +314,6 @@ func (from Int64x4) ToMask() (to Mask64x4) { return from.NotEqual(Int64x4{}) } -// ToMask converts from Uint8x32 to Mask8x32, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint8x32) ToMask() (to Mask8x32) { - return from.NotEqual(Uint8x32{}) -} - -// ToMask converts from Uint16x16 to Mask16x16, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint16x16) ToMask() (to Mask16x16) { - return from.NotEqual(Uint16x16{}) -} - -// ToMask converts from Uint32x8 to Mask32x8, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint32x8) ToMask() (to Mask32x8) { - return from.NotEqual(Uint32x8{}) -} - -// ToMask converts from Uint64x4 to Mask64x4, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint64x4) ToMask() (to Mask64x4) { - return from.NotEqual(Uint64x4{}) -} - -// ToMask converts from Float32x8 to Mask32x8, mask element is set to true when the corresponding vector element is non-zero. -func (from Float32x8) ToMask() (to Mask32x8) { - return from.NotEqual(Float32x8{}) -} - -// ToMask converts from Float64x4 to Mask64x4, mask element is set to true when the corresponding vector element is non-zero. -func (from Float64x4) ToMask() (to Mask64x4) { - return from.NotEqual(Float64x4{}) -} - // ToMask converts from Int8x64 to Mask8x64, mask element is set to true when the corresponding vector element is non-zero. func (from Int8x64) ToMask() (to Mask8x64) { return from.NotEqual(Int8x64{}) @@ -394,202 +334,172 @@ func (from Int64x8) ToMask() (to Mask64x8) { return from.NotEqual(Int64x8{}) } -// ToMask converts from Uint8x64 to Mask8x64, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint8x64) ToMask() (to Mask8x64) { - return from.NotEqual(Uint8x64{}) -} - -// ToMask converts from Uint16x32 to Mask16x32, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint16x32) ToMask() (to Mask16x32) { - return from.NotEqual(Uint16x32{}) -} - -// ToMask converts from Uint32x16 to Mask32x16, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint32x16) ToMask() (to Mask32x16) { - return from.NotEqual(Uint32x16{}) -} - -// ToMask converts from Uint64x8 to Mask64x8, mask element is set to true when the corresponding vector element is non-zero. -func (from Uint64x8) ToMask() (to Mask64x8) { - return from.NotEqual(Uint64x8{}) -} - -// ToMask converts from Float32x16 to Mask32x16, mask element is set to true when the corresponding vector element is non-zero. -func (from Float32x16) ToMask() (to Mask32x16) { - return from.NotEqual(Float32x16{}) -} - -// ToMask converts from Float64x8 to Mask64x8, mask element is set to true when the corresponding vector element is non-zero. -func (from Float64x8) ToMask() (to Mask64x8) { - return from.NotEqual(Float64x8{}) -} - // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX func (x Int8x16) Not() Int8x16 { - return x.Xor(x.Equal(x).AsInt8x16()) + return x.Xor(x.Equal(x).ToInt8x16()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX func (x Int16x8) Not() Int16x8 { - return x.Xor(x.Equal(x).AsInt16x8()) + return x.Xor(x.Equal(x).ToInt16x8()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX func (x Int32x4) Not() Int32x4 { - return x.Xor(x.Equal(x).AsInt32x4()) + return x.Xor(x.Equal(x).ToInt32x4()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX func (x Int64x2) Not() Int64x2 { - return x.Xor(x.Equal(x).AsInt64x2()) + return x.Xor(x.Equal(x).ToInt64x2()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX2 func (x Int8x32) Not() Int8x32 { - return x.Xor(x.Equal(x).AsInt8x32()) + return x.Xor(x.Equal(x).ToInt8x32()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX2 func (x Int16x16) Not() Int16x16 { - return x.Xor(x.Equal(x).AsInt16x16()) + return x.Xor(x.Equal(x).ToInt16x16()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX2 func (x Int32x8) Not() Int32x8 { - return x.Xor(x.Equal(x).AsInt32x8()) + return x.Xor(x.Equal(x).ToInt32x8()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX2 func (x Int64x4) Not() Int64x4 { - return x.Xor(x.Equal(x).AsInt64x4()) + return x.Xor(x.Equal(x).ToInt64x4()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX512 func (x Int8x64) Not() Int8x64 { - return x.Xor(x.Equal(x).AsInt8x64()) + return x.Xor(x.Equal(x).ToInt8x64()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX512 func (x Int16x32) Not() Int16x32 { - return x.Xor(x.Equal(x).AsInt16x32()) + return x.Xor(x.Equal(x).ToInt16x32()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX512 func (x Int32x16) Not() Int32x16 { - return x.Xor(x.Equal(x).AsInt32x16()) + return x.Xor(x.Equal(x).ToInt32x16()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX512 func (x Int64x8) Not() Int64x8 { - return x.Xor(x.Equal(x).AsInt64x8()) + return x.Xor(x.Equal(x).ToInt64x8()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX func (x Uint8x16) Not() Uint8x16 { - return x.Xor(x.Equal(x).AsInt8x16().AsUint8x16()) + return x.Xor(x.Equal(x).ToInt8x16().AsUint8x16()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX func (x Uint16x8) Not() Uint16x8 { - return x.Xor(x.Equal(x).AsInt16x8().AsUint16x8()) + return x.Xor(x.Equal(x).ToInt16x8().AsUint16x8()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX func (x Uint32x4) Not() Uint32x4 { - return x.Xor(x.Equal(x).AsInt32x4().AsUint32x4()) + return x.Xor(x.Equal(x).ToInt32x4().AsUint32x4()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX func (x Uint64x2) Not() Uint64x2 { - return x.Xor(x.Equal(x).AsInt64x2().AsUint64x2()) + return x.Xor(x.Equal(x).ToInt64x2().AsUint64x2()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX2 func (x Uint8x32) Not() Uint8x32 { - return x.Xor(x.Equal(x).AsInt8x32().AsUint8x32()) + return x.Xor(x.Equal(x).ToInt8x32().AsUint8x32()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX2 func (x Uint16x16) Not() Uint16x16 { - return x.Xor(x.Equal(x).AsInt16x16().AsUint16x16()) + return x.Xor(x.Equal(x).ToInt16x16().AsUint16x16()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX2 func (x Uint32x8) Not() Uint32x8 { - return x.Xor(x.Equal(x).AsInt32x8().AsUint32x8()) + return x.Xor(x.Equal(x).ToInt32x8().AsUint32x8()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX2 func (x Uint64x4) Not() Uint64x4 { - return x.Xor(x.Equal(x).AsInt64x4().AsUint64x4()) + return x.Xor(x.Equal(x).ToInt64x4().AsUint64x4()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX512 func (x Uint8x64) Not() Uint8x64 { - return x.Xor(x.Equal(x).AsInt8x64().AsUint8x64()) + return x.Xor(x.Equal(x).ToInt8x64().AsUint8x64()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX512 func (x Uint16x32) Not() Uint16x32 { - return x.Xor(x.Equal(x).AsInt16x32().AsUint16x32()) + return x.Xor(x.Equal(x).ToInt16x32().AsUint16x32()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX512 func (x Uint32x16) Not() Uint32x16 { - return x.Xor(x.Equal(x).AsInt32x16().AsUint32x16()) + return x.Xor(x.Equal(x).ToInt32x16().AsUint32x16()) } // Not returns the bitwise complement of x // // Emulated, CPU Feature AVX512 func (x Uint64x8) Not() Uint64x8 { - return x.Xor(x.Equal(x).AsInt64x8().AsUint64x8()) + return x.Xor(x.Equal(x).ToInt64x8().AsUint64x8()) } // String returns a string representation of SIMD vector x diff --git a/src/simd/pkginternal_test.go b/src/simd/pkginternal_test.go deleted file mode 100644 index abaa8330e41d3e30e5cd13a03f00ecc7829d926b..0000000000000000000000000000000000000000 --- a/src/simd/pkginternal_test.go +++ /dev/null @@ -1,258 +0,0 @@ -// Copyright 2025 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build goexperiment.simd && amd64 - -package simd_test - -import ( - "simd" - "simd/internal/test_helpers" - "testing" -) - -func TestConcatSelectedConstant64(t *testing.T) { - a := make([]int64, 2) - x := simd.LoadInt64x2Slice([]int64{4, 5}) - y := simd.LoadInt64x2Slice([]int64{6, 7}) - z := x.ExportTestConcatSelectedConstant(0b10, y) - z.StoreSlice(a) - test_helpers.CheckSlices[int64](t, a, []int64{4, 7}) -} - -func TestConcatSelectedConstantGrouped64(t *testing.T) { - a := make([]float64, 4) - x := simd.LoadFloat64x4Slice([]float64{4, 5, 8, 9}) - y := simd.LoadFloat64x4Slice([]float64{6, 7, 10, 11}) - z := x.ExportTestConcatSelectedConstantGrouped(0b_11_10, y) - z.StoreSlice(a) - test_helpers.CheckSlices[float64](t, a, []float64{4, 7, 9, 11}) -} - -func TestConcatSelectedConstant32(t *testing.T) { - a := make([]float32, 4) - x := simd.LoadFloat32x4Slice([]float32{4, 5, 8, 9}) - y := simd.LoadFloat32x4Slice([]float32{6, 7, 10, 11}) - z := x.ExportTestConcatSelectedConstant(0b_11_01_10_00, y) - z.StoreSlice(a) - test_helpers.CheckSlices[float32](t, a, []float32{4, 8, 7, 11}) -} - -func TestConcatSelectedConstantGrouped32(t *testing.T) { - a := make([]uint32, 8) - x := simd.LoadUint32x8Slice([]uint32{0, 1, 2, 3, 8, 9, 10, 11}) - y := simd.LoadUint32x8Slice([]uint32{4, 5, 6, 7, 12, 13, 14, 15}) - z := x.ExportTestConcatSelectedConstantGrouped(0b_11_01_00_10, y) - z.StoreSlice(a) - test_helpers.CheckSlices[uint32](t, a, []uint32{2, 0, 5, 7, 10, 8, 13, 15}) -} - -func TestTern(t *testing.T) { - if !simd.X86.AVX512() { - t.Skip("This test needs AVX512") - } - x := simd.LoadInt32x8Slice([]int32{0, 0, 0, 0, 1, 1, 1, 1}) - y := simd.LoadInt32x8Slice([]int32{0, 0, 1, 1, 0, 0, 1, 1}) - z := simd.LoadInt32x8Slice([]int32{0, 1, 0, 1, 0, 1, 0, 1}) - - foo := func(w simd.Int32x8, k uint8) { - a := make([]int32, 8) - w.StoreSlice(a) - t.Logf("For k=%0b, w=%v", k, a) - for i, b := range a { - if (int32(k)>>i)&1 != b { - t.Errorf("Element %d of stored slice (=%d) did not match corresponding bit in 0b%b", - i, b, k) - } - } - } - - foo(x.ExportTestTern(0b1111_0000, y, z), 0b1111_0000) - foo(x.ExportTestTern(0b1100_1100, y, z), 0b1100_1100) - foo(x.ExportTestTern(0b1010_1010, y, z), 0b1010_1010) -} - -func TestSelect2x4x32(t *testing.T) { - for a := range uint8(8) { - for b := range uint8(8) { - for c := range uint8(8) { - for d := range uint8(8) { - x := simd.LoadInt32x4Slice([]int32{0, 1, 2, 3}) - y := simd.LoadInt32x4Slice([]int32{4, 5, 6, 7}) - z := select2x4x32(x, a, b, c, d, y) - w := make([]int32, 4, 4) - z.StoreSlice(w) - if w[0] != int32(a) || w[1] != int32(b) || - w[2] != int32(c) || w[3] != int32(d) { - t.Errorf("Expected [%d %d %d %d] got %v", a, b, c, d, w) - } - } - } - } - } -} - -func TestSelect2x8x32Grouped(t *testing.T) { - for a := range uint8(8) { - for b := range uint8(8) { - for c := range uint8(8) { - for d := range uint8(8) { - x := simd.LoadInt32x8Slice([]int32{0, 1, 2, 3, 10, 11, 12, 13}) - y := simd.LoadInt32x8Slice([]int32{4, 5, 6, 7, 14, 15, 16, 17}) - z := select2x8x32Grouped(x, a, b, c, d, y) - w := make([]int32, 8, 8) - z.StoreSlice(w) - if w[0] != int32(a) || w[1] != int32(b) || - w[2] != int32(c) || w[3] != int32(d) || - w[4] != int32(10+a) || w[5] != int32(10+b) || - w[6] != int32(10+c) || w[7] != int32(10+d) { - t.Errorf("Expected [%d %d %d %d %d %d %d %d] got %v", a, b, c, d, 10+a, 10+b, 10+c, 10+d, w) - } - } - } - } - } -} - -// select2x4x32 returns a selection of 4 elements in x and y, numbered -// 0-7, where 0-3 are the four elements of x and 4-7 are the four elements -// of y. -func select2x4x32(x simd.Int32x4, a, b, c, d uint8, y simd.Int32x4) simd.Int32x4 { - pattern := a>>2 + (b&4)>>1 + (c & 4) + (d&4)<<1 - - a, b, c, d = a&3, b&3, c&3, d&3 - - switch pattern { - case simd.LLLL: - return x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, b, c, d), x) - case simd.HHHH: - return y.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, b, c, d), y) - case simd.LLHH: - return x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, b, c, d), y) - case simd.HHLL: - return y.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, b, c, d), x) - - case simd.HLLL: - z := y.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, a, b, b), x) - return z.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(0, 2, c, d), x) - case simd.LHLL: - z := x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, a, b, b), y) - return z.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(0, 2, c, d), x) - - case simd.HLHH: - z := y.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, a, b, b), x) - return z.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(0, 2, c, d), y) - case simd.LHHH: - z := x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, a, b, b), y) - return z.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(0, 2, c, d), y) - - case simd.LLLH: - z := x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(c, c, d, d), y) - return x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, b, 0, 2), z) - case simd.LLHL: - z := y.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(c, c, d, d), x) - return x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, b, 0, 2), z) - case simd.HHLH: - z := x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(c, c, d, d), y) - return y.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, b, 0, 2), z) - case simd.HHHL: - z := y.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(c, c, d, d), x) - return y.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, b, 0, 2), z) - - case simd.LHLH: - z := x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, c, b, d), y) - return z.ExportTestConcatSelectedConstant(0b11_01_10_00 /* =simd.ExportTestCscImm4(0, 2, 1, 3) */, z) - case simd.HLHL: - z := x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(b, d, a, c), y) - return z.ExportTestConcatSelectedConstant(0b01_11_00_10 /* =simd.ExportTestCscImm4(2, 0, 3, 1) */, z) - case simd.HLLH: - z := x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(b, c, a, d), y) - return z.ExportTestConcatSelectedConstant(0b11_01_00_10 /* =simd.ExportTestCscImm4(2, 0, 1, 3) */, z) - case simd.LHHL: - z := x.ExportTestConcatSelectedConstant(simd.ExportTestCscImm4(a, d, b, c), y) - return z.ExportTestConcatSelectedConstant(0b01_11_10_00 /* =simd.ExportTestCscImm4(0, 2, 3, 1) */, z) - } - panic("missing case, switch should be exhaustive") -} - -// select2x8x32Grouped returns a pair of selection of 4 elements in x and y, -// numbered 0-7, where 0-3 are the four elements of x's two groups (lower and -// upper 128 bits) and 4-7 are the four elements of y's two groups. - -func select2x8x32Grouped(x simd.Int32x8, a, b, c, d uint8, y simd.Int32x8) simd.Int32x8 { - // selections as being expressible in the ExportTestConcatSelectedConstant pattern, - // or not. Classification is by H and L, where H is a selection from 4-7 - // and L is a selection from 0-3. - // simd.LLHH -> CSC(x,y, a, b, c&3, d&3) - // simd.HHLL -> CSC(y,x, a&3, b&3, c, d) - // simd.LLLL -> CSC(x,x, a, b, c, d) - // simd.HHHH -> CSC(y,y, a&3, b&3, c&3, d&3) - - // simd.LLLH -> z = CSC(x, y, c, c, d&3, d&3); CSC(x, z, a, b, 0, 2) - // simd.LLHL -> z = CSC(x, y, c&3, c&3, d, d); CSC(x, z, a, b, 0, 2) - // simd.HHLH -> z = CSC(x, y, c, c, d&3, d&3); CSC(y, z, a&3, b&3, 0, 2) - // simd.HHHL -> z = CSC(x, y, c&3, c&3, d, d); CSC(y, z, a&3, b&3, 0, 2) - - // simd.LHLL -> z = CSC(x, y, a, a, b&3, b&3); CSC(z, x, 0, 2, c, d) - // etc - - // simd.LHLH -> z = CSC(x, y, a, c, b&3, d&3); CSC(z, z, 0, 2, 1, 3) - // simd.HLHL -> z = CSC(x, y, b, d, a&3, c&3); CSC(z, z, 2, 0, 3, 1) - - pattern := a>>2 + (b&4)>>1 + (c & 4) + (d&4)<<1 - - a, b, c, d = a&3, b&3, c&3, d&3 - - switch pattern { - case simd.LLLL: - return x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, b, c, d), x) - case simd.HHHH: - return y.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, b, c, d), y) - case simd.LLHH: - return x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, b, c, d), y) - case simd.HHLL: - return y.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, b, c, d), x) - - case simd.HLLL: - z := y.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, a, b, b), x) - return z.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(0, 2, c, d), x) - case simd.LHLL: - z := x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, a, b, b), y) - return z.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(0, 2, c, d), x) - - case simd.HLHH: - z := y.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, a, b, b), x) - return z.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(0, 2, c, d), y) - case simd.LHHH: - z := x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, a, b, b), y) - return z.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(0, 2, c, d), y) - - case simd.LLLH: - z := x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(c, c, d, d), y) - return x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, b, 0, 2), z) - case simd.LLHL: - z := y.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(c, c, d, d), x) - return x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, b, 0, 2), z) - case simd.HHLH: - z := x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(c, c, d, d), y) - return y.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, b, 0, 2), z) - case simd.HHHL: - z := y.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(c, c, d, d), x) - return y.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, b, 0, 2), z) - - case simd.LHLH: - z := x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, c, b, d), y) - return z.ExportTestConcatSelectedConstantGrouped(0b11_01_10_00 /* =simd.ExportTestCscImm4(0, 2, 1, 3) */, z) - case simd.HLHL: - z := x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(b, d, a, c), y) - return z.ExportTestConcatSelectedConstantGrouped(0b01_11_00_10 /* =simd.ExportTestCscImm4(2, 0, 3, 1) */, z) - case simd.HLLH: - z := x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(b, c, a, d), y) - return z.ExportTestConcatSelectedConstantGrouped(0b11_01_00_10 /* =simd.ExportTestCscImm4(2, 0, 1, 3) */, z) - case simd.LHHL: - z := x.ExportTestConcatSelectedConstantGrouped(simd.ExportTestCscImm4(a, d, b, c), y) - return z.ExportTestConcatSelectedConstantGrouped(0b01_11_10_00 /* =simd.ExportTestCscImm4(0, 2, 3, 1) */, z) - } - panic("missing case, switch should be exhaustive") -} diff --git a/src/simd/shuffles_amd64.go b/src/simd/archsimd/shuffles_amd64.go rename from src/simd/shuffles_amd64.go rename to src/simd/archsimd/shuffles_amd64.go index b7472f70200c104a0c0895ee8d7f13593e5cee75..2bbd89c72584da8bab29d6d79511c744997e8e4a 100644 --- a/src/simd/shuffles_amd64.go +++ b/src/simd/archsimd/shuffles_amd64.go @@ -4,7 +4,7 @@ // license that can be found in the LICENSE file. //go:build goexperiment.simd && amd64 -package simd +package archsimd // These constants represent the source pattern for the four parameters // (a, b, c, d) passed to SelectFromPair and SelectFromPairGrouped. @@ -1266,3 +1266,75 @@ // Asm: VPSHUFLW, CPU Feature: AVX512 func (x Uint16x32) PermuteScalarsLoGrouped(a, b, c, d uint8) Uint16x32 { return x.permuteScalarsLoGrouped(a&3 | (b&3)<<2 | (c&3)<<4 | d<<6) } + +// CarrylessMultiply computes one of four possible carryless +// multiplications of selected high and low halves of x and y, +// depending on the values of a and b, returning the 128-bit +// product in the concatenated two elements of the result. +// a selects the low (0) or high (1) element of x and +// b selects the low (0) or high (1) element of y. +// +// A carryless multiplication uses bitwise XOR instead of +// add-with-carry, for example (in base two): +// 11 * 11 = 11 * (10 ^ 1) = (11 * 10) ^ (11 * 1) = 110 ^ 11 = 101 +// +// This also models multiplication of polynomials with coefficients +// from GF(2) -- 11 * 11 models (x+1)*(x+1) = x**2 + (1^1)x + 1 = +// x**2 + 0x + 1 = x**2 + 1 modeled by 101. (Note that "+" adds +// polynomial terms, but coefficients "add" with XOR.) +// +// constant values of a and b will result in better performance, +// otherwise the intrinsic may translate into a jump table. +// +// Asm: VPCLMULQDQ, CPU Feature: AVX +func (x Uint64x2) CarrylessMultiply(a, b uint8, y Uint64x2) Uint64x2 { + return x.carrylessMultiply(a&1+((b&1)<<4), y) +} + +// CarrylessMultiplyGrouped computes one of four possible carryless +// multiplications of selected high and low halves of each of the two +// 128-bit lanes of x and y, depending on the values of a and b, +// and returns the four 128-bit products in the result's lanes. +// a selects the low (0) or high (1) elements of x's lanes and +// b selects the low (0) or high (1) elements of y's lanes. +// +// A carryless multiplication uses bitwise XOR instead of +// add-with-carry, for example (in base two): +// 11 * 11 = 11 * (10 ^ 1) = (11 * 10) ^ (11 * 1) = 110 ^ 11 = 101 +// +// This also models multiplication of polynomials with coefficients +// from GF(2) -- 11 * 11 models (x+1)*(x+1) = x**2 + (1^1)x + 1 = +// x**2 + 0x + 1 = x**2 + 1 modeled by 101. (Note that "+" adds +// polynomial terms, but coefficients "add" with XOR.) +// +// constant values of a and b will result in better performance, +// otherwise the intrinsic may translate into a jump table. +// +// Asm: VPCLMULQDQ, CPU Feature: AVX512VPCLMULQDQ +func (x Uint64x4) CarrylessMultiplyGrouped(a, b uint8, y Uint64x4) Uint64x4 { + return x.carrylessMultiply(a&1+((b&1)<<4), y) +} + +// CarrylessMultiplyGrouped computes one of four possible carryless +// multiplications of selected high and low halves of each of the four +// 128-bit lanes of x and y, depending on the values of a and b, +// and returns the four 128-bit products in the result's lanes. +// a selects the low (0) or high (1) elements of x's lanes and +// b selects the low (0) or high (1) elements of y's lanes. +// +// A carryless multiplication uses bitwise XOR instead of +// add-with-carry, for example (in base two): +// 11 * 11 = 11 * (10 ^ 1) = (11 * 10) ^ (11 * 1) = 110 ^ 11 = 101 +// +// This also models multiplication of polynomials with coefficients +// from GF(2) -- 11 * 11 models (x+1)*(x+1) = x**2 + (1^1)x + 1 = +// x**2 + 0x + 1 = x**2 + 1 modeled by 101. (Note that "+" adds +// polynomial terms, but coefficients "add" with XOR.) +// +// constant values of a and b will result in better performance, +// otherwise the intrinsic may translate into a jump table. +// +// Asm: VPCLMULQDQ, CPU Feature: AVX512VPCLMULQDQ +func (x Uint64x8) CarrylessMultiplyGrouped(a, b uint8, y Uint64x8) Uint64x8 { + return x.carrylessMultiply(a&1+((b&1)<<4), y) +} diff --git a/src/simd/slice_gen_amd64.go b/src/simd/archsimd/slice_gen_amd64.go rename from src/simd/slice_gen_amd64.go rename to src/simd/archsimd/slice_gen_amd64.go index 7d70cfb94d00180547e89f44b217a0072de74ead..c03e28206d76b630b22b7c4c43eb7613b39c7231 100644 --- a/src/simd/slice_gen_amd64.go +++ b/src/simd/archsimd/slice_gen_amd64.go @@ -2,7 +2,7 @@ // Code generated by 'go run genfiles.go'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd import "unsafe" diff --git a/src/simd/slicepart_amd64.go b/src/simd/archsimd/slicepart_amd64.go rename from src/simd/slicepart_amd64.go rename to src/simd/archsimd/slicepart_amd64.go index 206d3b98cb28f7896cab883492c2ff3a3a136e2a..a3188e4a5dceef4d0c8c8d3c5669602d31b29ab9 100644 --- a/src/simd/slicepart_amd64.go +++ b/src/simd/archsimd/slicepart_amd64.go @@ -4,7 +4,7 @@ // license that can be found in the LICENSE file. //go:build goexperiment.simd -package simd +package archsimd import "unsafe" diff --git a/src/simd/string.go b/src/simd/archsimd/string.go rename from src/simd/string.go rename to src/simd/archsimd/string.go index a692653aa0ddf5bbc48b51c51c73b591c196c6ee..77500ade1ca1e941cd9fe34c53172e438496ed45 100644 --- a/src/simd/string.go +++ b/src/simd/archsimd/string.go @@ -4,7 +4,7 @@ // license that can be found in the LICENSE file. //go:build goexperiment.simd && amd64 -package simd +package archsimd import ( "internal/strconv" diff --git a/src/simd/testdata/sample.go b/src/simd/archsimd/testdata/sample.go rename from src/simd/testdata/sample.go rename to src/simd/archsimd/testdata/sample.go index b8e3697b6bf644c76a9b787a6fe5cc78a5bab0bf..9c4695d949540becb321ffc43682ab93f8b6c666 100644 --- a/src/simd/testdata/sample.go +++ b/src/simd/archsimd/testdata/sample.go @@ -7,20 +7,20 @@ import ( "fmt" "os" - "simd" + "simd/archsimd" "unsafe" ) -func load(s []float64) simd.Float64x4 { - return simd.LoadFloat64x4((*[4]float64)(s[:4])) +func load(s []float64) archsimd.Float64x4 { + return archsimd.LoadFloat64x4((*[4]float64)(s[:4])) } -type S1 = simd.Float64x4 +type S1 = archsimd.Float64x4 -type S2 simd.Float64x4 +type S2 archsimd.Float64x4 func (s S2) Len() int { - return simd.Float64x4(s).Len() + return archsimd.Float64x4(s).Len() } func (s S2) Load(a []float64) S2 { @@ -28,19 +28,19 @@ return S2(load(a)) } func (s S2) Store(a *[4]float64) { - simd.Float64x4(s).Store(a) + archsimd.Float64x4(s).Store(a) } func (s S2) Add(a S2) S2 { - return S2(simd.Float64x4(s).Add(simd.Float64x4(a))) + return S2(archsimd.Float64x4(s).Add(archsimd.Float64x4(a))) } func (s S2) Mul(a S2) S2 { - return S2(simd.Float64x4(s).Mul(simd.Float64x4(a))) + return S2(archsimd.Float64x4(s).Mul(archsimd.Float64x4(a))) } type S3 struct { - simd.Float64x4 + archsimd.Float64x4 } func ip64_0(a, b []float64) float64 { @@ -82,7 +82,7 @@ return tmp[0] + tmp[1] + tmp[2] + tmp[3] } //go:noinline -func FMA(a, b, c simd.Float64x4) simd.Float64x4 { +func FMA(a, b, c archsimd.Float64x4) archsimd.Float64x4 { return a.Add(b.Mul(c)) } diff --git a/src/simd/types_amd64.go b/src/simd/archsimd/types_amd64.go rename from src/simd/types_amd64.go rename to src/simd/archsimd/types_amd64.go index dfa864b80204725de6a86575ffeb9e49d572aad6..556383b380529fc3e6020d93be36d98a41bfa890 100644 --- a/src/simd/types_amd64.go +++ b/src/simd/archsimd/types_amd64.go @@ -2,7 +2,7 @@ // Code generated by x/arch/internal/simdgen using 'go run . -xedPath $XED_PATH -o godefs -goroot $GOROOT go.yaml types.yaml categories.yaml'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd // v128 is a tag type that tells the compiler that this is really 128-bit SIMD type v128 struct { diff --git a/src/simd/unsafe_helpers.go b/src/simd/archsimd/unsafe_helpers.go rename from src/simd/unsafe_helpers.go rename to src/simd/archsimd/unsafe_helpers.go index c6ea50d551b123a16283262319717338863551a2..0123ad77c52ac18fde28c724200a65ab49a1efd2 100644 --- a/src/simd/unsafe_helpers.go +++ b/src/simd/archsimd/unsafe_helpers.go @@ -2,7 +2,7 @@ // Code generated by 'go run genfiles.go'; DO NOT EDIT. //go:build goexperiment.simd -package simd +package archsimd import "unsafe" diff --git a/src/text/template/exec_test.go b/src/text/template/exec_test.go index 8665f3ad4987c2add0bc60d8a43e19e30d219a60..5812c7b1369b7832424554bad425074dc09bae65 100644 --- a/src/text/template/exec_test.go +++ b/src/text/template/exec_test.go @@ -43,7 +43,8 @@ SICap []int SIEmpty []int SB []bool // Arrays - AI [3]int + AI [3]int + PAI *[3]int // pointer to array // Maps MSI map[string]int MSIone map[string]int // one element, for deterministic output @@ -142,6 +143,7 @@ W1: &W{999}, // leave W2 as nil SI: []int{3, 4, 5}, SICap: make([]int, 5, 10), AI: [3]int{3, 4, 5}, + PAI: &[3]int{3, 4, 5}, SB: []bool{true, false}, MSI: map[string]int{"one": 1, "two": 2, "three": 3}, MSIone: map[string]int{"one": 1}, @@ -556,6 +558,9 @@ {"indexes > cap(s)", "{{slice .SICap 6 10 11}}", "", tVal, false}, {"array[:]", "{{slice .AI}}", "[3 4 5]", tVal, true}, {"array[1:]", "{{slice .AI 1}}", "[4 5]", tVal, true}, {"array[1:2]", "{{slice .AI 1 2}}", "[4]", tVal, true}, + {"pointer to array[:]", "{{slice .PAI}}", "[3 4 5]", tVal, true}, + {"pointer to array[1:]", "{{slice .PAI 1}}", "[4 5]", tVal, true}, + {"pointer to array[1:2]", "{{slice .PAI 1 2}}", "[4]", tVal, true}, {"string[:]", "{{slice .S}}", "xyz", tVal, true}, {"string[0:1]", "{{slice .S 0 1}}", "x", tVal, true}, {"string[1:]", "{{slice .S 1}}", "yz", tVal, true}, diff --git a/src/text/template/funcs.go b/src/text/template/funcs.go index 30b3243a5a841604d98e3e3cba50b6df3614d30a..ed9c7ea5d550158c8f6deb4aa277bb59bb49cf58 100644 --- a/src/text/template/funcs.go +++ b/src/text/template/funcs.go @@ -244,6 +244,10 @@ item = indirectInterface(item) if !item.IsValid() { return reflect.Value{}, fmt.Errorf("slice of untyped nil") } + var isNil bool + if item, isNil = indirect(item); isNil { + return reflect.Value{}, fmt.Errorf("slice of nil pointer") + } if len(indexes) > 3 { return reflect.Value{}, fmt.Errorf("too many slice indexes: %d", len(indexes)) } diff --git a/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go index 8cf5d8112e452d434a93a35f4751fb428fb97857..956795524fa6d1efde34fe8813e78ce35b32b882 100644 --- a/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go +++ b/src/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305.go @@ -38,6 +38,9 @@ } // New returns a ChaCha20-Poly1305 AEAD that uses the given 256-bit key. func New(key []byte) (cipher.AEAD, error) { + if fips140Enforced() { + return nil, errors.New("chacha20poly1305: use of ChaCha20Poly1305 is not allowed in FIPS 140-only mode") + } if len(key) != KeySize { return nil, errors.New("chacha20poly1305: bad key length") } diff --git a/src/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_compat.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_compat.go new file mode 100644 index 0000000000000000000000000000000000000000..9b9d5643ec3d95ea49da9df154b9364c080b52e3 --- /dev/null +++ b/src/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_compat.go @@ -0,0 +1,9 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.26 + +package chacha20poly1305 + +func fips140Enforced() bool { return false } diff --git a/src/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_go1.26.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_go1.26.go new file mode 100644 index 0000000000000000000000000000000000000000..f71089c486e24e610c9ecbbcb2051c3b3f5788ad --- /dev/null +++ b/src/vendor/golang.org/x/crypto/chacha20poly1305/fips140only_go1.26.go @@ -0,0 +1,11 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.26 + +package chacha20poly1305 + +import "crypto/fips140" + +func fips140Enforced() bool { return fips140.Enforced() } diff --git a/src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go b/src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go index 1cebfe946f44407b0515add20bade859384586de..b4299b718c19d1896b0be622d26b97f30ff8c49e 100644 --- a/src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go +++ b/src/vendor/golang.org/x/crypto/chacha20poly1305/xchacha20poly1305.go @@ -22,6 +22,9 @@ // suitable to be generated randomly without risk of collisions. It should be // preferred when nonce uniqueness cannot be trivially ensured, or whenever // nonces are randomly generated. func NewX(key []byte) (cipher.AEAD, error) { + if fips140Enforced() { + return nil, errors.New("chacha20poly1305: use of ChaCha20Poly1305 is not allowed in FIPS 140-only mode") + } if len(key) != KeySize { return nil, errors.New("chacha20poly1305: bad key length") } diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 7932adddfaa1c5f84d4274e4ff50e7c47025bf4c..b6f6376eac041a7d55ae4d3748bbe27ca7940731 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -1,4 +1,4 @@ -# golang.org/x/crypto v0.45.0 +# golang.org/x/crypto v0.46.1-0.20251210140736-7dacc380ba00 ## explicit; go 1.24.0 golang.org/x/crypto/chacha20 golang.org/x/crypto/chacha20poly1305 @@ -15,10 +15,10 @@ golang.org/x/net/http2/hpack golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest -# golang.org/x/sys v0.38.1-0.20251125153526-08e54827f670 +# golang.org/x/sys v0.39.0 ## explicit; go 1.24.0 golang.org/x/sys/cpu -# golang.org/x/text v0.31.1-0.20251128220601-087616b6cde9 +# golang.org/x/text v0.32.0 ## explicit; go 1.24.0 golang.org/x/text/secure/bidirule golang.org/x/text/transform diff --git a/src/weak/pointer_test.go b/src/weak/pointer_test.go index 5e8b9bef5860e28bfedfa7748c6e8d6294642e11..b497c702af7b7148804cb3f698aafba881ed617d 100644 --- a/src/weak/pointer_test.go +++ b/src/weak/pointer_test.go @@ -110,7 +110,7 @@ } bt = nil // bt is no longer referenced. runtime.GC() - for i := range bt { + for i := range wt { st := wt[i].Value() if st != nil { t.Fatalf("expected weak pointer to be nil, got %p", st) diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go index 7cc6cf77e1d95c4fa1a081956988b30bb08b1961..93e4aaed03dd8cc3b2140e2ec5903d98f62a8abc 100644 --- a/test/codegen/arithmetic.go +++ b/test/codegen/arithmetic.go @@ -172,20 +172,26 @@ // arm64:-"ADD" // mips:"SUB" -"ADD" // mips64:"SUBV" -"ADDV" // loong64:"SUBV" -"ADDV" + // riscv64:-"ADD" r := (a + b) - (a + c) // amd64:-"ADDQ" + // riscv64:-"ADD" r1 := (a + b) - (c + a) // amd64:-"ADDQ" + // riscv64:-"ADD" r2 := (b + a) - (a + c) // amd64:-"ADDQ" + // riscv64:-"ADD" r3 := (b + a) - (c + a) // amd64:-"SUBQ" // arm64:-"SUB" // mips:"ADD" -"SUB" // mips64:"ADDV" -"SUBV" // loong64:"ADDV" -"SUBV" + // riscv64:-"SUB" r4 := (a - c) + (c + b) // amd64:-"SUBQ" + // riscv64:-"SUB" r5 := (a - c) + (b + c) return r, r1, r2, r3, r4, r5 } diff --git a/test/codegen/simd.go b/test/codegen/simd.go index 63d5bf757a28ef87b001a735c03df08fb4bb5d58..8f3a1a9f46e7b5b928d940d777089ca7df9ef2f6 100644 --- a/test/codegen/simd.go +++ b/test/codegen/simd.go @@ -10,70 +10,70 @@ //go:build goexperiment.simd package codegen -import "simd" +import "simd/archsimd" func vptest1() bool { - v1 := simd.LoadUint64x2Slice([]uint64{0, 1}) - v2 := simd.LoadUint64x2Slice([]uint64{0, 0}) + v1 := archsimd.LoadUint64x2Slice([]uint64{0, 1}) + v2 := archsimd.LoadUint64x2Slice([]uint64{0, 0}) // amd64:`VPTEST\s(.*)(.*)$` // amd64:`SETCS\s(.*)$` return v1.AndNot(v2).IsZero() } func vptest2() bool { - v1 := simd.LoadUint64x2Slice([]uint64{0, 1}) - v2 := simd.LoadUint64x2Slice([]uint64{0, 0}) + v1 := archsimd.LoadUint64x2Slice([]uint64{0, 1}) + v2 := archsimd.LoadUint64x2Slice([]uint64{0, 0}) // amd64:`VPTEST\s(.*)(.*)$` // amd64:`SETEQ\s(.*)$` return v1.And(v2).IsZero() } type Args2 struct { - V0 simd.Uint8x32 - V1 simd.Uint8x32 + V0 archsimd.Uint8x32 + V1 archsimd.Uint8x32 x string } //go:noinline -func simdStructNoSpill(a Args2) simd.Uint8x32 { +func simdStructNoSpill(a Args2) archsimd.Uint8x32 { // amd64:-`VMOVDQU\s.*$` return a.V0.Xor(a.V1) } -func simdStructWrapperNoSpill(a Args2) simd.Uint8x32 { +func simdStructWrapperNoSpill(a Args2) archsimd.Uint8x32 { // amd64:-`VMOVDQU\s.*$` a.x = "test" return simdStructNoSpill(a) } //go:noinline -func simdArrayNoSpill(a [1]Args2) simd.Uint8x32 { +func simdArrayNoSpill(a [1]Args2) archsimd.Uint8x32 { // amd64:-`VMOVDQU\s.*$` return a[0].V0.Xor(a[0].V1) } -func simdArrayWrapperNoSpill(a [1]Args2) simd.Uint8x32 { +func simdArrayWrapperNoSpill(a [1]Args2) archsimd.Uint8x32 { // amd64:-`VMOVDQU\s.*$` a[0].x = "test" return simdArrayNoSpill(a) } -func simdFeatureGuardedMaskOpt() simd.Int16x16 { - var x, y simd.Int16x16 - if simd.X86.AVX512() { - mask := simd.Mask16x16FromBits(5) +func simdFeatureGuardedMaskOpt() archsimd.Int16x16 { + var x, y archsimd.Int16x16 + if archsimd.X86.AVX512() { + mask := archsimd.Mask16x16FromBits(5) return x.Add(y).Masked(mask) // amd64:`VPADDW.Z\s.*$` } - mask := simd.Mask16x16FromBits(5) + mask := archsimd.Mask16x16FromBits(5) return x.Add(y).Masked(mask) // amd64:`VPAND\s.*$` } -func simdMaskedMerge() simd.Int16x16 { - var x, y simd.Int16x16 - if simd.X86.AVX512() { - mask := simd.Mask16x16FromBits(5) +func simdMaskedMerge() archsimd.Int16x16 { + var x, y archsimd.Int16x16 + if archsimd.X86.AVX512() { + mask := archsimd.Mask16x16FromBits(5) return x.Add(y).Merge(x, mask) // amd64:-`VPBLENDVB\s.*$` } - mask := simd.Mask16x16FromBits(5) + mask := archsimd.Mask16x16FromBits(5) return x.Add(y).Merge(x, mask) // amd64:`VPBLENDVB\s.*$` } diff --git a/test/simd.go b/test/simd.go index 087f6e3da1e1795a24084b452195d436c358521d..52e5ad6c21cc54098330daea193f77cda9fb9a4f 100644 --- a/test/simd.go +++ b/test/simd.go @@ -8,33 +8,33 @@ // license that can be found in the LICENSE file. package foo -import "simd" +import "simd/archsimd" -func f1(x simd.Int8x16) { +func f1(x archsimd.Int8x16) { return // ERROR "has features avx" } -func g1() simd.Int8x16 { - var x simd.Int8x16 +func g1() archsimd.Int8x16 { + var x archsimd.Int8x16 return x // ERROR "has features avx$" } -type T1 simd.Int8x16 +type T1 archsimd.Int8x16 func (x T1) h() { return // ERROR "has features avx$" } -func f2(x simd.Int8x64) { +func f2(x archsimd.Int8x64) { return // ERROR "has features avx[+]avx2[+]avx512$" } -func g2() simd.Int8x64 { - var x simd.Int8x64 +func g2() archsimd.Int8x64 { + var x archsimd.Int8x64 return x // ERROR "has features avx[+]avx2[+]avx512$" } -type T2 simd.Int8x64 +type T2 archsimd.Int8x64 func (x T2) h() { return // ERROR "has features avx[+]avx2[+]avx512$" @@ -44,12 +44,12 @@ var a int func f() { if a == 0 { - if !simd.X86.AVX512() { + if !archsimd.X86.AVX512() { return } println("has avx512") // ERROR "has features avx[+]avx2[+]avx512$" } else { - if !simd.X86.AVX2() { + if !archsimd.X86.AVX2() { return } println("has avx2") // ERROR "has features avx[+]avx2$" @@ -58,7 +58,7 @@ println("has something") } // ERROR "has features avx[+]avx2$" func g() { - if simd.X86.AVX2() { // ERROR "has features avx[+]avx2$" + if archsimd.X86.AVX2() { // ERROR "has features avx[+]avx2$" for range 5 { // ERROR "has features avx[+]avx2$" if a < 0 { // ERROR "has features avx[+]avx2$" a++ // ERROR "has features avx[+]avx2$" @@ -77,7 +77,7 @@ return true } func hasIrreducibleLoop() { - if simd.X86.AVX2() { + if archsimd.X86.AVX2() { goto a // ERROR "has features avx[+]avx2$" } else { goto b @@ -96,8 +96,8 @@ c: println("c") } -func ternRewrite(m, w, x, y, z simd.Int32x16) (t0, t1, t2 simd.Int32x16) { - if !simd.X86.AVX512() { // ERROR "has features avx[+]avx2[+]avx512$" +func ternRewrite(m, w, x, y, z archsimd.Int32x16) (t0, t1, t2 archsimd.Int32x16) { + if !archsimd.X86.AVX512() { // ERROR "has features avx[+]avx2[+]avx512$" return // ERROR "has features avx[+]avx2[+]avx512$" // all blocks have it because of the vector size } t0 = w.Xor(y).Xor(z) // ERROR "Rewriting.*ternInt" @@ -106,12 +106,12 @@ t2 = x.Xor(y).Xor(z).And(x.Xor(y).Xor(z.Not())) // ERROR "Rewriting.*ternInt" return // ERROR "has features avx[+]avx2[+]avx512$" } -func ternTricky1(x, y, z simd.Int32x8) simd.Int32x8 { +func ternTricky1(x, y, z archsimd.Int32x8) archsimd.Int32x8 { // Int32x8 is a 256-bit vector and does not guarantee AVX-512 // a is a 3-variable logical expression occurring outside AVX-512 feature check a := x.Xor(y).Xor(z) - var w simd.Int32x8 - if !simd.X86.AVX512() { // ERROR "has features avx$" + var w archsimd.Int32x8 + if !archsimd.X86.AVX512() { // ERROR "has features avx$" // do nothing } else { w = y.AndNot(a) // ERROR "has features avx[+]avx2[+]avx512" "Rewriting.*ternInt" @@ -120,10 +120,10 @@ // a is a common subexpression return a.Or(w) // ERROR "has features avx$" } -func ternTricky2(x, y, z simd.Int32x8) simd.Int32x8 { +func ternTricky2(x, y, z archsimd.Int32x8) archsimd.Int32x8 { // Int32x8 is a 256-bit vector and does not guarantee AVX-512 - var a, w simd.Int32x8 - if !simd.X86.AVX512() { // ERROR "has features avx$" + var a, w archsimd.Int32x8 + if !archsimd.X86.AVX512() { // ERROR "has features avx$" // do nothing } else { a = x.Xor(y).Xor(z) @@ -133,11 +133,11 @@ // a is a common subexpression return a.Or(w) // ERROR "has features avx$" } -func ternTricky3(x, y, z simd.Int32x8) simd.Int32x8 { +func ternTricky3(x, y, z archsimd.Int32x8) archsimd.Int32x8 { // Int32x8 is a 256-bit vector and does not guarantee AVX-512 a := x.Xor(y).Xor(z) w := y.AndNot(a) - if !simd.X86.AVX512() { // ERROR "has features avx$" + if !archsimd.X86.AVX512() { // ERROR "has features avx$" return a // ERROR "has features avx$" } // a is a common subexpression diff --git a/test/simd/bug1.go b/test/simd/bug1.go index dd450df439cf9f3d09ece12f4d581e8c05b08a04..82f086a508289ca7891bff52f5195afb61f975ab 100644 --- a/test/simd/bug1.go +++ b/test/simd/bug1.go @@ -11,7 +11,7 @@ package p import ( - "simd" + "simd/archsimd" "unsafe" ) @@ -20,19 +20,19 @@ dst *[2][4][4]float32, tos *[2][4][4]float32, blend int, ) { - tiny := simd.BroadcastFloat32x8(0) + tiny := archsimd.BroadcastFloat32x8(0) for { - dstCol12 := simd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(dst[0][0:])))) - dstCol34 := simd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(dst[0][2:])))) - dstCol56 := simd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(dst[1][0:])))) - dstCol78 := simd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(dst[1][2:])))) + dstCol12 := archsimd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(dst[0][0:])))) + dstCol34 := archsimd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(dst[0][2:])))) + dstCol56 := archsimd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(dst[1][0:])))) + dstCol78 := archsimd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(dst[1][2:])))) - tosCol12 := simd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(tos[0][0:])))) - tosCol34 := simd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(tos[0][2:])))) - tosCol56 := simd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(tos[1][0:])))) - tosCol78 := simd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(tos[1][2:])))) + tosCol12 := archsimd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(tos[0][0:])))) + tosCol34 := archsimd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(tos[0][2:])))) + tosCol56 := archsimd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(tos[1][0:])))) + tosCol78 := archsimd.LoadFloat32x8((*[8]float32)(unsafe.Pointer((*[2][4]float32)(tos[1][2:])))) - var Cr0, Cr1, Cr2 simd.Float32x8 + var Cr0, Cr1, Cr2 archsimd.Float32x8 if blend != 0 { invas := tosCol78.Max(tiny) invad := dstCol78.Max(tiny) @@ -42,7 +42,7 @@ Cd2 := dstCol56.Mul(invad) Cs0 := tosCol12.Mul(invas) Cs1 := tosCol34.Mul(invas) Cs2 := tosCol56.Mul(invas) - var Cm0, Cm1, Cm2 simd.Float32x8 + var Cm0, Cm1, Cm2 archsimd.Float32x8 switch blend { case 4: case 10: @@ -61,7 +61,7 @@ Cr0 = dstCol78.Mul(Cs0).Mul(Cm0) Cr1 = dstCol78.Mul(Cs1).Mul(Cm1) Cr2 = dstCol78.Mul(Cs2).Mul(Cm2) } - var resR, resG, resB, resA simd.Float32x8 + var resR, resG, resB, resA archsimd.Float32x8 if blend == 0 { resR = tosCol12 resG = tosCol34 diff --git a/test/simd/bug2.go b/test/simd/bug2.go index 5b7a21176a7c2f54b018b81efa912d423cb4ff66..ab59fc6db5169df73fb6e17541b8a89d31f16973 100644 --- a/test/simd/bug2.go +++ b/test/simd/bug2.go @@ -12,14 +12,14 @@ package p import ( - "simd" + "simd/archsimd" ) func PackComplex(b bool) { for { if b { var indices [4]uint32 - simd.Uint32x4{}.ShiftAllRight(20).Store(&indices) + archsimd.Uint32x4{}.ShiftAllRight(20).Store(&indices) _ = indices[indices[0]] } } @@ -34,9 +34,9 @@ for x := range row { px := &src[y] if b { var indices [4]uint32 - fu := simd.LoadFloat32x4(px).AsUint32x4() + fu := archsimd.LoadFloat32x4(px).AsUint32x4() fu.ShiftAllRight(0).Store(nil) - entry := simd.LoadUint32x4(&[4]uint32{ + entry := archsimd.LoadUint32x4(&[4]uint32{ toSrgbTable[indices[0]], }) var res [4]uint32 diff --git a/test/simd_inline.go b/test/simd_inline.go index b8c4e0de9e84f590c1b7a927b8aa10b306745b21..3d1872b6268de050dee5f11c00036961e13c6836 100644 --- a/test/simd_inline.go +++ b/test/simd_inline.go @@ -8,9 +8,9 @@ // license that can be found in the LICENSE file. package foo -import "simd" +import "simd/archsimd" -func hasClosure(a, b, c, d simd.Int64x4) (w, x, y, z simd.Int64x4) { +func hasClosure(a, b, c, d archsimd.Int64x4) (w, x, y, z archsimd.Int64x4) { shuf := func() { // ERROR "can inline hasClosure.func1" w = z.RotateAllLeft(1).Xor(a) x = w.RotateAllLeft(3).Xor(b)