diff --git a/src/cmd/cgo/internal/testplugin/plugin_test.go b/src/cmd/cgo/internal/testplugin/plugin_test.go index 3216073edbcb2d..4f0458b7dee472 100644 --- a/src/cmd/cgo/internal/testplugin/plugin_test.go +++ b/src/cmd/cgo/internal/testplugin/plugin_test.go @@ -430,3 +430,14 @@ func TestIssue75102(t *testing.T) { goCmd(t, "build", "-o", "issue75102.exe", "./issue75102/main.go") run(t, "./issue75102.exe") } + +func TestIssue81303(t *testing.T) { + // Issue 81303: the itab copies of a plugin must not hide the itabs + // of the host for the same interface/type pairs. + globalSkip(t) + goCmd(t, "build", "-buildmode=plugin", "-o", "issue81303p1.so", "./issue81303/plugin1.go") + goCmd(t, "build", "-buildmode=plugin", "-o", "issue81303p2.so", "./issue81303/plugin2.go") + goCmd(t, "build", "-buildmode=plugin", "-o", "issue81303p3.so", "./issue81303/plugin3.go") + goCmd(t, "build", "-o", "issue81303.exe", "./issue81303/main.go") + run(t, "./issue81303.exe") +} diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue81303/main.go b/src/cmd/cgo/internal/testplugin/testdata/issue81303/main.go new file mode 100644 index 00000000000000..7b2ea1595f18ac --- /dev/null +++ b/src/cmd/cgo/internal/testplugin/testdata/issue81303/main.go @@ -0,0 +1,39 @@ +// Copyright 2026 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. + +// Issue 81303: a plugin has its own copies of the itabs of the host. +// The runtime added these copies to the itab table as second entries +// for the same interface/type pairs. After the table grew, a lookup +// could return the copy from the plugin. A type switch compares the +// itab with the itab of the host, so it took the default case. +// +// Each plugin imports package p, which uses go/ast, so each plugin +// adds a copy of every go/ast itab of the host. The host walks a +// syntax tree before and after each plugin loads. The three plugins +// are the same because plugin.Open loads a plugin path only once. + +package main + +import ( + "log" + "plugin" + + "testplugin/issue81303/p" +) + +func main() { + p.Walk() + for _, name := range []string{"issue81303p1.so", "issue81303p2.so", "issue81303p3.so"} { + pl, err := plugin.Open(name) + if err != nil { + log.Fatal(err) + } + f, err := pl.Lookup("F") + if err != nil { + log.Fatal(err) + } + f.(func())() + p.Walk() + } +} diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue81303/p/p.go b/src/cmd/cgo/internal/testplugin/testdata/issue81303/p/p.go new file mode 100644 index 00000000000000..960d35e4376d5d --- /dev/null +++ b/src/cmd/cgo/internal/testplugin/testdata/issue81303/p/p.go @@ -0,0 +1,48 @@ +// Copyright 2026 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 ( + "go/ast" + "go/parser" + "go/token" + "log" +) + +const src = `package p + +import "fmt" + +type T struct{ x int } + +func (t *T) M(n int) (r int) { + defer func() { r++ }() + go fmt.Println(n) + if n > 0 { + r = n + } else { + r = -n + } + for i := 0; i < n; i++ { + r += t.x + } + switch v := any(n).(type) { + case int: + r = v + } + return +} +` + +// Walk parses src and walks the syntax tree. ast.Walk converts each +// node to ast.Node, which looks up the itab in the itab table, and +// then compares that itab with the itab of the host in a type switch. +func Walk() { + f, err := parser.ParseFile(token.NewFileSet(), "src.go", src, parser.SkipObjectResolution) + if err != nil { + log.Fatal(err) + } + ast.Inspect(f, func(ast.Node) bool { return true }) +} diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin1.go b/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin1.go new file mode 100644 index 00000000000000..c97a98583684ea --- /dev/null +++ b/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin1.go @@ -0,0 +1,11 @@ +// Copyright 2026 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 main + +import "testplugin/issue81303/p" + +func main() {} + +func F() { p.Walk() } diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin2.go b/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin2.go new file mode 100644 index 00000000000000..c97a98583684ea --- /dev/null +++ b/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin2.go @@ -0,0 +1,11 @@ +// Copyright 2026 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 main + +import "testplugin/issue81303/p" + +func main() {} + +func F() { p.Walk() } diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin3.go b/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin3.go new file mode 100644 index 00000000000000..c97a98583684ea --- /dev/null +++ b/src/cmd/cgo/internal/testplugin/testdata/issue81303/plugin3.go @@ -0,0 +1,11 @@ +// Copyright 2026 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 main + +import "testplugin/issue81303/p" + +func main() {} + +func F() { p.Walk() } diff --git a/src/cmd/compile/internal/arm64/simdssa_sve.go b/src/cmd/compile/internal/arm64/simdssa_sve.go index a2b9ff30e2a30f..da1dff09f7f56d 100644 --- a/src/cmd/compile/internal/arm64/simdssa_sve.go +++ b/src/cmd/compile/internal/arm64/simdssa_sve.go @@ -56,6 +56,7 @@ func ssaGenSIMDSVEValue(s *ssagen.State, v *ssa.Value) bool { ssaop.OpARM64ZSQADDD, ssaop.OpARM64ZUQADDD, ssaop.OpARM64ZANDD, + ssaop.OpARM64ZBICD, ssaop.OpARM64ZORRD, ssaop.OpARM64ZFSUBD, ssaop.OpARM64ZSUBD, @@ -126,6 +127,7 @@ func ssaGenSIMDSVEValue(s *ssagen.State, v *ssa.Value) bool { ssaop.OpARM64ZSQADDMergingB, ssaop.OpARM64ZUQADDMergingB, ssaop.OpARM64ZANDMergingB, + ssaop.OpARM64ZBICMergingB, ssaop.OpARM64ZORRMergingB, ssaop.OpARM64ZSUBMergingB, ssaop.OpARM64ZSQSUBMergingB, @@ -138,6 +140,7 @@ func ssaGenSIMDSVEValue(s *ssagen.State, v *ssa.Value) bool { ssaop.OpARM64ZSQADDMergingD, ssaop.OpARM64ZUQADDMergingD, ssaop.OpARM64ZANDMergingD, + ssaop.OpARM64ZBICMergingD, ssaop.OpARM64ZORRMergingD, ssaop.OpARM64ZFSUBMergingD, ssaop.OpARM64ZSUBMergingD, @@ -150,6 +153,7 @@ func ssaGenSIMDSVEValue(s *ssagen.State, v *ssa.Value) bool { ssaop.OpARM64ZSQADDMergingH, ssaop.OpARM64ZUQADDMergingH, ssaop.OpARM64ZANDMergingH, + ssaop.OpARM64ZBICMergingH, ssaop.OpARM64ZORRMergingH, ssaop.OpARM64ZSUBMergingH, ssaop.OpARM64ZSQSUBMergingH, @@ -162,6 +166,7 @@ func ssaGenSIMDSVEValue(s *ssagen.State, v *ssa.Value) bool { ssaop.OpARM64ZSQADDMergingS, ssaop.OpARM64ZUQADDMergingS, ssaop.OpARM64ZANDMergingS, + ssaop.OpARM64ZBICMergingS, ssaop.OpARM64ZORRMergingS, ssaop.OpARM64ZFSUBMergingS, ssaop.OpARM64ZSUBMergingS, diff --git a/src/cmd/compile/internal/ssa/_gen/simdARM64SVE.rules b/src/cmd/compile/internal/ssa/_gen/simdARM64SVE.rules index ea1571e7d523d4..75dfc96eab978d 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdARM64SVE.rules +++ b/src/cmd/compile/internal/ssa/_gen/simdARM64SVE.rules @@ -26,6 +26,14 @@ (AndUint16s ...) => (ZANDD ...) // pureVreg (AndUint32s ...) => (ZANDD ...) // pureVreg (AndUint64s ...) => (ZANDD ...) // pureVreg +(AndNotInt8s ...) => (ZBICD ...) // pureVreg +(AndNotInt16s ...) => (ZBICD ...) // pureVreg +(AndNotInt32s ...) => (ZBICD ...) // pureVreg +(AndNotInt64s ...) => (ZBICD ...) // pureVreg +(AndNotUint8s ...) => (ZBICD ...) // pureVreg +(AndNotUint16s ...) => (ZBICD ...) // pureVreg +(AndNotUint32s ...) => (ZBICD ...) // pureVreg +(AndNotUint64s ...) => (ZBICD ...) // pureVreg (OrInt8s ...) => (ZORRD ...) // pureVreg (OrInt16s ...) => (ZORRD ...) // pureVreg (OrInt32s ...) => (ZORRD ...) // pureVreg @@ -129,6 +137,7 @@ (ZSELB (ZANDD x y) x mask) => (ZANDMergingB x y mask) (ZSELB (ZANDD x y) y mask) => (ZANDMergingB y x mask) (ZSELB (ZANDD x y) z mask) => (ZANDMergingPrefixedB z x y mask) +(ZSELB (ZBICD x y) x mask) => (ZBICMergingB x y mask) (ZSELB (ZEORD x y) x mask) => (ZEORMergingB x y mask) (ZSELB (ZEORD x y) y mask) => (ZEORMergingB y x mask) (ZSELB (ZEORD x y) z mask) => (ZEORMergingPrefixedB z x y mask) @@ -152,6 +161,7 @@ (ZSELD (ZANDD x y) x mask) => (ZANDMergingD x y mask) (ZSELD (ZANDD x y) y mask) => (ZANDMergingD y x mask) (ZSELD (ZANDD x y) z mask) => (ZANDMergingPrefixedD z x y mask) +(ZSELD (ZBICD x y) x mask) => (ZBICMergingD x y mask) (ZSELD (ZEORD x y) x mask) => (ZEORMergingD x y mask) (ZSELD (ZEORD x y) y mask) => (ZEORMergingD y x mask) (ZSELD (ZEORD x y) z mask) => (ZEORMergingPrefixedD z x y mask) @@ -182,6 +192,7 @@ (ZSELH (ZANDD x y) x mask) => (ZANDMergingH x y mask) (ZSELH (ZANDD x y) y mask) => (ZANDMergingH y x mask) (ZSELH (ZANDD x y) z mask) => (ZANDMergingPrefixedH z x y mask) +(ZSELH (ZBICD x y) x mask) => (ZBICMergingH x y mask) (ZSELH (ZEORD x y) x mask) => (ZEORMergingH x y mask) (ZSELH (ZEORD x y) y mask) => (ZEORMergingH y x mask) (ZSELH (ZEORD x y) z mask) => (ZEORMergingPrefixedH z x y mask) @@ -205,6 +216,7 @@ (ZSELS (ZANDD x y) x mask) => (ZANDMergingS x y mask) (ZSELS (ZANDD x y) y mask) => (ZANDMergingS y x mask) (ZSELS (ZANDD x y) z mask) => (ZANDMergingPrefixedS z x y mask) +(ZSELS (ZBICD x y) x mask) => (ZBICMergingS x y mask) (ZSELS (ZEORD x y) x mask) => (ZEORMergingS x y mask) (ZSELS (ZEORD x y) y mask) => (ZEORMergingS y x mask) (ZSELS (ZEORD x y) z mask) => (ZEORMergingPrefixedS z x y mask) diff --git a/src/cmd/compile/internal/ssa/_gen/simdARM64SVEops.go b/src/cmd/compile/internal/ssa/_gen/simdARM64SVEops.go index 1f33449b23ceec..87dd20e3ce44df 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdARM64SVEops.go +++ b/src/cmd/compile/internal/ssa/_gen/simdARM64SVEops.go @@ -33,6 +33,11 @@ func simdARM64SVEOps(z11, z21, zkv, z2kk, z2kv, z2kvPred, z3kvPred regInfo) []op {name: "ZANDMergingPrefixedH", argLength: 4, reg: z3kvPred, asm: "ZAND", typ: "Vec256", resultInArg0: true}, {name: "ZANDMergingPrefixedS", argLength: 4, reg: z3kvPred, asm: "ZAND", typ: "Vec256", resultInArg0: true}, {name: "ZANDMergingS", argLength: 3, reg: z2kvPred, asm: "ZAND", commutative: true, typ: "Vec256"}, + {name: "ZBICD", argLength: 2, reg: z21, asm: "ZBIC", typ: "Vec256"}, + {name: "ZBICMergingB", argLength: 3, reg: z2kvPred, asm: "ZBIC", typ: "Vec256", resultInArg0: true}, + {name: "ZBICMergingD", argLength: 3, reg: z2kvPred, asm: "ZBIC", typ: "Vec256", resultInArg0: true}, + {name: "ZBICMergingH", argLength: 3, reg: z2kvPred, asm: "ZBIC", typ: "Vec256", resultInArg0: true}, + {name: "ZBICMergingS", argLength: 3, reg: z2kvPred, asm: "ZBIC", typ: "Vec256", resultInArg0: true}, {name: "ZCMPEQB", argLength: 3, reg: z2kk, asm: "ZCMPEQ", commutative: true, typ: "Mask"}, {name: "ZCMPEQD", argLength: 3, reg: z2kk, asm: "ZCMPEQ", commutative: true, typ: "Mask"}, {name: "ZCMPEQH", argLength: 3, reg: z2kk, asm: "ZCMPEQ", commutative: true, typ: "Mask"}, diff --git a/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go b/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go index 0a1253a0aa5573..81d205033c28d8 100644 --- a/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go +++ b/src/cmd/compile/internal/ssa/_gen/simdgenericOps.go @@ -121,27 +121,35 @@ func simdGenericOps() []opData { {name: "AndInt64x2", argLength: 2, commutative: true}, // ARCH:amd64,arm64,wasm {name: "AndInt64x4", argLength: 2, commutative: true}, // ARCH:amd64 {name: "AndInt64x8", argLength: 2, commutative: true}, // ARCH:amd64 + {name: "AndNotInt8s", argLength: 2}, // ARCH:sve {name: "AndNotInt8x16", argLength: 2}, // ARCH:amd64,arm64,wasm {name: "AndNotInt8x32", argLength: 2}, // ARCH:amd64 {name: "AndNotInt8x64", argLength: 2}, // ARCH:amd64 + {name: "AndNotInt16s", argLength: 2}, // ARCH:sve {name: "AndNotInt16x8", argLength: 2}, // ARCH:amd64,arm64,wasm {name: "AndNotInt16x16", argLength: 2}, // ARCH:amd64 {name: "AndNotInt16x32", argLength: 2}, // ARCH:amd64 + {name: "AndNotInt32s", argLength: 2}, // ARCH:sve {name: "AndNotInt32x4", argLength: 2}, // ARCH:amd64,arm64,wasm {name: "AndNotInt32x8", argLength: 2}, // ARCH:amd64 {name: "AndNotInt32x16", argLength: 2}, // ARCH:amd64 + {name: "AndNotInt64s", argLength: 2}, // ARCH:sve {name: "AndNotInt64x2", argLength: 2}, // ARCH:amd64,arm64,wasm {name: "AndNotInt64x4", argLength: 2}, // ARCH:amd64 {name: "AndNotInt64x8", argLength: 2}, // ARCH:amd64 + {name: "AndNotUint8s", argLength: 2}, // ARCH:sve {name: "AndNotUint8x16", argLength: 2}, // ARCH:amd64,arm64,wasm {name: "AndNotUint8x32", argLength: 2}, // ARCH:amd64 {name: "AndNotUint8x64", argLength: 2}, // ARCH:amd64 + {name: "AndNotUint16s", argLength: 2}, // ARCH:sve {name: "AndNotUint16x8", argLength: 2}, // ARCH:amd64,arm64,wasm {name: "AndNotUint16x16", argLength: 2}, // ARCH:amd64 {name: "AndNotUint16x32", argLength: 2}, // ARCH:amd64 + {name: "AndNotUint32s", argLength: 2}, // ARCH:sve {name: "AndNotUint32x4", argLength: 2}, // ARCH:amd64,arm64,wasm {name: "AndNotUint32x8", argLength: 2}, // ARCH:amd64 {name: "AndNotUint32x16", argLength: 2}, // ARCH:amd64 + {name: "AndNotUint64s", argLength: 2}, // ARCH:sve {name: "AndNotUint64x2", argLength: 2}, // ARCH:amd64,arm64,wasm {name: "AndNotUint64x4", argLength: 2}, // ARCH:amd64 {name: "AndNotUint64x8", argLength: 2}, // ARCH:amd64 diff --git a/src/cmd/compile/internal/ssa/ssaop/opGen.go b/src/cmd/compile/internal/ssa/ssaop/opGen.go index 7336d86acbf7ad..f5055e6fa72772 100644 --- a/src/cmd/compile/internal/ssa/ssaop/opGen.go +++ b/src/cmd/compile/internal/ssa/ssaop/opGen.go @@ -5069,6 +5069,11 @@ const ( OpARM64ZANDMergingPrefixedH OpARM64ZANDMergingPrefixedS OpARM64ZANDMergingS + OpARM64ZBICD + OpARM64ZBICMergingB + OpARM64ZBICMergingD + OpARM64ZBICMergingH + OpARM64ZBICMergingS OpARM64ZCMPEQB OpARM64ZCMPEQD OpARM64ZCMPEQH @@ -7241,27 +7246,35 @@ const ( OpAndInt8x16 OpAndInt8x32 OpAndInt8x64 + OpAndNotInt16s OpAndNotInt16x16 OpAndNotInt16x32 OpAndNotInt16x8 + OpAndNotInt32s OpAndNotInt32x16 OpAndNotInt32x4 OpAndNotInt32x8 + OpAndNotInt64s OpAndNotInt64x2 OpAndNotInt64x4 OpAndNotInt64x8 + OpAndNotInt8s OpAndNotInt8x16 OpAndNotInt8x32 OpAndNotInt8x64 + OpAndNotUint16s OpAndNotUint16x16 OpAndNotUint16x32 OpAndNotUint16x8 + OpAndNotUint32s OpAndNotUint32x16 OpAndNotUint32x4 OpAndNotUint32x8 + OpAndNotUint64s OpAndNotUint64x2 OpAndNotUint64x4 OpAndNotUint64x8 + OpAndNotUint8s OpAndNotUint8x16 OpAndNotUint8x32 OpAndNotUint8x64 @@ -86356,6 +86369,84 @@ var OpcodeTable = [...]OpInfo{ }, }, }, + { + Name: "ZBICD", + ArgLen: 2, + asm: arm64.AZBIC, + Reg: RegInfo{ + Inputs: []InputInfo{ + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + Outputs: []OutputInfo{ + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, + { + Name: "ZBICMergingB", + ArgLen: 3, + ResultInArg0: true, + asm: arm64.AZBIC, + Reg: RegInfo{ + Inputs: []InputInfo{ + {2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15 + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + Outputs: []OutputInfo{ + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, + { + Name: "ZBICMergingD", + ArgLen: 3, + ResultInArg0: true, + asm: arm64.AZBIC, + Reg: RegInfo{ + Inputs: []InputInfo{ + {2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15 + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + Outputs: []OutputInfo{ + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, + { + Name: "ZBICMergingH", + ArgLen: 3, + ResultInArg0: true, + asm: arm64.AZBIC, + Reg: RegInfo{ + Inputs: []InputInfo{ + {2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15 + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + Outputs: []OutputInfo{ + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, + { + Name: "ZBICMergingS", + ArgLen: 3, + ResultInArg0: true, + asm: arm64.AZBIC, + Reg: RegInfo{ + Inputs: []InputInfo{ + {2, RegMask{V1: 9223372036854775808, V2: 32767}}, // P0 P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15 + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + {1, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + Outputs: []OutputInfo{ + {0, RegMask{V1: 9223372034707292160, V2: 0}}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31 + }, + }, + }, { Name: "ZCMPEQB", ArgLen: 3, @@ -112604,6 +112695,11 @@ var OpcodeTable = [...]OpInfo{ Commutative: true, Generic: true, }, + { + Name: "AndNotInt16s", + ArgLen: 2, + Generic: true, + }, { Name: "AndNotInt16x16", ArgLen: 2, @@ -112619,6 +112715,11 @@ var OpcodeTable = [...]OpInfo{ ArgLen: 2, Generic: true, }, + { + Name: "AndNotInt32s", + ArgLen: 2, + Generic: true, + }, { Name: "AndNotInt32x16", ArgLen: 2, @@ -112634,6 +112735,11 @@ var OpcodeTable = [...]OpInfo{ ArgLen: 2, Generic: true, }, + { + Name: "AndNotInt64s", + ArgLen: 2, + Generic: true, + }, { Name: "AndNotInt64x2", ArgLen: 2, @@ -112649,6 +112755,11 @@ var OpcodeTable = [...]OpInfo{ ArgLen: 2, Generic: true, }, + { + Name: "AndNotInt8s", + ArgLen: 2, + Generic: true, + }, { Name: "AndNotInt8x16", ArgLen: 2, @@ -112664,6 +112775,11 @@ var OpcodeTable = [...]OpInfo{ ArgLen: 2, Generic: true, }, + { + Name: "AndNotUint16s", + ArgLen: 2, + Generic: true, + }, { Name: "AndNotUint16x16", ArgLen: 2, @@ -112679,6 +112795,11 @@ var OpcodeTable = [...]OpInfo{ ArgLen: 2, Generic: true, }, + { + Name: "AndNotUint32s", + ArgLen: 2, + Generic: true, + }, { Name: "AndNotUint32x16", ArgLen: 2, @@ -112694,6 +112815,11 @@ var OpcodeTable = [...]OpInfo{ ArgLen: 2, Generic: true, }, + { + Name: "AndNotUint64s", + ArgLen: 2, + Generic: true, + }, { Name: "AndNotUint64x2", ArgLen: 2, @@ -112709,6 +112835,11 @@ var OpcodeTable = [...]OpInfo{ ArgLen: 2, Generic: true, }, + { + Name: "AndNotUint8s", + ArgLen: 2, + Generic: true, + }, { Name: "AndNotUint8x16", ArgLen: 2, diff --git a/src/cmd/compile/internal/ssagen/simdARM64SVEintrinsics.go b/src/cmd/compile/internal/ssagen/simdARM64SVEintrinsics.go index d742bda5e3961a..06b0c3a0645226 100644 --- a/src/cmd/compile/internal/ssagen/simdARM64SVEintrinsics.go +++ b/src/cmd/compile/internal/ssagen/simdARM64SVEintrinsics.go @@ -43,6 +43,14 @@ func simdARM64SVEIntrinsics(addF func(pkg, fn string, b intrinsicBuilder, archFa addF(simdPackage, "Uint16s.And", opLen2(ssaop.OpAndUint16s, types.TypeVec256), sys.ARM64) addF(simdPackage, "Uint32s.And", opLen2(ssaop.OpAndUint32s, types.TypeVec256), sys.ARM64) addF(simdPackage, "Uint64s.And", opLen2(ssaop.OpAndUint64s, types.TypeVec256), sys.ARM64) + addF(simdPackage, "Int8s.AndNot", opLen2(ssaop.OpAndNotInt8s, types.TypeVec256), sys.ARM64) + addF(simdPackage, "Int16s.AndNot", opLen2(ssaop.OpAndNotInt16s, types.TypeVec256), sys.ARM64) + addF(simdPackage, "Int32s.AndNot", opLen2(ssaop.OpAndNotInt32s, types.TypeVec256), sys.ARM64) + addF(simdPackage, "Int64s.AndNot", opLen2(ssaop.OpAndNotInt64s, types.TypeVec256), sys.ARM64) + addF(simdPackage, "Uint8s.AndNot", opLen2(ssaop.OpAndNotUint8s, types.TypeVec256), sys.ARM64) + addF(simdPackage, "Uint16s.AndNot", opLen2(ssaop.OpAndNotUint16s, types.TypeVec256), sys.ARM64) + addF(simdPackage, "Uint32s.AndNot", opLen2(ssaop.OpAndNotUint32s, types.TypeVec256), sys.ARM64) + addF(simdPackage, "Uint64s.AndNot", opLen2(ssaop.OpAndNotUint64s, types.TypeVec256), sys.ARM64) addF(simdPackage, "Float32s.Ceil", opLen1(ssaop.OpCeilFloat32s, types.TypeVec256), sys.ARM64) addF(simdPackage, "Float64s.Ceil", opLen1(ssaop.OpCeilFloat64s, types.TypeVec256), sys.ARM64) addF(simdPackage, "Float32s.Equal", opLen2(ssaop.OpEqualFloat32s, types.TypeMask), sys.ARM64) diff --git a/src/cmd/compile/internal/ssarewrite/rewritearm64/rewriteARM64.go b/src/cmd/compile/internal/ssarewrite/rewritearm64/rewriteARM64.go index 3f7aa57bc22fb2..f56d229d482fe6 100644 --- a/src/cmd/compile/internal/ssarewrite/rewritearm64/rewriteARM64.go +++ b/src/cmd/compile/internal/ssarewrite/rewritearm64/rewriteARM64.go @@ -730,27 +730,51 @@ func RewriteValue(v *ssa.Value) bool { case ssaop.OpAndInt8x16: v.Op = ssaop.OpARM64VAND16B return true + case ssaop.OpAndNotInt16s: + v.Op = ssaop.OpARM64ZBICD + return true case ssaop.OpAndNotInt16x8: v.Op = ssaop.OpARM64VBIC16B return true + case ssaop.OpAndNotInt32s: + v.Op = ssaop.OpARM64ZBICD + return true case ssaop.OpAndNotInt32x4: v.Op = ssaop.OpARM64VBIC16B return true + case ssaop.OpAndNotInt64s: + v.Op = ssaop.OpARM64ZBICD + return true case ssaop.OpAndNotInt64x2: v.Op = ssaop.OpARM64VBIC16B return true + case ssaop.OpAndNotInt8s: + v.Op = ssaop.OpARM64ZBICD + return true case ssaop.OpAndNotInt8x16: v.Op = ssaop.OpARM64VBIC16B return true + case ssaop.OpAndNotUint16s: + v.Op = ssaop.OpARM64ZBICD + return true case ssaop.OpAndNotUint16x8: v.Op = ssaop.OpARM64VBIC16B return true + case ssaop.OpAndNotUint32s: + v.Op = ssaop.OpARM64ZBICD + return true case ssaop.OpAndNotUint32x4: v.Op = ssaop.OpARM64VBIC16B return true + case ssaop.OpAndNotUint64s: + v.Op = ssaop.OpARM64ZBICD + return true case ssaop.OpAndNotUint64x2: v.Op = ssaop.OpARM64VBIC16B return true + case ssaop.OpAndNotUint8s: + v.Op = ssaop.OpARM64ZBICD + return true case ssaop.OpAndNotUint8x16: v.Op = ssaop.OpARM64VBIC16B return true @@ -20233,6 +20257,22 @@ func rewriteValue_OpARM64ZSELB(v *ssa.Value) bool { v.AddArg4(z, x, y, mask) return true } + // match: (ZSELB (ZBICD x y) x mask) + // result: (ZBICMergingB x y mask) + for { + if v_0.Op != ssaop.OpARM64ZBICD { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 { + break + } + mask := v_2 + v.Reset(ssaop.OpARM64ZBICMergingB) + v.AddArg3(x, y, mask) + return true + } // match: (ZSELB (ZEORD x y) x mask) // result: (ZEORMergingB x y mask) for { @@ -20697,6 +20737,22 @@ func rewriteValue_OpARM64ZSELD(v *ssa.Value) bool { v.AddArg4(z, x, y, mask) return true } + // match: (ZSELD (ZBICD x y) x mask) + // result: (ZBICMergingD x y mask) + for { + if v_0.Op != ssaop.OpARM64ZBICD { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 { + break + } + mask := v_2 + v.Reset(ssaop.OpARM64ZBICMergingD) + v.AddArg3(x, y, mask) + return true + } // match: (ZSELD (ZEORD x y) x mask) // result: (ZEORMergingD x y mask) for { @@ -21328,6 +21384,22 @@ func rewriteValue_OpARM64ZSELH(v *ssa.Value) bool { v.AddArg4(z, x, y, mask) return true } + // match: (ZSELH (ZBICD x y) x mask) + // result: (ZBICMergingH x y mask) + for { + if v_0.Op != ssaop.OpARM64ZBICD { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 { + break + } + mask := v_2 + v.Reset(ssaop.OpARM64ZBICMergingH) + v.AddArg3(x, y, mask) + return true + } // match: (ZSELH (ZEORD x y) x mask) // result: (ZEORMergingH x y mask) for { @@ -21792,6 +21864,22 @@ func rewriteValue_OpARM64ZSELS(v *ssa.Value) bool { v.AddArg4(z, x, y, mask) return true } + // match: (ZSELS (ZBICD x y) x mask) + // result: (ZBICMergingS x y mask) + for { + if v_0.Op != ssaop.OpARM64ZBICD { + break + } + y := v_0.Args[1] + x := v_0.Args[0] + if x != v_1 { + break + } + mask := v_2 + v.Reset(ssaop.OpARM64ZBICMergingS) + v.AddArg3(x, y, mask) + return true + } // match: (ZSELS (ZEORD x y) x mask) // result: (ZEORMergingS x y mask) for { diff --git a/src/cmd/compile/internal/types2/importer_test.go b/src/cmd/compile/internal/types2/importer_test.go index ee4d978639bc33..381aed0329d4bd 100644 --- a/src/cmd/compile/internal/types2/importer_test.go +++ b/src/cmd/compile/internal/types2/importer_test.go @@ -2,35 +2,15 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This file implements the plumbing to get importing to work. - package types2_test import ( - "cmd/compile/internal/importer" + "cmd/compile/internal/testimporter" "cmd/compile/internal/types2" - "io" ) -// TODO(mark): Switch to use new types2 importer. -func defaultImporter() types2.Importer { - return &gcimports{ - packages: make(map[string]*types2.Package), - } -} - -type gcimports struct { - packages map[string]*types2.Package - lookup func(path string) (io.ReadCloser, error) -} - -func (m *gcimports) Import(path string) (*types2.Package, error) { - return m.ImportFrom(path, "" /* no vendoring */, 0) -} +var imp = testimporter.NewImporter() -func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*types2.Package, error) { - if mode != 0 { - panic("mode must be 0") - } - return importer.Import(m.packages, path, srcDir, m.lookup) +func defaultImporter() types2.Importer { + return imp } diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index cf2d580b71b7b2..56e41a398b0622 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -88,6 +88,7 @@ var ARM64 struct { HasSB bool IsNeoverse bool HasSVE bool + HasSVE2 bool _ CacheLinePad } diff --git a/src/internal/cpu/cpu_arm64_hwcap.go b/src/internal/cpu/cpu_arm64_hwcap.go index a0ef5ec68f70d3..869335884d0745 100644 --- a/src/internal/cpu/cpu_arm64_hwcap.go +++ b/src/internal/cpu/cpu_arm64_hwcap.go @@ -21,6 +21,10 @@ import _ "unsafe" // for linkname //go:linkname HWCap var HWCap uint +// HWCap2 may be initialized by archauxv and +// should not be changed after it was initialized. +var HWCap2 uint + // HWCAP bits. These are exposed by Linux. // See arch/arm64/include/uapi/asm/hwcap.h. const ( @@ -36,6 +40,8 @@ const ( hwcap_SVE = 1 << 22 hwcap_DIT = 1 << 24 hwcap_SB = 1 << 29 + + hwcap2_SVE2 = 1 << 1 ) func hwcapInit(os string) { @@ -54,6 +60,7 @@ func hwcapInit(os string) { ARM64.HasDIT = isSet(HWCap, hwcap_DIT) ARM64.HasSB = isSet(HWCap, hwcap_SB) ARM64.HasSVE = isSet(HWCap, hwcap_SVE) + ARM64.HasSVE2 = isSet(HWCap2, hwcap2_SVE2) // The Samsung S9+ kernel reports support for atomics, but not all cores // actually support them, resulting in SIGILL. See issue #28431. diff --git a/src/runtime/iface.go b/src/runtime/iface.go index 6385d1c9d055b1..9f1914372e7194 100644 --- a/src/runtime/iface.go +++ b/src/runtime/iface.go @@ -174,11 +174,11 @@ func (t *itabTableType) add(m *itab) { for i := uintptr(1); ; i++ { p := (**itab)(add(unsafe.Pointer(&t.entries), h*goarch.PtrSize)) m2 := *p - if m2 == m { - // A given itab may be used in more than one module - // and thanks to the way global symbol resolution works, the - // pointed-to itab may already have been inserted into the - // global 'hash'. + if m2 != nil && m2.Inter == m.Inter && m2.Type == m.Type { + // A plugin has its own copy of the itabs that the main program + // also has. Type switches and type assertions compare against + // the itab that is already in the table, so don't add a second + // itab for the same interface/type pair. return } if m2 == nil { diff --git a/src/runtime/os_linux_arm64.go b/src/runtime/os_linux_arm64.go index ccfb92f8ebdacd..44d5e6f0e16d8a 100644 --- a/src/runtime/os_linux_arm64.go +++ b/src/runtime/os_linux_arm64.go @@ -12,6 +12,8 @@ func archauxv(tag, val uintptr) { switch tag { case _AT_HWCAP: cpu.HWCap = uint(val) + case _AT_HWCAP2: + cpu.HWCap2 = uint(val) } } diff --git a/src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/go_sve.yaml b/src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/go_sve.yaml index db866f54d5d967..302386562b57ba 100644 --- a/src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/go_sve.yaml +++ b/src/simd/archsimd/_gen/simdgen/ops/BitwiseLogic/go_sve.yaml @@ -55,3 +55,20 @@ - *uint out: - *uint + +# AndNot — bitwise x &^ y, ZBIC. Width-agnostic like ZAND. +- go: AndNot + asm: "ZBIC" + in: + - *int + - *int + out: + - *int + +- go: AndNot + asm: "ZBIC" + in: + - *uint + - *uint + out: + - *uint diff --git a/src/simd/archsimd/cpu_other.go b/src/simd/archsimd/cpu_other.go index ae98fa3d1f54ca..cc68df709389fc 100644 --- a/src/simd/archsimd/cpu_other.go +++ b/src/simd/archsimd/cpu_other.go @@ -23,3 +23,8 @@ func (ARM64Features) PMULL() bool { func (ARM64Features) SVE() bool { return cpu.ARM64.HasSVE } + +// SVE2 returns whether the CPU supports the SVE2 extension. +func (ARM64Features) SVE2() bool { + return cpu.ARM64.HasSVE2 +} diff --git a/src/simd/archsimd/internal/simd_test/binary_sve_arm64_test.go b/src/simd/archsimd/internal/simd_test/binary_sve_arm64_test.go index 40dd55e4f67b26..d4e3cf14a8a406 100644 --- a/src/simd/archsimd/internal/simd_test/binary_sve_arm64_test.go +++ b/src/simd/archsimd/internal/simd_test/binary_sve_arm64_test.go @@ -321,3 +321,17 @@ func TestXorSVE(t *testing.T) { } testInt8sBinary(t, archsimd.Int8s.Xor, xorInt8) } + +func TestAndNotSVE(t *testing.T) { + if !archsimd.ARM64.SVE() { + t.Skip("no SVE") + } + andNotInt8 := func(x, y []int8) []int8 { + r := make([]int8, len(x)) + for i := range x { + r[i] = x[i] &^ y[i] + } + return r + } + testInt8sBinary(t, archsimd.Int8s.AndNot, andNotInt8) +} diff --git a/src/simd/archsimd/ops_sve.go b/src/simd/archsimd/ops_sve.go index 1a5f75d18eabb6..9004f6ac2b2f97 100644 --- a/src/simd/archsimd/ops_sve.go +++ b/src/simd/archsimd/ops_sve.go @@ -172,6 +172,48 @@ func (x Uint32s) And(y Uint32s) Uint32s // Asm: ZAND, CPU Feature: SVE func (x Uint64s) And(y Uint64s) Uint64s +/* AndNot */ + +// AndNot performs a bitwise x &^ y. +// +// Asm: ZBIC, CPU Feature: SVE +func (x Int8s) AndNot(y Int8s) Int8s + +// AndNot performs a bitwise x &^ y. +// +// Asm: ZBIC, CPU Feature: SVE +func (x Int16s) AndNot(y Int16s) Int16s + +// AndNot performs a bitwise x &^ y. +// +// Asm: ZBIC, CPU Feature: SVE +func (x Int32s) AndNot(y Int32s) Int32s + +// AndNot performs a bitwise x &^ y. +// +// Asm: ZBIC, CPU Feature: SVE +func (x Int64s) AndNot(y Int64s) Int64s + +// AndNot performs a bitwise x &^ y. +// +// Asm: ZBIC, CPU Feature: SVE +func (x Uint8s) AndNot(y Uint8s) Uint8s + +// AndNot performs a bitwise x &^ y. +// +// Asm: ZBIC, CPU Feature: SVE +func (x Uint16s) AndNot(y Uint16s) Uint16s + +// AndNot performs a bitwise x &^ y. +// +// Asm: ZBIC, CPU Feature: SVE +func (x Uint32s) AndNot(y Uint32s) Uint32s + +// AndNot performs a bitwise x &^ y. +// +// Asm: ZBIC, CPU Feature: SVE +func (x Uint64s) AndNot(y Uint64s) Uint64s + /* Ceil */ // Ceil rounds elements up to the nearest integer.